SQLcl Projects: referencia práctica para CI/CD en Oracle APEX

Oracle APEX nos permite desarrollar aplicaciones de forma ágil, pero cuando el proyecto crece, o trabajamos en equipo, el control de versiones, la trazabilidad y la automatización del despliegue dejan de ser opcionales. En este contexto, implementar un flujo CI/CD sólido se convierte en una necesidad.

El verdadero reto surge cuando debemos versionar de forma coherente tanto el código de la aplicación APEX como los objetos de base de datos que la soportan. Una aplicación APEX puede exportarse como un único archivo fXXX.sql, pero este formato monolítico dificulta detectar cambios puntuales, aislar funcionalidades o resolver conflictos en un desarrollo colaborativo. Por su parte, objetos como paquetes PL/SQL, vistas, tablas o triggers suelen permanecer dispersos, sin una estructura uniforme ni un control histórico detallado, lo que complica su seguimiento y su despliegue ordenado en diferentes entornos.

Conscientes de esta necesidad, a partir de SQLcl 24.3 (octubre de 2024) Oracle incorporó la funcionalidad Projects, un conjunto de comandos (init, export, stage, release, deploy, entre otros) diseñado específicamente para estructurar y versionar aplicaciones y objetos de base de datos. Desde entonces, la herramienta ha evolucionado —en la versión 25.1 (abril de 2025) se añadió soporte para vistas materializadas y módulos ORDS REST— convirtiéndose en una pieza clave para implementar flujos CI/CD modernos en entornos APEX.

En este post veremos una pequeña introducción sobre cómo estructurar un proyecto APEX usando SQLcl Projects, incluyendo el versionado granular de la aplicación y de los objetos de base de datos, el uso de ramas por funcionalidad, el despliegue entre entornos, y buenas prácticas asociadas a DevSecOps.

Inicialmente, al comenzar a escribir esta entrada, pensé que sería una pequeña referencia al uso de la herramienta, pero poco a poco me di cuenta que podrían aparecer otras piezas causando cierta incertidumbre, por lo que esta entrada ha crecido más de lo esperado. En este punto, espero que tengáis un refresco y un poco de paciencia, y seguro que completáis la lectura de este post con una visión completa de una pieza que se volverá indispensable cuando desarrollemos cualquier app.

CI/CD en entornos low-code: más que posible, necesario

CI/CD (Integración y Entrega Continuas, por sus siglas en inglés) permite integrar cambios de forma frecuente, validarlos automáticamente y desplegarlos de manera segura. Aunque APEX es una plataforma low-code, no está exenta de complejidad: trabajamos con lógica de negocio en PL/SQL, vistas SQL, interfaces APEX, reglas de seguridad y, en muchos casos, con dependencias entre estos elementos. Todo ello requiere un control cuidadoso.

En el caso de APEX, un flujo CI/CD efectivo debe contemplar no solo el ciclo de vida de la aplicación, sino también el de todos los objetos de base de datos que la acompañan. Esto implica versionar de forma granular y automatizar el despliegue de ambos mundos para mantener coherencia entre entornos como DEV, STAGING y PROD.

Adoptar CI/CD en APEX nos aporta beneficios claros:

  • Revisión de cambios en equipo, con control de versiones distribuido.

  • Automatización de despliegues ordenados entre entornos (DEV → STAGING → PROD).

  • Mayor seguridad y trazabilidad, con validaciones y controles previos.

  • Detección temprana de errores o problemas de permisos, gracias a pruebas automatizadas.

Ejemplo de un posible flujo CI/CD con SQLcl Projects

[DEV]
  ├─ Desarrollamos en APEX y PL/SQL
  ├─ Exportamos con SQLcl Projects
  │    ├─ apex export -split
  │    ├─ ddl table / view / package
  └─ Commit en rama de funcionalidad (Git)

       ↓ Pull Request / Merge

[REPOSITORIO GIT]
  ├─ Revisión de código y ficheros exportados
  ├─ Pruebas automáticas (utPLSQL, validaciones)
  └─ Generación de artefacto de despliegue

       ↓ Pipeline CI/CD

[STAGING]
  ├─ sql -project project-staging.json @install.sql
  ├─ Verificación de despliegue y tests funcionales
  └─ Validación de seguridad (DevSecOps)

       ↓ Aprobación

[PROD]
  └─ sql -project project-prod.json @install.sql

En este esquema:

  • DEV es el entorno de desarrollo donde se crean o modifican aplicaciones y objetos de base de datos (si trabajamos en local, o en un entorno compartido, lo dejamos para otro post…)

  • El repositorio Git centraliza cambios, facilita la revisión en equipo y ejecuta pruebas automatizadas.

  • STAGING actúa como entorno intermedio para validar la instalación antes de la liberación definitiva.

  • PROD recibe únicamente cambios validados y aprobados.

Esta secuencia representa un sencillo ejemplo que no solo organiza el proceso de forma ordenada, sino que facilita la trazabilidad, la seguridad y la capacidad de repetir los despliegues de forma sencilla.

¿Qué nos ofrece SQLcl Projects?

Ya se ha mencionado SQLcl varias veces, pero ¿qué es exactamente? Pues, de forma resumida, se trata de una herramienta de línea de comandos gratuita que evoluciona y extiende SQL*Plus, facilitando la exportación estructurada de esquemas (objetos de base de datos) y aplicaciones APEX. Con la funcionalidad Projects podemos:

  • Versionar objetos de base de datos de forma granular.

  • Exportar aplicaciones APEX por componentes.

  • Construir scripts de instalación ordenados.

  • Integrarnos fácilmente con Git, GitHub, GitLab, Jenkins, entre otros.

Estructura típica de un SQLcl Project

Tras ejecutar sql init, obtenemos:

mi-proyecto/
 ├── .dbtools/                   # Configuración interna de SQLcl
 ├── filters/
 │    └── project.filters        # Definición de filtros de exportación
 ├── project.config.json         # Configuración principal del proyecto
 ├── project.sqlformat.xml       # Reglas de formato SQL
 ├── dist/                       # Artefactos generados con 'project release'
 ├── src/
 │    └── database/
 │         └── esquema-bbdd/     # Carpeta base para objetos del esquema
 ├── install.sql                 # Script maestro de instalación (opcional, manual)

Esta estructura nos permite mantener el código separado por tipo de objeto, y preparar un proceso de instalación claro y reproducible.

Ejemplo práctico: desde desarrollo hasta despliegue

Una vez presentados los agentes que intervienen, veamos de forma práctica como poner todo en marcha. Para este ejercicio, vamos a plantear un escenario en el que nunca hemos utilizado ninguna de las herramientas mencionadas, más allá de nuestros desarrollos habituales en oracle APEX.

Prerrequisitos

Antes de comenzar a trabajar con SQLcl Projects para versionar y desplegar aplicaciones APEX y objetos de base de datos, necesitamos preparar nuestro entorno de trabajo. Si ya contáis con SQLcl configurado en vuestro equipo de trabajo, y vuestra conexión con Git correctamente establecida, podéis saltar al punto 1.

Instalar SQLcl

SQLcl es una herramienta de Oracle, disponible para Windows, macOS y Linux. Puede descargarse desde:

https://www.oracle.com/tools/sqlcl/

Pasos recomendados:

  • Descargar la última versión (a partir de 24.3 para contar con la funcionalidad project).

  • Descomprimir el archivo en una carpeta de nuestra elección.

  • Añadir la ruta de bin/ de SQLcl a la variable de entorno PATH para poder ejecutar sql desde cualquier terminal.

Ejemplo (Linux/macOS):

export PATH=$PATH:/ruta/a/sqlcl/bin

Ejemplo (Windows, PowerShell):

setx PATH "$($env:PATH);C:\\ruta\\a\\sqlcl\\bin"

Podemos verificar la instalación ejecutando:

sql -V

Disponer de un repositorio Git

Para controlar versiones de forma profesional, utilizaremos Git como sistema de control de versiones y una plataforma como GitHub o GitLab para alojar el repositorio remoto.

Pasos recomendados:

  • Crear un nuevo repositorio vacío en GitHub o GitLab (en mi caso, y para el ejemplo, utilizaré GitHub).

  • No es necesario clonarlo aún; lo inicializaremos más adelante desde nuestro directorio de proyecto SQLcl.

  • Asegurarnos de tener Git instalado localmente:

      git --version
    

Configurar VS Code para trabajar con Git y SQLcl

Como preferencia personal, me siento muy cómodo trabajando con Visual Studio Code. Esta herramienta, mediante sus extensiones, nos facilita muchas de las tareas diarias relacionadas con desarrollo, control de versiones y conexión con bases de datos.

Para ilustrar este ejemplo, es preciso:

  • Instalar la extensión oficial de GitHub o GitLab, según la plataforma de control de versiones que utilicemos.

  • Verificar que VS Code detecta el comando git, asegurándonos de que Git está correctamente instalado y disponible en la terminal integrada.

  • Instalar una extensión de SQL para mejorar la experiencia al editar scripts (coloreado de sintaxis, autocompletado, ejecución directa). Mi preferencia pasa por usar la extensión oficial de Oracle, Oracle SQL Developer Extension for VS Code, que además permite conectarnos directamente a bases de datos Oracle, ejecutar consultas SQL y scripts, o incluso integrar un servidor MCP (que ya veremos más adelante..).

  • Configurar la terminal integrada para que pueda invocar sql de SQLcl sin necesidad de especificar la ruta completa, añadiendo el directorio bin/ de SQLcl al PATH del sistema.

Conexión a la base de datos

Para poder utilizar SQLcl Projects necesitamos conectividad SQL*Net hacia la base de datos. En este post, por comodidad, realizaremos el ejemplo de desarrollo y versionado usando una Autonomous Database (ADB) de Oracle Cloud, pero el ejercicio puede realizarse del mismo modo utilizando una BBDD local (Oracle XE en Docker, por ejemplo**)** o con una BBDD en la nube/corporativa mediante la configuración oportuna (conexión Usuario/Contraseña, mediante tunel SSH, etc). Además, si no contáis con vuestro entorno de desarrollo propio, podéis solicitar una versión gratuita para lo que necesitéis.

  1. En OCI, descargamos el wallet de la ADB y lo descomprimimos (contiene tnsnames.ora y certificados).

  2. Apuntamos la variable de entorno TNS_ADMIN al directorio del wallet (descomprimido):

    • macOS / Linux:

        export TNS_ADMIN=/ruta/al/wallet
      

      Para dejarlo permanente, tendríamos que añadir este comando a ~/.zshrc o ~/.bashrc.

    • Windows (PowerShell):

      • Para establecerla permanentemente:

          setx TNS_ADMIN "C:\\ruta\\al\\wallet"
        

        (En este punto será necesario abrir una nueva ventana para que se aplique)

      • Para la sesión actual:

          $env:TNS_ADMIN = "C:\\ruta\\al\\wallet"
        
  3. Probamos la conexión con SQLcl (pedirá contraseña):

     sql customers_app@miadb_tp
    
  4. Ya tenemos configurada correctamente y establecida nuestra conexión a la Autonomous Database en Oracle Cloud Infrastructure que usaremos para nuestro desarrollo.

Desarrollo de nuestra aplicación y objetos de base de datos

En este punto, estamos listos para poner todo en marcha. Para ello, supongamos que desarrollamos una aplicación de gestión de clientes. Nuestra aplicación incluye:

  • La propia aplicación APEX (ID 109 en mi Workspace).

  • Una tabla customers.

  • Un paquete PL/SQL customer_api.

Con nuestro todo listo para ser versionado y desplegado en otro entorno, ahora podemos hacer uso de las herramientas que hemos instalado previamente y poner en práctica la parte importante de este post.

Para crear la app y los objetos de base de datos, podemos apoyarnos en QuickSQL y realizar todo a partir de unos cuantos clicks. Os dejo un pequeño enlace con las instrucciones aquí.

1. Inicialización del proyecto

Nota sobre esquemas en Oracle APEX (ADB y otros entornos multiusuario)

Antes de meternos en harina, cabe destacar que en algunos entornos de Oracle APEX —especialmente en Autonomous Database (ADB)— el esquema propietario de la aplicación no siempre es el mismo que el esquema donde residen los objetos de base de datos.

  • Esquema de aplicación: el propietario del workspace APEX donde desarrollamos la app (por ejemplo, MI_ESQUEMA).

  • Esquema de objetos: el que contiene tablas, paquetes, vistas, etc. En entornos ADB multiusuario suele tener prefijo WKSP_ (por ejemplo, WKSP_MI_ESQUEMA).

En este ejemplo asumimos el caso sencillo en el que ambos coinciden, lo que es habitual en entornos de desarrollo individuales o en bases de datos locales.

Si en vuestro caso están separados, será necesario conectarse a cada uno de ellos según el comando que se ejecute:

  • apex export → contra el esquema de aplicación.

  • ddl → contra el esquema de objetos.

Aclarada esta cuestión sobre dónde reside cada cosa, creamos un directorio para nuestro proyecto y lo inicializamos con la funcionalidad Projects de SQLcl (disponible a partir de la versión 24.3). Esto creará automáticamente la estructura base y el archivo project.config.json con la configuración inicial.

  1. En una terminal, o en la terminal de VS Code, ejecutamos:
mkdir sqlcl-projects
cd sqlcl-projects
  1. Conectar con SQLcl al esquema del workspace APEX (o el esquema donde residen los objetos de la app). En este post usamos ADB con TNS_ADMIN ya configurado y nos conectamos a una base de datos llamada juandev:
sql projects_demo@juandev_tp

SQLcl pedirá la contraseña del usuario de base de datos customers_app en la base de datos juandev para continuar.

  1. Ya dentro de SQLcl, inicializar el Project:
project init -name customers-app -schemas PROJECTS_DEMO
  1. Salir de SQLcl (opcional, para seguir editando archivos desde VS Code):
exit

Es importante destacar que el comando project init sólo es necesario la primera vez en un directorio vacío. Si lo ejecutamos de nuevo en el mismo directorio, SQLcl detectará project.config.json y no sobrescribirá la configuración; únicamente verificará/complementará la estructura si faltara alguna carpeta. Esto resulta útil si se ha eliminado algo por error.

Como pequeño extra, para cuando estemos algo más acostumbrados a utilizar la herramienta, los pasos 2 al 4 pueden agruparse del siguiente modo:

sql projects_demo@juandev_tp "project init -name customers-app -schemas PROJECTS_DEMO"

En este punto, el directorio de trabajo ya está listo para continuar con la exportación de la app APEX y de los objetos de base de datos en los siguientes pasos.

2. Exportación inicial con project export

En este ejemplo, la aplicación APEX y los objetos de base de datos residen en el mismo esquema (CUSTOMERS_APP), por lo que un único comando project export puede generar toda la estructura necesaria:

  • Carpeta src/apex/ → aplicación APEX exportada (en algunas versiones, ya en formato dividido split).

  • Carpeta src/database/<ESQUEMA>/ → objetos de base de datos (tablas, vistas, paquetes, etc.) en ficheros DDL separados por tipo.

Aunque esta aproximación “todo en uno” puede resultar cómoda, personalmente prefiero exportar la aplicación y los objetos por separado. Las dos razones principales son:

  1. En la mayoría de los proyectos, la aplicación APEX y los objetos de base de datos no residen en el mismo esquema.

  2. El comando apex export permite forzar siempre el split de la aplicación, asegurando un control de versiones más granular y predecible.

Caso 1 — App y objetos en el mismo esquema

Si queremos hacer todo de una vez, conectados a CUSTOMERS_APP en SQLcl:

project export

Resultado esperado (ejemplo):

