CI/CD setup
Automate SteadyCron manifest deployments with GitHub Actions — plan diffs on pull requests, apply on merge.
Running steadycron plan in every pull request and steadycron apply --prune on merge
turns your manifest into a GitOps workflow: reviewers see exactly what cron changes a PR
introduces, and the main branch is always the source of truth.
Prerequisites
- A SteadyCron API key (create one in Settings → API keys)
- Your manifest committed to the repo (see Migrate to IaC)
Step 1 — add the API key as a secret
In your GitHub repository, go to Settings → Secrets and variables → Actions and add:
| Name | Value |
|---|---|
STEADYCRON_API_KEY | Your SteadyCron API key (sc_...) |
Add any other environment-specific secrets your manifest references (e.g. SLACK_WEBHOOK_URL).
For plan-only pipelines (read operations), you can create a separate read-only API key and use it exclusively in the PR workflow.
Workflow 1 — plan diff on pull request
Post the plan output as a PR comment whenever a manifest file changes:
# .github/workflows/cron-plan.yml
name: Cron plan
on:
pull_request:
paths:
- 'manifests/**'
jobs:
plan:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: steadycron/action@v1
with:
command: plan
manifest: manifests/production.yaml
comment-on-pr: 'true'
env:
STEADYCRON_API_KEY: ${{ secrets.STEADYCRON_API_KEY }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
The action posts a comment like:
SteadyCron plan — manifests/production.yaml
~ weekly-digest update retries: 2 → 3
+ invoice-cron create http 0 17 * * 5
1 to create · 1 to update · 0 to delete
Workflow 2 — apply on merge
Apply the manifest (with --prune) whenever the main branch is updated:
# .github/workflows/cron-apply.yml
name: Cron apply
on:
push:
branches:
- main
paths:
- 'manifests/**'
jobs:
apply:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: steadycron/action@v1
with:
command: apply
manifest: manifests/production.yaml
prune: 'true'
env:
STEADYCRON_API_KEY: ${{ secrets.STEADYCRON_API_KEY }}
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}
Action inputs
| Input | Description | Default |
|---|---|---|
command | plan, apply, validate, or sync | plan |
manifest | Path to the manifest file or directory | — |
prune | If true, pass --prune to apply | false |
comment-on-pr | If true, post the plan output as a PR comment | false |
All ${ENV_VAR} placeholders in your manifest are read from the job’s environment —
pass them via the env: block in your workflow step.
Multiple environments
Manage separate staging and production manifests with a matrix:
jobs:
apply:
runs-on: ubuntu-latest
strategy:
matrix:
env: [staging, production]
steps:
- uses: actions/checkout@v4
- uses: steadycron/action@v1
with:
command: apply
manifest: manifests/${{ matrix.env }}.yaml
prune: 'true'
env:
STEADYCRON_API_KEY: ${{ secrets[format('STEADYCRON_API_KEY_{0}', matrix.env)] }}
Least-privilege API keys
For plan-only workflows (PR comments), use a read-only API key that cannot make changes.
Create a separate key in the dashboard with read scope only and store it as a separate
secret (e.g. STEADYCRON_API_KEY_RO).
This limits the blast radius if the PR workflow secret is ever compromised.
Validate on every push
Add a validate job to catch schema errors before plan runs:
- uses: steadycron/action@v1
with:
command: validate
manifest: manifests/production.yaml
env:
STEADYCRON_API_KEY: ${{ secrets.STEADYCRON_API_KEY }}
validate exits non-zero on schema errors and does not require an API key, but passing
one allows the server to validate against your account’s current limits.
Related
- IaC workflow — all CLI commands explained
- Migrate to IaC — adopt an existing account
- Manifest reference — full field reference