PostgreSQL: GitHub Actions y GitLab CI

Inicie un servicio real de PostgreSQL desde su pipeline de GitHub Actions o GitLab CI, ejecute sus pruebas sobre él y elimínelo automáticamente

👋 ¡Bienvenido a la documentación de Stackhero!

Stackhero ofrece una solución nube PostgreSQL lista para usar que proporciona una serie de beneficios, incluyendo:

  • Conexiones y transferencias de datos ilimitadas.
  • Interfaz web PgAdmin incluida.
  • Muchos módulos incluidos como PostGIS, TimescaleDB y PgVector.
  • Actualizaciones sin esfuerzo con solo un clic.
  • Rendimiento óptimo y seguridad robusta impulsada por una VM privada y dedicada.

Ahorre tiempo y simplifique su vida: ¡solo toma 5 minutos probar la solución de nube hosting PostgreSQL de Stackhero!

Esta guía le mostrará cómo ejecutar un servicio real y dedicado de PostgreSQL dentro de su pipeline de CI utilizando GitHub Actions o GitLab CI. Siguiendo estos pasos, podrá probar su código contra una instancia activa de PostgreSQL en condiciones similares a producción, sin depender de mocks o simulaciones. PostgreSQL is a powerful, open source object-relational SQL database that your app can rely on in production.

Cada vez que se ejecute su pipeline, obtendrá una nueva instancia de PostgreSQL. Esto significa que sus pruebas interactúan con el mismo tipo de servicio que verán sus usuarios en producción. El workflow crea automáticamente una stack temporal, añade PostgreSQL, espera a que esté listo, recupera las credenciales generadas, ejecuta una prueba básica (smoke test) usando psql y, al finalizar, limpia siempre todos los recursos utilizados.

Utilizará la Stackhero CLI, una herramienta de línea de comandos independiente que facilita el despliegue y la gestión de servicios Stackhero de forma rápida y sencilla.

Para que la CLI funcione de forma no interactiva, necesitará un access token (formato: usr-xxxxxx:tokenId). Solo tiene que crear este token una vez y añadirlo a su pipeline de CI como un secreto seguro y cifrado.

  1. Cree el token: En su panel de Stackhero, haga clic en su foto de perfil en la parte superior derecha, vaya a Su cuenta, luego a Access tokens y haga clic en Crear token.
  2. Para GitHub Actions: En su repositorio, vaya a Settings > Secrets and variables > Actions > New repository secret e introduzca el token como STACKHERO_TOKEN.
  3. Para GitLab CI: En su proyecto, vaya a Settings > CI/CD > Variables > Add variable, establezca la clave como STACKHERO_TOKEN y marque Masked (y Protected si su CI solo se ejecuta en ramas protegidas).

No incluya nunca su access token directamente en el archivo YAML del pipeline. Si está presente en el YAML, podría ser expuesto a cualquier persona con acceso al repositorio y aparecer en los logs de compilación. Guardarlo como secreto de CI garantiza que permanezca cifrado y oculto, manteniendo su token seguro.

A continuación, tiene un ejemplo completo de script que gestiona todo el ciclo de vida del servicio. Demuestra lo sencillo que es el proceso, con solo unos pocos comandos. Puede copiar el YAML listo para su plataforma desde las secciones siguientes.

#!/bin/bash
set -euo pipefail

# STACKHERO_TOKEN lo proporciona el secreto de CI, la CLI lo detecta automáticamente.

stackName="ci-postgresql-$$"          # Nombre de stack único para cada ejecución
serviceStore="postgresql"             # El store del servicio PostgreSQL
instance="10G"        # Modifique si es necesario (ver paso 3)
region="europe"                         # Nombre de la región (ver stackhero regions-list)

# 1. Instalar la CLI en el runner
curl -fsSL https://www.stackhero.io/install.sh | sh

# 2. Instalar el cliente necesario para el smoke test (jq + curl son la base)
apt-get update && apt-get install -y --no-install-recommends jq curl postgresql-client

# 3. Crear una stack dedicada para esta ejecución
stackId=$(stackhero --format=script stack-create --name="$stackName")
echo "Stack creada: $stackId"

# 4. Añadir PostgreSQL y capturar su service id
serviceId=$(stackhero --format=script service-add \
  --stack="$stackId" \
  --service-store="$serviceStore" \
  --instance="$instance" \
  --region="$region")
echo "Servicio añadido: $serviceId"

# 5. Esperar a que el servicio esté operativo (puede tardar unos minutos)
stackhero service-wait-for --service="$serviceId"

# 6. Leer la configuración (contiene las credenciales generadas)
config=$(stackhero service-configuration-get --service="$serviceId" --format=json)

# 7. Extraer las credenciales necesarias
host=$(echo "$config" | jq -r '.configuration.domain')
password=$(echo "$config" | jq -r '.configuration.password')

# 8. Smoke test: Run a trivial query against the database.
PGPASSWORD="$password" psql "host=$host port=5432 user=admin dbname=admin sslmode=require" -c "SELECT 1;"

echo "✅ PostgreSQL es accesible desde CI."

El paso de eliminación, que borra el servicio, espera a que se elimine y luego borra la stack, se detalla en las secciones específicas de cada plataforma más abajo. Este enfoque garantiza que la limpieza siempre se realice, incluso si falla el smoke test.

Una stack solo puede eliminarse cuando está vacía. Elimine siempre primero el servicio y espere a que se borre antes de eliminar la stack. El comando service-wait-for asegura que el servicio esté en ejecución o eliminado antes de continuar, por lo que es la herramienta adecuada para esperar la eliminación.

Los ejemplos siguientes utilizan por defecto la instancia de entrada 10G para PostgreSQL. Es una opción fiable para la mayoría de los casos, pero puede ajustarla según sus necesidades. Para ver todos los tipos de instancia disponibles para PostgreSQL, puede ejecutar:

# La columna NAME muestra el valor que debe pasar a --instance
stackhero instances-store-list --service-store=postgresql

Para empezar, guarde el siguiente contenido como .github/workflows/ci.yml. A partir de ahora, cada push y pull request ejecutará pruebas contra una instancia real de PostgreSQL.

name: CI con PostgreSQL

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    env:
      STACKHERO_TOKEN: ${{ secrets.STACKHERO_TOKEN }}
      STACK_NAME: ci-postgresql-${{ github.run_id }}-${{ github.run_attempt }}
      INSTANCE: "10G"   # Modifique si es necesario (ver paso 3)
      REGION: europe
    steps:
      - uses: actions/checkout@v4

      - name: Instalar Stackhero CLI y el cliente
        run: |
          curl -fsSL https://www.stackhero.io/install.sh | sh
          apt-get update && apt-get install -y --no-install-recommends jq curl postgresql-client

      - name: Crear el servicio PostgreSQL
        run: |
          set -euo pipefail
          STACK_ID=$(stackhero --format=script stack-create --name="$STACK_NAME")
          echo "STACK_ID=$STACK_ID" >> "$GITHUB_ENV"
          SERVICE_ID=$(stackhero --format=script service-add \
            --stack="$STACK_ID" \
            --service-store="postgresql" \
            --instance="$INSTANCE" \
            --region="$REGION")
          echo "SERVICE_ID=$SERVICE_ID" >> "$GITHUB_ENV"
          stackhero service-wait-for --service="$SERVICE_ID"

      - name: Ejecutar pruebas sobre PostgreSQL
        run: |
          set -euo pipefail
          config=$(stackhero service-configuration-get --service="$SERVICE_ID" --format=json)
          host=$(echo "$config" | jq -r '.configuration.domain')