src/
  apex/
    customers-app/
      f110.sql
      pages/
      shared_components/
      ...
  database/
    CUSTOMERS_APP/
      tables/
        PD_CUSTOMERS.sql
      packages/
        CUSTOMER_API.pks
        CUSTOMER_API.pkb
      views/
      ...

Nota importante:

project export exportará también la aplicación APEX si reside en el mismo esquema, pero en algunas versiones no lo hará con -split en la primera ejecución. En ejecuciones posteriores, puede aparecer ya dividida, pero este comportamiento no está documentado ni garantizado.

Si queremos asegurar el -split en cualquier circunstancia, lo recomendable es exportar la aplicación con apex export y luego exportar los objetos con project export.

Caso 2 — App y objetos en esquemas separados (o preferencia por exportar separado)

  1. Exportar la aplicación (conexión al esquema propietario de la app APEX):

     apex export -applicationid 110 -split -dir src/apex/customers-app
    
    • -applicationid → ID de la aplicación APEX que vamos a exportar.

    • -split → exporta la aplicación en varios ficheros, facilitando un control de versiones más granular.

    • -dir → ruta donde se guardarán los ficheros exportados (relativa al directorio del proyecto).

  1. Exportar los objetos (conexión al esquema que los contiene):

     project export
    

De esta forma mantenemos control total sobre el formato y el contenido de cada exportación, incluso cuando project export no genere el split de la app por sí solo.

Para siguientes despliegues, no es necesario que usemos project export siempre (esto siempre traería todo lo que haya en el esquema, cuente o no con cambios). Por eso, si se realizan manipulaciones de objetos concretos, pueden usarse comandos como el siguiente, y sql projects se encargará de incorporar los cambios de la tabla en la correspondiente carpeta.

ddl table pd_customers

3. Inicialización del repositorio Git y preparación de ramas

Antes de empaquetar el proyecto para despliegue, es recomendable inicializar un repositorio Git y trabajar en una rama que no sea protegida (como main o master). Esto es especialmente importante si vamos a usar la funcionalidad project stage de SQLcl, que bloquea la ejecución en ramas protegidas - como veremos dentro de un momento.

  1. Inicializar el repositorio (si aún no existe):
git init
  1. Añadir un .gitignore básico para evitar subir artefactos temporales, wallets, etc., si procede:
printf "dist/\\nreleases/\\n.dbtools/\\n*.zip\\n*.p12\\n*.sso\\n*.jks\\n*.ora\\nwallet*/\\n_wallet*/\\n" >> .gitignore
  1. Realizamos nuestro primer commit con la exportación inicial del proyecto:
git add .
git commit -m "Inicialización del proyecto APEX exportado con SQLcl"
  1. Crear y cambiar a una rama no protegida (para trabajar o generar un paquete de despliegue):
# Crea la rama principal 'main'
git checkout -b main
# Crea una rama no protegida para preparar la versión de despliegue
git checkout -b release/v1.0.0
# (Opcional) commit vacío para que haya diferencias con main y SQLcl pueda hacer la comparación
git commit --allow-empty -m "Preparación de la versión v1.0.0 para despliegue"
  1. Verificar que el árbol está limpio antes de usar comandos de empaquetado:
git status
  1. (Opcional) Tras generar el artefacto y validar el despliegue, mergear los cambios a main:
git checkout main
git merge release/v1.0.0
git push origin main

4. Creación del script de instalación

Opción 1. install.sql manual

Aunque project export nos genera todos los scripts de la aplicación y objetos de base de datos organizados por tipo, no crea automáticamente un install.sql.

Este archivo es clave para definir el orden exacto en que se ejecutarán los componentes durante un despliegue, respetando dependencias y posibles pasos adicionales (por ejemplo, datos iniciales, validaciones, tareas previas o posteriores al despliegue).

Un ejemplo de install.sql para nuestro caso podría ser:

@src/database/customers_app/tables/pd_customers.sql
@src/database/customers_app/packages/customer_api.pks
@src/database/customers_app/packages/customer_api.pkb
@src/apex/customers-app/f110.sql

