CircleCI
Uses setup workflows with dynamic config to completely skip jobs before they start
Cigen is not just a configuration generator - it’s a universal CI abstraction layer that allows you to write your CI configuration once and run it on ANY CI platform, regardless of that platform’s limitations or quirks.
What you write: “Skip this job if these files haven’t changed”
How cigen implements it:
CircleCI
Uses setup workflows with dynamic config to completely skip jobs before they start
GitHub Actions
Injects early-exit steps that check SHA256 hashes and abort if unchanged
Other Platforms
Best-effort implementation based on available platform features
Our approach uses a top-down SHA256 hash of actual file contents, which is far more reliable than GitHub’s brittle paths filter that:
What you write: “Run this job when approval_A OR approval_B happens”
How cigen implements it:
In DocSpring’s workflow, build_app_image should run when:
approve_build_app_image, ORSince CircleCI only supports AND dependencies, cigen automatically creates approve_build_app_image_staging/eu/us shim jobs that programmatically approve the main approval via API.
What you write: “Run this job on architectures: [amd64, arm64]”
How cigen implements it:
job_amd64, job_arm64)Cigen provides built-in commands for common workarounds:
steps: - automated_approval: target_job_name # Approve jobs via API - skip_if_unchanged: '@ruby' # Check file hashes - wait_for_any: [job_a, job_b] # OR dependencies - matrix_job: [amd64, arm64] # Multi-arch buildsCigen detects platform capabilities and automatically:
# What you write:jobs: test: source_files: '@ruby' # Only run if Ruby files changed steps: - run: bundle exec rspec# Uses setup workflow to check hashes and skip entire job if unchangedsetup: trueworkflows: setup: jobs: - check_changes: filters: { branches: { only: /.*/ } } - continue: requires: [check_changes]# Injects early-exit stepjobs: test: steps: - name: Check if files changed run: | if cache_hit "${SHA256_HASH}"; then echo "Files unchanged, skipping job" exit 0 fi - name: Run tests run: bundle exec rspec# What you write:jobs: deploy: requires_any: [approval_staging, approval_production] steps: [...]# Creates automated shim jobs that convert OR to ANDjobs: approval_staging_shim: type: approval requires: [approval_staging] steps: - automated_approval: deploy
approval_production_shim: type: approval requires: [approval_production] steps: - automated_approval: deployPortability
Move between CI platforms without rewriting configurations
Consistency
Same behavior across different platforms with identical semantics
Simplicity
Write what you want to happen, not how to achieve it on each platform
Evolution
As platforms add features, cigen switches from workarounds to native implementations
As cigen evolves, it will: