OptimoCMSDocs
Guides

Pipeline CI/CD

Automatiza actualizaciones de contenido y publicación con GitHub Actions y el SDK de OptimoCMS. De staging a producción en un solo push.

Pipeline CI/CD con GitHub Actions

Automatiza tu flujo de trabajo OptimoCMS con GitHub Actions. Envía cambios de contenido a un repositorio y deja que el pipeline actualice y publique automáticamente tu sitio.

En este tutorial:

  • Configurar un workflow de GitHub Actions
  • Actualizar contenido vía el SDK en CI
  • Flujo staging (sandbox) → producción
  • Publicación automática al hacer merge a main

Requisitos previos

  • Repositorio GitHub con tu contenido/configuración
  • Clave API de OptimoCMS (almacenada como GitHub Secret)
  • Opcional: un sitio sandbox para staging

Paso 1 — Configurar GitHub Secrets

Ve a tu repositorio → SettingsSecrets and variablesActions y añade:

SecretValor
OPTIMOCMS_API_KEYTu clave API de producción
OPTIMOCMS_SITE_IDEl ID de tu sitio de producción
OPTIMOCMS_SANDBOX_KEY(opcional) Clave API sandbox para staging
OPTIMOCMS_SANDBOX_SITE_ID(opcional) ID del sitio sandbox

Paso 2 — Contenido como código

Estructura tu contenido en el repositorio:

content/
├── pages/
│   ├── home.json
│   ├── about.json
│   └── menu.json
├── design-tokens.json
└── navigation.json

Ejemplo content/pages/home.json:

{
  "title": "Inicio",
  "slug": "home",
  "blocks": [
    {
      "type": "Hero",
      "props": {
        "title": "Bienvenido a nuestro restaurante",
        "subtitle": "La mejor cocina italiana desde 1985",
        "ctaText": "Reservar ahora",
        "ctaLink": "/reservar"
      }
    }
  ]
}

Paso 3 — Script de despliegue

Crea un scripts/deploy.ts que envía contenido a OptimoCMS:

import { OptimoCMS } from '@optimocms/sdk';
import { readFileSync, readdirSync } from 'node:fs';
import { join } from 'node:path';

const client = new OptimoCMS({
  apiKey: process.env.OPTIMOCMS_API_KEY!,
});

const siteId = process.env.OPTIMOCMS_SITE_ID!;

async function deployPages(): Promise<void> {
  const pagesDir = join(process.cwd(), 'content', 'pages');
  const files = readdirSync(pagesDir).filter(f => f.endsWith('.json'));

  console.log(`Desplegando ${files.length} páginas...`);

  for (const file of files) {
    const content = JSON.parse(readFileSync(join(pagesDir, file), 'utf-8'));

    const existing = await client.pages.list(siteId, { status: 'published' });
    const existingPage = existing.data.find(p => p.slug === content.slug);

    if (existingPage) {
      await client.pages.update(siteId, existingPage.id, {
        title: content.title,
        blocks: content.blocks,
      });
      console.log(`  ✓ Actualizada: ${content.title}`);
    } else {
      await client.pages.create(siteId, {
        title: content.title,
        slug: content.slug,
        status: 'published',
        blocks: content.blocks,
      });
      console.log(`  ✓ Creada: ${content.title}`);
    }
  }
}

async function main(): Promise<void> {
  console.log('🚀 Despliegue OptimoCMS iniciado\n');
  await deployPages();

  const result = await client.sites.publish(siteId);
  console.log(`\n✓ Sitio publicado (${result.status})`);
}

main().catch(error => {
  console.error('Despliegue fallido:', error.message);
  process.exit(1);
});

Paso 4 — Workflow de GitHub Actions

Crea .github/workflows/deploy-content.yml:

name: Deploy Content to OptimoCMS

on:
  push:
    branches: [main]
    paths:
      - 'content/**'
  workflow_dispatch:

jobs:
  deploy-production:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - name: Deploy to Production
        env:
          OPTIMOCMS_API_KEY: ${{ secrets.OPTIMOCMS_API_KEY }}
          OPTIMOCMS_SITE_ID: ${{ secrets.OPTIMOCMS_SITE_ID }}
        run: npx tsx scripts/deploy.ts

Resumen del workflow

Rama feature           PR                    Rama main
     │                  │                        │
     │  push content/   │                        │
     ├─────────────────►│  deploy to sandbox     │
     │                  ├───────────────────►     │
     │                  │  enlace preview en PR   │
     │                  │                        │
     │                  │  merge PR              │
     │                  ├───────────────────────►│
     │                  │                        │  deploy to production
     │                  │                        ├───────────────────►

Siguientes pasos

On this page