Buenas prácticas para install.sql:

  1. Tablas antes que vistas y paquetes.

  2. Vistas antes que paquetes (si hay dependencias).

  3. Código PL/SQL antes que la aplicación APEX, para que ésta pueda invocar cualquier API desde el primer momento.

  4. Aplicación APEX al final, como último paso del despliegue.

Opción 2. Uso de project stage y project release

Si preferimos no crear manualmente un install.sql, SQLcl ofrece un flujo automático de empaquetado de despliegues usando dos comandos clave:

  1. project stage → genera un conjunto de scripts listos para instalar en un entorno de destino, ordenados según la lógica predefinida de SQLcl.

  2. project release → empaqueta los scripts staged en un archivo comprimido (.zip) o carpeta, listo para ser transportado e instalado en el entorno final.

Ejemplo de uso:

-- Generar la carpeta 'stage' con todos los scripts listos para instalar
project stage

-- Crear un paquete comprimido con la release
project release -version 1.0.0

Ventajas de esta opción:

  • Evita mantener manualmente un install.sql.

  • Estandariza el orden de instalación siguiendo convenciones de SQLcl.

  • Permite empaquetar releases con nombre y versionado.

Inconvenientes:

  • El orden es el que define SQLcl, sin posibilidad de insertar pasos personalizados.

  • Menos flexible si necesitamos lógica específica antes o después de determinados scripts.

  • Necesitamos trabajar correctamente con nuestra herramienta de control de versiones, en una rama no protegida.

5. Control de versiones y subida de cambios a la rama principal

Con la estructura generada por SQLcl Projects ya en el repositorio (carpetas src/, dist/, .dbtools/, etc.), es momento de versionar los cambios y fusionarlos en la rama principal (main).

Antes de entrar en los pasos prácticos, es importante definir un enfoque de trabajo.

5.1. Trabajo por funcionalidades

Para aprovechar todo el potencial de nuestra herramienta de control de versiones, recomendamos un flujo basado en ramas por funcionalidad o por ticket, evitando trabajar directamente en main. Por ejemplo:

git checkout -b feat/JL-001-nuevo-cliente

Este enfoque nos permite:

  • Aislar cambios y facilitar revisiones mediante pull requests.

  • Asignar responsabilidades claras.

  • Controlar con precisión qué cambia y por qué.

Si es la primera vez que sincronizamos el repositorio, podemos hacerlo desde VS Code o línea de comandos:

git init
git add .
git commit -m "Inicialización del proyecto APEX"
git remote add origin <https://gitlab.com/organizacion/apex-ci-project.git>
git push -u origin main

5.2. Subir cambios y mergear a main

Podemos hacerlo desde VS Code (interfaz gráfica) o con Git en línea de comandos.

Opción 1: Con VS Code

  1. Comprobar el estado del repo

    • Abre VS Code en la carpeta del proyecto.

    • Barra lateral → Source Control (Ctrl/Cmd + Shift + G) → verás archivos modificados.

  2. Añadir los cambios

    • Marca los archivos a incluir o pulsa “+” en Changes para pasarlos a Staged Changes.

    • 💡 Pro tip: si has generado carpetas stage/ o release/ temporales, añádelas a .gitignore para evitar “ruido” en los commits.

  3. Hacer commit

    • Escribe un mensaje claro, por ejemplo:

      feat(apex): add install.sql and stage/release workflow

      y pulsa Commit.

  4. Subir a tu rama de trabajo

    • Si ya estabas en tu rama (ej. sqlcl-projects-post), pulsa Sync/Push.

    • Si no existe en remoto, VS Code ofrecerá Publish Branch.

  5. Crear Pull/Merge Request

    • VS Code puede mostrar un banner “Create Pull Request”. Pulsa y completa:

      • Base: main

      • Compare: tu rama (sqlcl-projects-post)

      • Añade descripción breve: qué incluye, cómo probarlo, si afecta a la app APEX 110, etc.

    • Alternativa: crear el PR/MR directamente en GitHub/GitLab.

  6. Revisar y fusionar

    • Una vez aprobado el PR/MR:

      • Tipo de merge recomendado: Squash & Merge (historial limpio) o Merge commit si queréis preservar commits.

      • Confirma el merge hacia main.

  7. Eliminar la rama tras el merge

    • La plataforma suele mostrar Delete branch (remoto).

    • En VS Code, cambia a main y sincroniza. Luego elimina la rama local:

      Paleta (Ctrl/Cmd + Shift + P) → Git: Delete Branch.

