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 → Settings → Secrets and variables → Actions y añade:
| Secret | Valor |
|---|---|
OPTIMOCMS_API_KEY | Tu clave API de producción |
OPTIMOCMS_SITE_ID | El 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.jsonEjemplo 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.tsResumen del workflow
Rama feature PR Rama main
│ │ │
│ push content/ │ │
├─────────────────►│ deploy to sandbox │
│ ├───────────────────► │
│ │ enlace preview en PR │
│ │ │
│ │ merge PR │
│ ├───────────────────────►│
│ │ │ deploy to production
│ │ ├───────────────────►Siguientes pasos
- Automatización multi-sitio — El mismo pipeline para múltiples sitios
- Sync webhook — Recibir notificaciones al publicar
- Manejo de errores SDK — Manejo robusto de errores en CI