OptimoCMSDocs
Guides

CI/CD-Pipeline

Automatisiere Content-Updates und Veröffentlichungen mit GitHub Actions und dem OptimoCMS SDK. Von Staging zu Produktion in einem Push.

CI/CD-Pipeline mit GitHub Actions

Automatisiere deinen OptimoCMS-Workflow mit GitHub Actions. Pushe Content-Änderungen in ein Repository und lass die Pipeline automatisch deine Site aktualisieren und veröffentlichen.

In diesem Tutorial:

  • GitHub Actions Workflow einrichten
  • Content über das SDK in CI aktualisieren
  • Staging (Sandbox) → Produktion Flow
  • Automatische Veröffentlichung bei Merge nach main

Voraussetzungen

  • GitHub-Repository mit deiner Content-/Konfiguration
  • OptimoCMS API-Schlüssel (als GitHub Secret gespeichert)
  • Optional: eine Sandbox-Site für Staging

Schritt 1 — GitHub Secrets einrichten

Gehe zu deinem Repository → SettingsSecrets and variablesActions und füge hinzu:

SecretWert
OPTIMOCMS_API_KEYDein Live-API-Schlüssel
OPTIMOCMS_SITE_IDDeine Produktions-Site-ID
OPTIMOCMS_SANDBOX_KEY(optional) Sandbox-API-Schlüssel für Staging
OPTIMOCMS_SANDBOX_SITE_ID(optional) Sandbox-Site-ID

Schritt 2 — Content als Code

Strukturiere deinen Content im Repository:

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

Beispiel content/pages/home.json:

{
  "title": "Home",
  "slug": "home",
  "blocks": [
    {
      "type": "Hero",
      "props": {
        "title": "Willkommen in unserem Restaurant",
        "subtitle": "Die beste italienische Küche seit 1985",
        "ctaText": "Jetzt reservieren",
        "ctaLink": "/reservieren"
      }
    },
    {
      "type": "FeaturedMenu",
      "props": {
        "title": "Empfehlung des Chefs",
        "items": ["bruschetta", "risotto", "tiramisu"]
      }
    }
  ]
}

Schritt 3 — Deploy-Skript

Erstelle ein scripts/deploy.ts, das Content an OptimoCMS überträgt:

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!;

interface PageContent {
  title: string;
  slug: string;
  blocks: Array<{ type: string; props: Record<string, unknown> }>;
  seo?: { title?: string; description?: string };
}

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

  console.log(`Deploye ${files.length} Seiten...`);

  for (const file of files) {
    const content: PageContent = 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,
        seo: content.seo,
      });
      console.log(`  ✓ Aktualisiert: ${content.title} (${content.slug})`);
    } else {
      await client.pages.create(siteId, {
        title: content.title,
        slug: content.slug,
        status: 'published',
        blocks: content.blocks,
        seo: content.seo,
      });
      console.log(`  ✓ Erstellt: ${content.title} (${content.slug})`);
    }
  }
}

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

  const result = await client.sites.publish(siteId);
  console.log(`\n✓ Site veröffentlicht (${result.status})`);
}

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

Schritt 4 — GitHub Actions Workflow

Erstelle .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

Schritt 5 — Staging → Produktion Flow

Verwende einen PR-basierten Workflow mit Sandbox-Preview:

name: Preview on PR

on:
  pull_request:
    paths:
      - 'content/**'

jobs:
  preview:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'npm'
      - run: npm ci
      - name: Deploy to Sandbox
        env:
          OPTIMOCMS_API_KEY: ${{ secrets.OPTIMOCMS_SANDBOX_KEY }}
          OPTIMOCMS_SITE_ID: ${{ secrets.OPTIMOCMS_SANDBOX_SITE_ID }}
        run: npx tsx scripts/deploy.ts

Workflow-Übersicht

Feature Branch         PR                    Main Branch
     │                  │                        │
     │  push content/   │                        │
     ├─────────────────►│  deploy to sandbox     │
     │                  ├───────────────────►     │
     │                  │  Preview-Link in PR     │
     │                  │                        │
     │                  │  merge PR              │
     │                  ├───────────────────────►│
     │                  │                        │  deploy to production
     │                  │                        ├───────────────────►

Nächste Schritte

On this page