ℹ️ Nota: si main está protegida (recomendado), necesitarás PR/MR, revisores y pipeline verde antes del merge.

Opción 2: Con Git (CLI)

Usando la terminal integrada en VS Code:

# 1) Ver estado
git status

# 2) Añadir cambios
git add .

# 3) Commit con mensaje
git commit -m "feat(apex): add install.sql and stage/release workflow"

# 4) Subir a tu rama
git push -u origin sqlcl-projects-post

Crear el PR/MR en GitHub/GitLab (o con gh/glab).

Tras aprobar y mergear:

# 5) Cambiar a main y actualizar
git checkout main
git pull origin main

# 6) Eliminar rama local
git branch -d sqlcl-projects-post

# 7) Eliminar rama remota
git push origin --delete sqlcl-projects-post

5.3. (Opcional) Etiquetar la release

Si hemos creado una release con project release -version 1.0.0 y queremos reflejarla en Git:

git tag v1.0.0
git push origin v1.0.0

En GitHub/GitLab se puede crear además una Release enlazando el tag y adjuntando el .zip generado, o bien referenciando el pipeline de despliegue.

5.4. Buenas prácticas

  • Mensajes de commit con prefijos claros: feat:, fix:, docs:, chore:, ci:.

  • PR/MR con contexto: qué cambia, cómo probarlo (@install.sql en SQLcl o project stage), riesgos y rollback.

  • Ramas protegidas: exigir PR/MR, checks automáticos y al menos un revisor.

  • Squash & Merge para mantener un historial limpio.

  • Tags para releases “desplegables” de SQLcl Projects.

  • .gitignore para artefactos temporales (stage/, release/), logs y ficheros locales.

Despliegue entre entornos (DEV → STAGING)

Con el proyecto ya estructurado y versionado en main, podemos preparar el despliegue a un segundo entorno (por ejemplo, STAGING) usando el install.sql creado en el punto 4 o bien el flujo automático de empaquetado que vimos en la opción 2 de ese mismo apartado.

El objetivo es que el entorno de STAGING quede sincronizado con el contenido aprobado en main, siguiendo siempre un orden de instalación controlado.

1. Usando install.sql manual

Si optamos por mantener nuestro install.sql (creado manualmente y versionado en Git), el despliegue en STAGING se realiza ejecutando el script contra la conexión del entorno de destino:

sql -oci staging_user/staging_pass@staging_host @install.sql

Este método es directo y permite personalizar la secuencia de instalación, pero requiere que nos aseguremos de tener el install.sql actualizado con cada cambio.

2. Usando un archivo de configuración por entorno

Para evitar modificar credenciales en el project.config.json principal, podemos crear un archivo de configuración alternativo, por ejemplo:

project.staging.config.json

{
  "defaultConnection": "staging_user/staging_pass@host:1521/xepdb1",
  "schema": "STAGING_SCHEMA"
}

De esta forma, el despliegue a STAGING sería:

sql -project project.staging.config.json @install.sql

Esto nos permite cambiar de entorno sin editar el archivo principal y es ideal para escenarios multi–entorno o pipelines de CI/CD.

3. Usando el flujo project stage / project install

Si seguimos el flujo automático de SQLcl Projects (explicado en el punto 4. Opción 2):

  1. En DEV, generamos el paquete listo para instalar:

     project stage
     project release -version 1.0.0
    

    Esto creará una carpeta stage/ o un .zip con los scripts ordenados según la lógica interna de SQLcl.

  2. En STAGING, instalamos el paquete con la configuración del entorno:

     sql -project project.staging.config.json
     project install
    

    project install detectará el contenido staged y lo ejecutará respetando el orden predefinido.

