Trigger Orchestration
Detailed reference for the trigger orchestration system (change-trigger.yaml).
Overview
The change-trigger.yaml workflow implements incremental CI by detecting which modules have changed and orchestrating their build and test execution. This workflow serves as the main entry point for continuous integration and handles all release triggering.
On push to main, after CI workflows complete, the workflow checks for pending releases from two sources:
- Semver modules: Changelog versions without corresponding git tags (r2r-cli, ext-eac)
- Calver modules: Modules that had CI dispatched and auto-release on every push (docs, books)
Releases are triggered in dependency order, with each layer completing before the next begins.
Location: .github/workflows/change-trigger.yaml
Triggers
on:
push:
branches:
- main
pull_request:
branches:
- main
workflow_dispatch:
inputs:
trigger-all:
description: 'Trigger all workflows regardless of changes'
required: false
type: boolean
default: false
The workflow runs automatically on pushes to main and pull requests targeting main. It can also be triggered manually with an option to bypass change detection.
Permissions
permissions:
actions: write # Required to dispatch child workflows
contents: read # Required to checkout code
Pipeline Architecture
The workflow executes in multiple stages with two parallel flows:
Stage 0: Build CI Tooling
↓
┌────┴────┐
↓ ↓
Flow A Flow B
(Repo) (Modules)
↓ ↓
└────┬────┘
↓
Summary
Stage 0: Build CI Tooling
Job: build-tooling
Builds and caches the commands binary for use by all subsequent jobs.
Steps:
- Checkout repository
- Setup commands binary using
.github/actions/setup-commands - Generate build summary
Outputs:
- Uploads
commands-binaryartifact for reuse
Flow A: Repository Validation (Parallel)
Validates repository-level contracts and structure.
Job: build-repository
Builds the repository module.
Dependencies: build-tooling
Steps:
- Checkout repository
- Build repository module using
.github/actions/build-module
Job: validate-repository
Runs repository commit test suite.
Dependencies: build-repository
Steps:
- Checkout repository
- Pre-compute git file list via GitHub API (optimization to avoid slow
git ls-files) - Test repository module using
.github/actions/test-modulewithcommitsuite
Optimization: Uses GitHub API to fetch file list (~2-5s) instead of git ls-files (~84s).
Flow B: Module CI Orchestration (Parallel)
Detects changes, calculates execution order, and dispatches module CI workflows.
Job: detect-changes
Determines which modules need to be rebuilt based on file changes.
Dependencies: build-tooling
Steps:
- Checkout repository with full history (
fetch-depth: 0) - Download commands binary artifact
- Detect changed modules using change detection logic (see below)
- Filter to modules with CI workflows (
.github/workflows/ci-{moniker}.yaml) - Generate step summary showing detected changes
Outputs:
changed-modules- Space-separated list of module monikershas-changes- Boolean indicating if any modules changeddirectly_changed- Modules with direct file changesinvalidated- Dependent modules triggered by dependency changesbase_sha- Base commit SHA used for comparisonis_bootstrap- Boolean indicating bootstrap mode (no previous CI)changed_file_count- Number of files changedfiles_by_module- JSON object mapping modules to changed files
Change Detection Logic:
Manual Override:
Pull Request:
# Compare against PR base SHA
RESULT=$(commands get changed-modules-ci --pr-base "⟪ github.event.pull_request.base.sha ⟫" --as-json)
Push to Main:
Bootstrap Mode:
- Triggered when no previous successful CI run exists
- Builds all modules
Dependency Invalidation:
- When a module changes, all modules that depend on it are also marked for rebuild
- Ensures dependent modules are rebuilt when their dependencies change (cache invalidation)
Job: calculate-order
Computes dependency-based execution order for changed modules.
Dependencies: detect-changes
Steps:
- Checkout repository
- Download commands binary artifact
- Calculate execution order using dependency graph
- Generate execution plan (modules grouped into layers)
- Generate step summary showing layer structure
Command:
Outputs:
execution-plan- JSON object with layered execution planlayer-count- Number of dependency layers
Execution Plan Structure:
{
"layer_count": 3,
"layers": [
["eac-core", "eac-ai"],
["eac-commands", "eac-mcp-commands"],
["r2r-cli"]
]
}
Layer explanation:
- Layer 1:
eac-core,eac-ai- No dependencies - Layer 2:
eac-commands,eac-mcp-commands- Depend on Layer 1 - Layer 3:
r2r-cli- Depends on Layer 2
Job: execute-layers
Dispatches module CI workflows in dependency order.
Dependencies: detect-changes, calculate-order
Steps:
- Checkout repository
- Download commands binary artifact
- Execute workflows based on execution mode (PR vs trunk)
- Generate step summary
Execution Modes:
Pull Request Mode:
# Run all workflows in parallel for fast feedback
for module in $ALL_MODULES; do
gh workflow run "ci-${module}.yaml" \
--ref "$DISPATCH_REF" \
-f ref=⟪ github.ref ⟫ \
-f sha=⟪ github.sha ⟫ \
-f trigger_run_id=⟪ github.run_id ⟫
done
# Child workflows report their own statuses
Trunk Mode (Main Branch):
# Run in dependency layers
for layer_idx in 0..$LAYER_COUNT; do
# Dispatch all workflows in this layer
for module in $LAYER_MODULES; do
gh workflow run "ci-${module}.yaml" ...
done
# Wait for all workflows in layer to complete
commands pipeline wait $LAYER_RUN_IDS --timeout 3600
# Exit if layer fails
if [ $? -ne 0 ]; then
exit 1
fi
done
Key Differences:
- PR mode: All modules run in parallel, no waiting, commit tests only
- Trunk mode: Sequential layers with waiting, full test suite (commit + acceptance)
Summary Stage
Job: summary
Generates comprehensive summary of CI run.
Dependencies: All previous jobs (waits for both flows)
Condition: always() - Runs even if previous jobs fail
Steps:
- Check build-tooling status
- Check repository validation status
- Check module dispatch status
- Generate step summary with diagnostic information
Summary Content:
- Trigger information (event, branch, commit)
- Pipeline stage results (tooling, repository, modules)
- No-change explanation (if applicable)
- Validation passed confirmation
- Link to child workflow checks
Change Detection Details
For Pull Requests
Compares PR head against PR base to determine what the PR introduces:
For Push to Main
Compares current commit against last successful CI run:
The command queries GitHub Actions API to find the last successful run of change-trigger.yaml on the main branch.
Bootstrap Mode
When no previous successful CI run is found:
is_bootstrapis set totrue- All modules are marked for rebuild
- Establishes baseline for future incremental builds
Dependency Invalidation
The change detection includes transitive invalidation:
- Directly changed modules: Modules with modified files
- Invalidated modules: Modules that depend on directly changed modules
Example:
If eac-core changes, both eac-commands and r2r-cli are rebuilt.
Workflow Dispatch Parameters
trigger-all (boolean)
Bypasses change detection and triggers all module CI workflows.
Use cases:
- Testing full build after infrastructure changes
- Periodic full validation
- Debugging change detection logic
Behavior:
- Discovers all
ci-*.yamlworkflows dynamically - Dispatches all discovered workflows
- Skips change detection and dependency analysis
Environment Variables
GH_TOKEN- GitHub token for workflow dispatch and API calls (automatically provided)GITHUB_TOKEN- GitHub token for checkout and artifact operations (automatically provided)
Artifacts
Produced
commands-binary- Cached commands executable for reuse
Consumed
- None (creates initial artifacts)
Step Summaries
The workflow generates rich GitHub step summaries:
Change Detection Summary
Shows:
- Base SHA or bootstrap mode
- Files changed count
- Directly changed modules
- Invalidated (dependent) modules
- CI workflows to run
- Per-module reasoning (why each module was triggered)
Execution Order Summary
Shows:
- Execution mode (PR parallel vs trunk layered)
- Layer structure with module groupings
- Explanation of execution strategy
Final Summary
Shows:
- Pipeline stage results (pass/fail)
- Total workflows dispatched
- Link to child workflow status checks
- Troubleshooting information (if no changes)
Performance Optimizations
- Artifact caching: Commands binary built once and reused
- GitHub API file list: Uses fast API instead of slow
git ls-files - Incremental builds: Only builds changed modules and their dependents
- Parallel execution: Modules in same layer run concurrently
Failure Modes
Build Tooling Failure
If build-tooling fails:
- All downstream jobs are skipped
- Summary explains tooling build failure
Repository Validation Failure
If build-repository or validate-repository fails:
- Module workflows are still dispatched (validation is independent)
- Summary shows repository validation failure
Module Dispatch Failure
If execute-layers fails to dispatch workflows:
- Summary shows dispatch failure
- Indicates orchestration problem (not module failure)
No Changes Detected
If no modules need rebuilding:
- Summary explains why (base SHA, file count, affected modules)
- Workflow succeeds (no work to do)
References
- Workflow file:
.github/workflows/change-trigger.yaml - Overview - Workflow architecture
- CI Workflows - Module CI workflow patterns
- Repository Layout - Module structure
Tutorials | How-to Guides | Explanation | Reference
You are here: Reference — information-oriented technical descriptions of the system.