password=$(echo "$config" | jq -r '.configuration.password')
          # Run a trivial query against the database.
          PGPASSWORD="$password" psql "host=$host port=5432 user=admin dbname=admin sslmode=require" -c "SELECT 1;"
          echo "✅ PostgreSQL es accesible desde CI."
          # Puede ejecutar su propia batería de pruebas aquí usando las credenciales anteriores ...

      - name: Eliminación (siempre, incluso en caso de fallo)
        if: always()
        run: |
          if [ -n "${SERVICE_ID:-}" ]; then
            stackhero service-delete --service="$SERVICE_ID" --confirm
            stackhero service-wait-for --service="$SERVICE_ID"
          fi
          if [ -n "${STACK_ID:-}" ]; then
            stackhero stack-delete --stack="$STACK_ID" --confirm
          fi

El paso de eliminación está configurado con if: always() para que se ejecute siempre, asegurando que su instancia de PostgreSQL se borre y no se le facture por recursos no utilizados.

Puede guardar esta configuración como .gitlab-ci.yml. Con esta configuración, cada ejecución del pipeline crea una nueva instancia real de PostgreSQL para sus pruebas.

test:
  image: ubuntu:24.04
  variables:
    STACK_NAME: "ci-postgresql-$CI_PIPELINE_ID-$CI_JOB_ID"
    INSTANCE: "10G"   # Modifique si es necesario (ver paso 3)
    REGION: "europe"
    SERVICE_STORE: "postgresql"
  # STACKHERO_TOKEN proviene de la variable CI/CD creada en el paso 1.
  script:
    - set -euo pipefail
    - curl -fsSL https://www.stackhero.io/install.sh | sh
    - apt-get update && apt-get install -y --no-install-recommends jq curl postgresql-client
    - STACK_ID=$(stackhero --format=script stack-create --name="$STACK_NAME")
    - echo "STACK_ID=$STACK_ID" >> deploy.env
    - SERVICE_ID=$(stackhero --format=script service-add --stack="$STACK_ID" --service-store="$SERVICE_STORE" --instance="$INSTANCE" --region="$REGION")
    - echo "SERVICE_ID=$SERVICE_ID" >> deploy.env
    - stackhero service-wait-for --service="$SERVICE_ID"
    - config=$(stackhero service-configuration-get --service="$SERVICE_ID" --format=json)
    - host=$(echo "$config" | jq -r '.configuration.domain')
password=$(echo "$config" | jq -r '.configuration.password')
    # Run a trivial query against the database.
    - PGPASSWORD="$password" psql "host=$host port=5432 user=admin dbname=admin sslmode=require" -c "SELECT 1;"
    - echo "✅ PostgreSQL es accesible desde CI."
    # Puede ejecutar su propia batería de pruebas aquí usando las credenciales anteriores ...
  after_script:
    - test -f deploy.env && . ./deploy.env || true
    - >
      if [ -n "${SERVICE_ID:-}" ]; then
        stackhero service-delete --service="$SERVICE_ID" --confirm
        stackhero service-wait-for --service="$SERVICE_ID"
      fi
    - >
      if [ -n "${STACK_ID:-}" ]; then
        stackhero stack-delete --stack="$STACK_ID" --confirm
      fi

En GitLab, la limpieza se realiza en after_script. Esta sección siempre se ejecuta, incluso si el job falla, por lo que sus recursos de PostgreSQL se eliminan y no se le cobra por recursos que no está utilizando.

En GitLab, after_script se ejecuta en un shell nuevo. Para gestionarlo, el script escribe los IDs del servicio y la stack en deploy.env durante el job y los recarga antes de la eliminación. Así, incluso si algo falla a mitad del job, sus recursos se limpian correctamente.

Ese es el ciclo completo de CI para PostgreSQL: crear una stack, añadir el servicio, esperar, recuperar credenciales, smoke test y siempre eliminar. Cada ejecución del pipeline obtiene un servicio real e independiente, sin dejar nada funcionando al terminar. Para más información sobre los comandos disponibles y la autenticación no interactiva con STACKHERO_TOKEN, puede consultar la documentación completa de la CLI.