CI/CD Integration
How to integrate xcaffold into GitHub Actions and other CI/CD pipelines.
xcaffold is designed for GitOps-first workflows. The CLI provides two commands purpose-built for CI:
xcaffold status— fails the pipeline (exit code 1) if any developer manually edited a compiled output directoryxcaffold apply— recompiles from.xcafsources and updates the state file
This page shows the recommended patterns for GitHub Actions. The same approach applies to GitLab CI, CircleCI, and any other runner.
The Golden Rule
Commit your
xcaf/directory andproject.xcaf.state. Add provider output directories to.gitignore.
Provider output directories (.claude/, .cursor/, .gemini/, .github/, .agents/) are build outputs — equivalent to dist/ or node_modules/. Developers never edit them directly; they only edit .xcaf files. CI regenerates output on every deployment.
# .gitignore additions
.claude/
.cursor/
.gemini/
.github/copilot-instructions.md
.agents/
Drift Detection Workflow
The most important CI job is the drift check. It runs on every pull request and ensures no one bypassed the compiler.
# .github/workflows/xcaffold-drift.yml
name: xcaffold Drift Check
on:
pull_request:
paths:
- "xcaf/**"
- "project.xcaf"
- "project.xcaf.state"
jobs:
drift-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install xcaffold
run: |
curl -sSL https://github.com/saero-ai/xcaffold/releases/latest/download/xcaffold_Linux_x86_64.tar.gz | tar -xz
sudo mv xcaffold /usr/local/bin/
- name: Compile from .xcaf sources
run: xcaffold apply
- name: Check for drift
run: xcaffold statusIf xcaffold status exits with code 1, the PR is blocked. The developer must revert manual changes and commit through the proper .xcaf workflow instead.
Policy Validation Gate
Block merges that deploy agents violating your project policies:
name: xcaffold Policy Gate
on:
pull_request:
paths: ['xcaf/**', 'project.xcaf']
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install xcaffold
run: |
curl -sSL https://github.com/saero-ai/xcaffold/releases/latest/download/xcaffold_Linux_x86_64.tar.gz | tar -xz
sudo mv xcaffold /usr/local/bin/
- name: Validate policies
run: xcaffold validateFull Apply Workflow (Deployment)
Use this pattern on main branch pushes to ensure the deployed environment always reflects the latest configuration:
# .github/workflows/xcaffold-deploy.yml
name: xcaffold Deploy Agents
on:
push:
branches: [main]
paths:
- "xcaf/**"
- "project.xcaf"
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Install xcaffold
run: |
curl -sSL https://github.com/saero-ai/xcaffold/releases/latest/download/xcaffold_Linux_x86_64.tar.gz | tar -xz
sudo mv xcaffold /usr/local/bin/
- name: Compile agents
run: xcaffold apply
- name: Verify state integrity
run: xcaffold status
- name: Commit updated state
run: |
git config user.name "xcaffold-bot"
git config user.email "[email protected]"
git add project.xcaf.state
git diff --staged --quiet || git commit -m "chore: update project.xcaf.state [skip ci]"
git pushInstallation Methods in CI
Binary download (recommended for Linux runners):
curl -sSL https://github.com/saero-ai/xcaffold/releases/latest/download/xcaffold_Linux_x86_64.tar.gz | tar -xz sudo mv xcaffold /usr/local/bin/
Homebrew (macOS runners):
brew install saero-ai/tap/xcaffold
Go install:
go install github.com/saero-ai/xcaffold/cmd/xcaffold@latest