Skip to content

Philosophy

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:

  • Misses changes in dependencies outside specified paths
  • Prevents re-runs when external issues are fixed
  • Can’t handle intermittent failures that need retries

What you write: “Run this job when approval_A OR approval_B happens”

How cigen implements it:

  • CircleCI: Automatically generates “shim” jobs using the CircleCI API to programmatically approve jobs, converting OR logic into AND logic
  • GitHub Actions: Uses workflow_dispatch events or conditional logic
  • Other platforms: Platform-specific workarounds

In DocSpring’s workflow, build_app_image should run when:

  • Someone manually approves approve_build_app_image, OR
  • Someone approves any deployment (staging/EU/US)

Since 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:

  • CircleCI: Generates separate jobs with architecture suffixes (job_amd64, job_arm64)
  • GitHub Actions: Uses native matrix strategies
  • Other platforms: Best available approach for parallel execution

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 builds

Cigen detects platform capabilities and automatically:

  1. Uses native features when available
  2. Implements workarounds when features are missing
  3. Warns about limitations that can’t be worked around
config.yml
# What you write:
jobs:
test:
source_files: '@ruby' # Only run if Ruby files changed
steps:
- run: bundle exec rspec
Generated for CircleCI
# Uses setup workflow to check hashes and skip entire job if unchanged
setup: true
workflows:
setup:
jobs:
- check_changes:
filters: { branches: { only: /.*/ } }
- continue:
requires: [check_changes]
Generated for GitHub Actions
# Injects early-exit step
jobs:
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
config.yml
# What you write:
jobs:
deploy:
requires_any: [approval_staging, approval_production]
steps: [...]
Generated for CircleCI
# Creates automated shim jobs that convert OR to AND
jobs:
approval_staging_shim:
type: approval
requires: [approval_staging]
steps:
- automated_approval: deploy
approval_production_shim:
type: approval
requires: [approval_production]
steps:
- automated_approval: deploy

Portability

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:

  1. Build a comprehensive library of platform-specific workarounds
  2. Enable community sharing of workarounds and best practices
  3. Influence CI platforms to add missing features natively
  4. Provide performance metrics comparing native vs workaround implementations