What CI/CD Pipelines Are Defined in .github/workflows for open-seo?

The open-seo repository defines four GitHub Actions workflows in .github/workflows: ci.yml for core checks, docker-image.yml for multi-arch container builds, sourcemaps.yml for PostHog error tracking, and pr-preview.yml for Cloudflare Workers preview deployments.

The open-seo project by every-app automates its entire software delivery lifecycle through GitHub Actions. All CI/CD configurations live in the .github/workflows directory, providing continuous integration, reproducible builds, error monitoring, and on-demand preview environments. This guide breaks down each pipeline, its triggers, and how they work together as derived directly from the source code.


CI Workflow: ci.yml

The ci.yml workflow serves as the primary quality gate for every code change.

Triggers and Purpose

  • Triggers: push to main and any pull request
  • Key steps: dependency installation, linting, type-checking, unit tests, Vite worker bundle build, and website compilation

The workflow uses actions/setup-node@v4 with cache: pnpm for fast, reproducible dependency restoration. Concurrency is controlled via group: ci-${{ github.ref }}, automatically cancelling stale runs when new commits arrive.

Core Pipeline Steps


# From .github/workflows/ci.yml

# Simplified representation of the job structure

jobs:
  ci:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
          cache: 'pnpm'
      - run: pnpm install --frozen-lockfile
      - run: pnpm run ci:check      # Lint + type-check

      - run: pnpm run test:ci       # Unit test suite

      - run: pnpm vite build        # Worker bundle

      - run: pnpm --dir web install && pnpm --dir web run build

Run this locally to match CI behavior:

pnpm install --frozen-lockfile
pnpm run ci:check
pnpm run test:ci
pnpm vite build
pnpm --dir web install && pnpm --dir web run build

Docker Image Build Workflow: docker-image.yml

The docker-image.yml workflow produces multi-architecture container images for self-hosting.

Triggers and Publishing

  • Triggers: push to main, v* tags, and manual dispatch via workflow_dispatch
  • Output: GitHub Container Registry (GHCR)

This workflow builds for both linux/amd64 and linux/arm64 using QEMU and Buildx. The docker/metadata-action@v5 auto-generates tags and labels, while type=gha cache acceleration speeds up subsequent builds.

Multi-Arch Build Configuration


# From .github/workflows/docker-image.yml

# Key Docker buildx configuration

- name: Set up QEMU
  uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
  uses: docker/setup-buildx-action@v3
- name: Build and push
  uses: docker/build-push-action@v5
  with:
    context: .
    file: Dockerfile.selfhost
    platforms: linux/amd64,linux/arm64
    cache-from: type=gha
    cache-to: type=gha,mode=max

Trigger manually with the GitHub CLI:

gh workflow run docker-image.yml --ref main

Sourcemaps Upload Workflow: sourcemaps.yml

The sourcemaps.yml workflow ensures production errors remain debuggable.

Purpose and Trigger

  • Trigger: push to main only
  • Function: Compile and upload sourcemaps to PostHog for error de-obfuscation

The workflow requires POSTHOG_CLI_TOKEN via ${{ secrets.POSTHOG_CLI_TOKEN }}. This enables the team to trace minified production errors back to original TypeScript source locations.


PR Preview Workflow: pr-preview.yml

The pr-preview.yml workflow creates ephemeral preview environments for every pull request on Cloudflare Workers.

Full Lifecycle Automation

PR Event Action
opened Deploy new preview stage
synchronize Update existing preview with new commits
reopened Redeploy previously closed preview
closed Automatically destroy preview and clean up resources

Preview URL Generation and Verification

The workflow reads WORKERS_SUBDOMAIN from the ENV_PREVIEW secret (a .env.preview file) to construct URLs like https://open-seo-pr-12.example.workers.dev. After deployment, it validates that Cloudflare Access protection is active, then posts the preview URL as a PR comment.

Access the preview from the posted comment:


# Example URL from PR comment

curl -I https://open-seo-pr-12.example.workers.dev

Shared Architecture Patterns

All four workflows in .github/workflows follow consistent design principles:

  • Concurrency control: Each uses concurrency blocks with cancel-in-progress: true to prevent resource waste
  • Secret injection: Sensitive credentials use ${{ secrets... }} and ${{ vars... }} contexts
  • Caching strategy: pnpm dependencies and Docker layers are aggressively cached
  • Fail-fast behavior: Quality checks run early to surface issues before expensive builds

Summary

  • ci.yml runs lint, type-check, tests, and builds on every push and PR
  • docker-image.yml publishes multi-arch images to GHCR on main/tags or manual trigger
  • sourcemaps.yml uploads production sourcemaps to PostHog after successful main branch builds
  • pr-preview.yml deploys and tears down Cloudflare Workers previews tied to PR lifecycle
  • All workflows use concurrency controls, strategic caching, and secret-based configuration for secure, efficient automation

Frequently Asked Questions

How do I trigger a Docker build without pushing code?

Use the GitHub CLI or GitHub web UI to run the docker-image.yml workflow with workflow_dispatch. Run: gh workflow run docker-image.yml --ref main.

What architectures does the Docker image support?

The docker-image.yml workflow builds for linux/amd64 and linux/arm64 using QEMU emulation and Docker Buildx, ensuring compatibility with most server environments.

Where do PR preview URLs come from?

The pr-preview.yml workflow constructs URLs using the WORKERS_SUBDOMAIN value from the ENV_PREVIEW secret, producing addresses like https://open-seo-pr-N.subdomain.workers.dev and posting them as PR comments.

Why are sourcemaps uploaded separately from the main CI?

Sourcemap generation requires production build artifacts and the PostHog CLI token. The sourcemaps.yml workflow isolates this concern, running only after successful main branch builds to ensure de-obfuscation data matches deployed code.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →