CI/CD Integration
Store config files in Git and let CI handle the lifecycle: diff on pull request, apply on merge. Every config change gets a review, an audit trail, and an automatic rollback checkpoint.
Repository layout
Section titled “Repository layout”Keep config files in a dedicated directory so CI can track changes to them:
repo/└── config/ ├── feature_flags.json ├── rate_limits.json └── service_config.jsonPrerequisites
Section titled “Prerequisites”Add two secrets to your GitHub repository (Settings → Secrets and variables → Actions):
| Secret | Value |
|---|---|
ST8_SERVER | Your st8d URL, e.g. https://st8.internal |
ST8_TOKEN | Bearer token configured in st8d |
Diff on pull request
Section titled “Diff on pull request”On every PR that touches config/, run st8ctl diff against each changed file and post the output as a PR comment.
name: Config diff
on: pull_request: paths: - 'config/**'
jobs: diff: runs-on: ubuntu-latest permissions: pull-requests: write steps: - uses: actions/checkout@v4
- uses: actions/setup-go@v5 with: go-version: stable
- name: Install st8ctl run: go install github.com/geeper-io/st8/cmd/st8ctl@latest
- name: Diff config files run: | args=() for f in config/*.json; do args+=(-f "$f"); done output=$(st8ctl \ --server "$ST8_SERVER" \ --token "$ST8_TOKEN" \ --namespace myapp/prod \ diff "${args[@]}" 2>&1 || true)
if [ -z "$output" ]; then body="## Config diff\n\n_No changes._" else body="## Config diff\n\n\`\`\`diff\n${output}\n\`\`\`" fi
printf '%s' "$body" > /tmp/diff-body.md env: ST8_SERVER: ${{ secrets.ST8_SERVER }} ST8_TOKEN: ${{ secrets.ST8_TOKEN }}
- name: Post PR comment uses: actions/github-script@v7 with: script: | const fs = require('fs'); const body = fs.readFileSync('/tmp/diff-body.md', 'utf8'); await github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body, });The PR comment will look like:
**`config/feature_flags.json`** "new_checkout": false, "ai_search": false, "ai_search": true, "max_upload_mb": 10Apply on merge
Section titled “Apply on merge”When a PR merges to main, apply all config files and create a checkpoint named after the commit SHA so you can roll back to it later.
name: Apply config
on: push: branches: - main paths: - 'config/**'
jobs: apply: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- uses: actions/setup-go@v5 with: go-version: stable
- name: Install st8ctl run: go install github.com/geeper-io/st8/cmd/st8ctl@latest
- name: Apply config run: | args=() for f in config/*.json; do args+=(-f "$f"); done st8ctl \ --server "$ST8_SERVER" \ --token "$ST8_TOKEN" \ --namespace myapp/prod \ apply "${args[@]}" \ --message "deploy: ${{ github.sha }}" env: ST8_SERVER: ${{ secrets.ST8_SERVER }} ST8_TOKEN: ${{ secrets.ST8_TOKEN }}
- name: Checkpoint run: | st8ctl \ --server "$ST8_SERVER" \ --token "$ST8_TOKEN" \ --namespace myapp/prod \ checkpoint "sha-${{ github.sha }}" \ --description "Deployed from ${{ github.sha }}" env: ST8_SERVER: ${{ secrets.ST8_SERVER }} ST8_TOKEN: ${{ secrets.ST8_TOKEN }}Emergency rollback
Section titled “Emergency rollback”If a deploy causes problems, roll back to any previous checkpoint directly from the terminal:
# List recent deploys to find a good onest8ctl --server https://st8.internal --token $ST8_TOKEN \ --namespace myapp/prod \ log --limit 10
# Roll back to a specific deployst8ctl --server https://st8.internal --token $ST8_TOKEN \ --namespace myapp/prod \ rollback \ --checkpoint sha-abc1234 \ --message "rollback: revert bad config deploy"Or trigger a rollback workflow that accepts the target SHA:
name: Rollback config
on: workflow_dispatch: inputs: sha: description: 'Commit SHA to roll back to' required: true
jobs: rollback: runs-on: ubuntu-latest steps: - uses: actions/setup-go@v5 with: go-version: stable
- name: Install st8ctl run: go install github.com/geeper-io/st8/cmd/st8ctl@latest
- name: Rollback run: | st8ctl \ --server "$ST8_SERVER" \ --token "$ST8_TOKEN" \ --namespace myapp/prod \ rollback \ --checkpoint "sha-${{ github.event.inputs.sha }}" \ --message "rollback: revert to ${{ github.event.inputs.sha }}" env: ST8_SERVER: ${{ secrets.ST8_SERVER }} ST8_TOKEN: ${{ secrets.ST8_TOKEN }}Trigger it from the GitHub Actions UI or with gh workflow run st8-rollback.yml -f sha=abc1234.
Multi-environment: staging then production
Section titled “Multi-environment: staging then production”Use separate namespaces and a production environment gate to require human approval before applying to prod.
name: Apply config
on: push: branches: - main paths: - 'config/**'
jobs: staging: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: stable - run: go install github.com/geeper-io/st8/cmd/st8ctl@latest - name: Apply to staging run: | args=() for f in config/*.json; do args+=(-f "$f"); done st8ctl \ --server "$ST8_SERVER" \ --token "$ST8_TOKEN" \ --namespace myapp/staging \ apply "${args[@]}" \ --message "staging: ${{ github.sha }}" env: ST8_SERVER: ${{ secrets.ST8_SERVER }} ST8_TOKEN: ${{ secrets.ST8_TOKEN }}
production: needs: staging runs-on: ubuntu-latest environment: production # requires manual approval in GitHub steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: stable - run: go install github.com/geeper-io/st8/cmd/st8ctl@latest - name: Apply to production run: | args=() for f in config/*.json; do args+=(-f "$f"); done st8ctl \ --server "$ST8_SERVER" \ --token "$ST8_TOKEN" \ --namespace myapp/prod \ apply "${args[@]}" \ --message "prod: ${{ github.sha }}" st8ctl \ --server "$ST8_SERVER" \ --token "$ST8_TOKEN" \ --namespace myapp/prod \ checkpoint "sha-${{ github.sha }}" \ --description "Deployed ${{ github.sha }}" env: ST8_SERVER: ${{ secrets.ST8_SERVER }} ST8_TOKEN: ${{ secrets.ST8_TOKEN }}The environment: production gate pauses the job until an approver clicks Review deployments in GitHub Actions.