4. Buenas prácticas para el despliegue

  • Siempre desplegar desde main o desde un tag de release para asegurar que el código ha pasado por revisión y control de versiones.

  • Separar configuraciones por entorno: project.dev.config.json, project.staging.config.json, project.prod.config.json.

  • Usar variables de entorno en vez de credenciales planas cuando el despliegue se ejecute en pipelines.

  • Versionar install.sql (si se usa) para que forme parte del control de cambios junto con el resto del proyecto.

  • Etiquetar releases en Git (git tag v1.0.0) alineadas con las versiones generadas por project release.

Con este paso, cerramos el flujo completo:

exportación de la aplicación y objetos con SQLcl Projects → creación del script o empaquetado → control de versiones en Git → fusión a main → despliegue a STAGING.

El mismo patrón se puede aplicar para pasar de STAGING a PRODUCCIÓN, añadiendo validaciones, backups y aprobaciones según la política de cada equipo.

Seguridad, validación y DevSecOps

En un flujo CI/CD profesional, la seguridad no es un añadido, sino una parte integral del proceso. Algunas prácticas recomendadas:

  • Evitar commits de contraseñas o credenciales: usar .gitignore, gestores de secretos (HashiCorp Vault, Azure Key Vault, AWS Secrets Manager) o variables de entorno en pipelines.

  • Validar permisos y grants con scripts específicos antes de llegar a entornos superiores.

  • Revisar estructuras sensibles, como triggers, políticas de auditoría o código que pueda impactar la seguridad de datos.

  • Incluir pruebas unitarias PL/SQL con utPLSQL para validar lógica de negocio.

  • Aplicar validaciones previas al despliegue: sintaxis, compilación y tests automatizados.

Ejemplo de verificación básica de sintaxis antes de desplegar:

sql check src/packages/customer_api.pkb

Buenas prácticas adicionales

  • Commits atómicos, uno por funcionalidad o corrección, para facilitar revisión y trazabilidad.

  • Prefijos numéricos en scripts de instalación para garantizar el orden de ejecución:

      01_tables.sql
      02_views.sql
      03_packages.sql
    
  • Mantener objetos separados por tipo (tables/, views/, packages/), evitando scripts monolíticos.

  • Excluir del control de versiones objetos volátiles o del sistema (estadísticas, objetos temporales).

  • Incluir scripts de datos controlados solo cuando sean necesarios (src/data/).

  • Automatizar pruebas y validaciones tras cada push usando pipelines (GitHub Actions, GitLab CI/CD).

Conclusión

Adoptar un enfoque CI/CD en Oracle APEX con SQLcl Projects nos permite controlar y automatizar el ciclo completo de vida de nuestras aplicaciones: desde el desarrollo en DEV, pasando por entornos intermedios como STAGING, hasta la entrega final en PRODUCCIÓN.

A través de una estructura clara, control de versiones preciso y despliegues reproducibles, nos alineamos con prácticas de DevSecOps, donde la seguridad, la validación y la trazabilidad no son pasos opcionales, sino parte del proceso desde el inicio.

SQLcl Projects no es solo una herramienta útil para exportar aplicaciones, sino una pieza clave para quienes buscan un desarrollo APEX moderno, colaborativo y sostenible en el tiempo.

0
Subscribe to my newsletter

Read articles from Juan López García directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Juan López García
Juan López García

I am a technology professional with about a decade of experience in software development, specialising in Oracle APEX. My career began in telecommunications engineering, but my passion for technology and software development led me to transition into this field. Since then, I have been deeply involved in leading teams and driving digital transformation across various projects. As a part of my daily tasks, I focus on fostering collaboration, efficiency, and technical excellence, ensuring that the projects where I'm involved embrace digital advancements effectively. I take great pride in sharing my knowledge and experience, whether through mentorship, conferences, or engaging with the tech community.