27 KiB
27 KiB
Workflow Triggers & Dependencies
Complete reference for CI/CD workflow triggering rules and dependency chains.
Trigger Types Overview
1. Push Triggers
Workflows triggered by commits pushed to branches.
on:
push:
branches: [main, develop] # Branch filter
paths: # Path filter (optional)
- 'src/**'
paths-ignore: # Exclude paths (optional)
- 'docs/**'
tags: # Tag filter (for releases)
- 'v*'
2. Pull Request Triggers
Workflows triggered by PR events.
on:
pull_request:
branches: [main, develop] # Target branch filter
types: [opened, synchronize, reopened] # Event types
paths:
- 'src/**'
3. Schedule Triggers
Cron-based scheduled execution.
on:
schedule:
- cron: '0 5 * * *' # Daily at 5 AM UTC
- cron: '0 2 * * 0' # Weekly Sunday at 2 AM UTC
4. Manual Triggers
On-demand workflow execution with inputs.
on:
workflow_dispatch:
inputs:
environment:
type: choice
options: [staging, production]
dry_run:
type: boolean
default: false
5. Workflow Call (Reusable)
Called by other workflows.
on:
workflow_call:
inputs:
category:
type: string
required: true
Complete Trigger Matrix
PR-Gating Workflows (Always Run on PR)
| Workflow | Branches | Path Filters | Purpose |
|---|---|---|---|
test-matrix.yml |
main | !docs/**, !*.md |
Unit, Architecture, Contract, Integration, Security, Golden tests |
build-test-deploy.yml |
main, develop | src/**, docs/**, scripts/** |
Build verification |
policy-lint.yml |
main | docs/policy/**, src/Cli/** |
Policy file validation |
sast-scan.yml |
main, develop | src/**, *.cs, *.ts, Dockerfile* |
Static security analysis |
docs.yml |
- | docs/**, scripts/render_docs.py |
Documentation validation |
integration-tests-gate.yml |
main, develop | src/**, src/__Tests/** |
Extended integration |
Main Branch Only Workflows
| Workflow | Trigger Condition | Purpose |
|---|---|---|
build-test-deploy.yml → deploy |
github.ref == 'refs/heads/main' |
Deploy to staging |
integration-tests-gate.yml → corpus-validation |
github.ref == 'refs/heads/main' |
Ground truth validation |
coverage-report |
After integration tests on main | Full coverage analysis |
Tag-Triggered Workflows
| Workflow | Tag Pattern | Example | Purpose |
|---|---|---|---|
release-suite.yml |
suite-* |
suite-2026.04 |
Ubuntu-style suite release |
release.yml |
v* |
v2025.12.1, v2025.12.0-edge |
Version bundle release |
module-publish.yml |
module-*-v* |
module-authority-v1.2.3 |
Per-module publishing |
Scheduled Workflows
| Workflow | Schedule (UTC) | Frequency | Purpose |
|---|---|---|---|
nightly-regression.yml |
0 2 * * * |
Daily 2 AM | Full regression suite |
dependency-security-scan.yml |
0 2 * * 0 |
Sunday 2 AM | Vulnerability audit |
renovate.yml |
0 3,15 * * * |
Daily 3 AM & 3 PM | Dependency updates |
sast-scan.yml |
30 3 * * 1 |
Monday 3:30 AM | Weekly deep scan |
migration-test.yml |
30 4 * * * |
Daily 4:30 AM | Migration validation |
build-test-deploy.yml |
0 5 * * * |
Daily 5 AM | Extended build tests |
test-matrix.yml |
0 5 * * * |
Daily 5 AM | Extended test categories |
Manual-Only Workflows
| Workflow | Inputs | Purpose |
|---|---|---|
cli-build.yml |
rids, config, sign | Multi-platform CLI builds |
scanner-determinism.yml |
- | Verify scanner reproducibility |
cross-platform-determinism.yml |
- | Cross-OS build verification |
rollback.yml |
environment, service, version | Emergency rollback |
promote.yml |
from_env, to_env, version | Environment promotion |
Dependency Chains
Build → Test → Deploy Pipeline
┌─────────────────────────────────────────────────────────────────┐
│ build-test-deploy.yml │
├─────────────────────────────────────────────────────────────────┤
│ │
│ profile-validation ─────────────────────────────────┐ │
│ │ │ │
│ ▼ │ │
│ build-test ─────────────────────────────────────────┤ │
│ │ (CLI, Concelier, Authority, Scanner, etc.) │ │
│ │ │ │
│ ▼ │ │
│ quality-gates ──────────────────────────────────────┤ │
│ │ (Reachability, TTFS, Performance SLOs) │ │
│ │ │ │
│ ▼ │ │
│ security-testing (PR label or schedule) ────────────┤ │
│ │ │ │
│ ▼ │ │
│ sealed-mode-ci ─────────────────────────────────────┤ │
│ │ │ │
│ ▼ │ │
│ docs ───────────────────────────────────────────────┤ │
│ │ │ │
│ ▼ │ │
│ scanner-perf ───────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ deploy (main branch only OR workflow_dispatch) │
│ │ │
│ ▼ │
│ summary │
│ │
└─────────────────────────────────────────────────────────────────┘
Test Matrix Pipeline
┌─────────────────────────────────────────────────────────────────┐
│ test-matrix.yml │
├─────────────────────────────────────────────────────────────────┤
│ │
│ discover ─────────────────────────────────────────────────┐ │
│ │ (Find all *.Tests.csproj files) │ │
│ │ │ │
│ ├───▶ pr-gating-tests (Matrix: 5 categories) │ │
│ │ ├── Unit │ │
│ │ ├── Architecture │ │
│ │ ├── Contract │ │
│ │ ├── Security │ │
│ │ └── Golden │ │
│ │ │ │
│ ├───▶ integration (PostgreSQL service) │ │
│ │ │ │
│ └───▶ extended-tests (schedule or manual) │ │
│ ├── Performance │ │
│ ├── Benchmark │ │
│ ├── AirGap │ │
│ ├── Chaos │ │
│ ├── Determinism │ │
│ ├── Resilience │ │
│ └── Observability │ │
│ │ │ │
│ ◀────────────────────────────────────────────┘ │ │
│ │ │ │
│ ▼ │ │
│ summary ◀─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Suite Release Pipeline
┌─────────────────────────────────────────────────────────────────┐
│ release-suite.yml │
│ (suite-* tag OR manual) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ parse-tag (if push event) ────────────────────────────────┐ │
│ │ │ │
│ ▼ │ │
│ validate ─────────────────────────────────────────────────┤ │
│ │ │ │
│ ▼ │ │
│ test-gate (optional, skip with skip_tests=true) ──────────┤ │
│ │ │ │
│ ├───▶ build-modules (Matrix: 9 modules) │ │
│ │ ├── Authority │ │
│ │ ├── Scanner │ │
│ │ ├── Concelier │ │
│ │ ├── Excititor │ │
│ │ ├── SbomService │ │
│ │ ├── EvidenceLocker │ │
│ │ ├── Policy │ │
│ │ ├── Attestor │ │
│ │ └── VexLens │ │
│ │ │ │
│ ├───▶ build-containers (Matrix: 9 images) │ │
│ │ │ │
│ ├───▶ build-cli (Matrix: 5 runtimes) │ │
│ │ ├── linux-x64 │ │
│ │ ├── linux-arm64 │ │
│ │ ├── win-x64 │ │
│ │ ├── osx-x64 │ │
│ │ └── osx-arm64 │ │
│ │ │ │
│ └───▶ build-helm │ │
│ │ │
│ ◀────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ release-manifest ─────────────────────────────────────────┐ │
│ │ │ │
│ ├───▶ generate-changelog │ │
│ ├───▶ generate-suite-docs │ │
│ └───▶ generate-compose │ │
│ │ │
│ ◀────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ create-release ───────────────────────────────────────────┐ │
│ │ │ │
│ ▼ │ │
│ commit-docs ──────────────────────────────────────────────┤ │
│ │ │ │
│ ▼ │ │
│ summary ◀─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Conditional Execution Patterns
Branch-Based Conditions
# Deploy only on main branch
deploy:
if: github.ref == 'refs/heads/main'
# Run on main or develop
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/develop'
# Skip on release branches
if: "!startsWith(github.ref, 'refs/heads/release/')"
Event-Based Conditions
# Different behavior based on trigger
steps:
- name: Full scan (schedule)
if: github.event_name == 'schedule'
run: ./scan.sh --full
- name: Quick scan (PR)
if: github.event_name == 'pull_request'
run: ./scan.sh --quick
Input-Based Conditions
# Run extended tests if requested
extended-tests:
if: >-
github.event_name == 'schedule' ||
github.event.inputs.include_performance == 'true' ||
github.event.inputs.include_benchmark == 'true'
Failure-Based Conditions
# Run cleanup on failure
cleanup:
if: failure()
# Run notification always
notify:
if: always()
# Run only on success
deploy:
if: success()
Complex Conditions
# Deploy gate: multiple conditions
deploy:
if: >-
needs.build-test.result == 'success' &&
needs.docs.result == 'success' &&
needs.scanner-perf.result == 'success' &&
((github.event_name == 'push' && github.ref == 'refs/heads/main') ||
github.event_name == 'workflow_dispatch')
Path Filters Reference
Common Path Patterns
| Pattern | Matches | Example Files |
|---|---|---|
src/** |
All source code | src/Scanner/Program.cs |
docs/** |
All documentation | docs/api/openapi.yaml |
*.md |
Root markdown | README.md, CHANGELOG.md |
**/*.csproj |
All project files | src/Cli/StellaOps.Cli.csproj |
devops/** |
DevOps config | devops/helm/values.yaml |
.gitea/workflows/** |
Workflow files | .gitea/workflows/test-matrix.yml |
Path Filter Examples
# Source code changes only
paths:
- 'src/**'
- '!src/**/*.md' # Exclude markdown in src
# Documentation only
paths:
- 'docs/**'
- '*.md'
- 'scripts/render_docs.py'
# Security-relevant files
paths:
- 'src/**/*.cs'
- 'src/**/*.csproj'
- '**/Dockerfile*'
- '.gitea/workflows/sast-scan.yml'
# Dependency files
paths:
- 'src/Directory.Packages.props'
- '**/package.json'
- '**/package-lock.json'
- '**/*.csproj'
Tag Patterns Reference
Semantic Version Tags
# Standard releases
tags:
- 'v*' # v1.0.0, v2025.12.1, v2025.12.0-edge
# Channel-specific
tags:
- 'v*-edge' # v2025.12.0-edge
- 'v*-stable' # v2025.12.0-stable
- 'v*-lts' # v2025.12.0-lts
Suite Tags
tags:
- 'suite-*' # suite-2026.04, suite-2026.10
Module Tags
tags:
- 'module-*-v*' # module-authority-v1.2.3
# module-scanner-v2.0.0
# module-cli-v3.1.0
Workflow Inputs Reference
Common Input Types
workflow_dispatch:
inputs:
# String input
version:
description: 'Version to release'
required: true
type: string
# Choice input
environment:
description: 'Target environment'
type: choice
options:
- staging
- production
default: staging
# Boolean input
dry_run:
description: 'Run without making changes'
type: boolean
default: false
# Multi-select (via string)
rids:
description: 'Runtime identifiers (comma-separated)'
type: string
default: 'linux-x64,linux-arm64,win-x64'
Accessing Inputs
steps:
- name: Use input
run: |
echo "Version: ${{ github.event.inputs.version }}"
echo "Environment: ${{ inputs.environment }}"
if [[ "${{ inputs.dry_run }}" == "true" ]]; then
echo "Dry run mode"
fi
Best Practices
1. Minimize PR Workflow Duration
# Use path filters to skip irrelevant runs
paths-ignore:
- 'docs/**'
- '*.md'
- 'LICENSE'
# Use concurrency to cancel outdated runs
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
2. Fail Fast for Critical Issues
strategy:
fail-fast: true # Stop all jobs if one fails
matrix:
category: [Unit, Integration, Security]
3. Use Matrix for Parallel Execution
strategy:
matrix:
include:
- category: Unit
timeout: 20
- category: Integration
timeout: 45
4. Preserve Artifacts
- uses: actions/upload-artifact@v4
with:
name: test-results-${{ matrix.category }}
path: ./TestResults
retention-days: 14 # PR artifacts
# retention-days: 90 # Release artifacts
5. Use Conditional Steps
- name: Deploy (main only)
if: github.ref == 'refs/heads/main'
run: ./deploy.sh
- name: Notify on failure
if: failure()
run: ./notify-slack.sh
Troubleshooting Triggers
Workflow Not Running
- Check branch protection rules - Ensure workflow runs are allowed
- Verify path filters - File changes must match
pathspatterns - Check
ifconditions - Job may be skipped by condition - Review concurrency settings - May be cancelled by concurrent run
Workflow Running Unexpectedly
- Check
paths-ignore- May need to exclude more paths - Review schedule - Cron schedule may overlap with events
- Check tag patterns - Tag may match unexpected pattern
Schedule Not Triggering
- Verify cron syntax - Use crontab.guru
- Check workflow file location - Must be on default branch
- Review repository activity - Inactive repos may have schedules disabled
Trigger Decision Tree
Use this decision tree to determine which workflows run for each event:
On PUSH to branch:
│
├── Is branch main/develop?
│ ├── YES → Run Category A (PR-Gating) + B (Main-Only) + affected C (Module)
│ └── NO (feature branch) → Skip CI (rely on PR workflow)
│
On PULL REQUEST:
│
├── Check changed paths
│ ├── docs/** only → Skip all (or run docs.yml only)
│ ├── src/** changed → Run Category A + affected C modules
│ └── *.csproj or *.props changed → Run Category A + B (full infrastructure)
│
On TAG push:
│
├── Match tag pattern
│ ├── suite-* → release-suite.yml
│ ├── module-*-v* → module-publish.yml
│ ├── service-*-v* → service-release.yml
│ ├── v*.*.* → containers-multiarch.yml + cli-build.yml
│ └── Other → Ignore
│
On SCHEDULE:
│
└── Run Category E pipelines per cron schedule
Smart Dependency Cascading
When shared libraries change, dependent module tests must also run:
Dependency Graph
SHARED LIBRARY TRIGGERS TESTS FOR
─────────────────────────────────────────────────────────────────
StellaOps.Cryptography* → ALL modules (security-critical)
- Scanner, Attestor, Authority
- EvidenceLocker, Signer
- AirGap, Offline tests
- Security test suite
StellaOps.Evidence* → Scanner, Attestor, EvidenceLocker
StellaOps.Provenance → ExportCenter, SbomService
StellaOps.Infrastructure.* → ALL integration tests
StellaOps.Postgres* (database-dependent modules)
StellaOps.Replay* → Scanner, Determinism tests
StellaOps.Determinism Replay module tests
StellaOps.Verdict → Policy, RiskEngine, ReachGraph
StellaOps.DeltaVerdict
StellaOps.Plugin → Authority, Scanner, Concelier
(plugin-based modules)
Directory.Build.props → ALL modules (build config)
Directory.Packages.props ALL tests
nuget.config
Cascade Implementation
Each workflow includes paths from its dependencies:
# Example: scanner-ci.yml with cascading
name: Scanner CI
on:
push:
branches: [main]
paths:
# Direct module paths
- 'src/Scanner/**'
- 'src/BinaryIndex/**'
# Shared library dependencies (cascading)
- 'src/__Libraries/StellaOps.Evidence*/**'
- 'src/__Libraries/StellaOps.Cryptography*/**'
- 'src/__Libraries/StellaOps.Replay*/**'
- 'src/__Libraries/StellaOps.Provenance/**'
# Infrastructure (triggers full test)
- 'Directory.Build.props'
- 'Directory.Packages.props'
Cascade Matrix Quick Reference
| When This Changes | Run These Tests |
|---|---|
src/__Libraries/StellaOps.Cryptography*/** |
Scanner, Attestor, Authority, Evidence, Signer, AirGap, Security |
src/__Libraries/StellaOps.Evidence*/** |
Scanner, Attestor, EvidenceLocker, Export |
src/__Libraries/StellaOps.Infrastructure*/** |
ALL integration tests |
src/__Libraries/StellaOps.Replay*/** |
Scanner, Determinism, Replay |
src/__Libraries/StellaOps.Verdict/** |
Policy, RiskEngine, ReachGraph |
src/__Libraries/StellaOps.Plugin/** |
Authority, Scanner, Concelier |
Directory.Build.props |
ALL modules |
Master Trigger Configuration
Complete Workflow Trigger Table
| Workflow | Feature Branch | PR | Main Push | Tag | Schedule |
|---|---|---|---|---|---|
| Category A: PR-Gating | |||||
| build-test-deploy.yml | ❌ | ✅ | ✅ | ❌ | ✅ Daily |
| test-matrix.yml | ❌ | ✅ | ✅ | ❌ | ✅ Daily |
| determinism-gate.yml | ❌ | ✅ | ✅ | ❌ | ❌ |
| policy-lint.yml | ❌ | ✅* | ✅* | ❌ | ❌ |
| sast-scan.yml | ❌ | ✅ | ✅ | ❌ | ✅ Weekly |
| secrets-scan.yml | ❌ | ✅ | ✅ | ❌ | ❌ |
| dependency-license-gate.yml | ❌ | ✅* | ❌ | ❌ | ❌ |
| Category B: Main-Only | |||||
| container-scan.yml | ❌ | ❌ | ✅* | ❌ | ✅ Daily |
| integration-tests-gate.yml | ❌ | ❌ | ✅ | ❌ | ❌ |
| api-governance.yml | ❌ | ✅* | ✅* | ❌ | ❌ |
| aoc-guard.yml | ❌ | ✅* | ✅* | ❌ | ❌ |
| provenance-check.yml | ❌ | ❌ | ✅ | ❌ | ❌ |
| Category C: Module-Specific | |||||
| scanner-*.yml | ❌ | ✅* | ✅* | ❌ | ❌ |
| concelier-*.yml | ❌ | ✅* | ✅* | ❌ | ❌ |
| authority-*.yml | ❌ | ✅* | ✅* | ❌ | ❌ |
| findings-ledger-ci.yml | ❌ | ✅* | ✅* | ❌ | ❌ |
| evidence-locker.yml | ❌ | ❌ | ❌ | ❌ | ❌ (manual) |
| [all module-*.yml] | ❌ | ✅* | ✅* | ❌ | ❌ |
| Category D: Release | |||||
| release-suite.yml | ❌ | ❌ | ❌ | ✅ suite-* | ❌ |
| module-publish.yml | ❌ | ❌ | ❌ | ✅ module--v | ❌ |
| service-release.yml | ❌ | ❌ | ❌ | ✅ service--v | ❌ |
| release.yml | ❌ | ❌ | ❌ | ✅ v* | ❌ |
| cli-build.yml | ❌ | ❌ | ❌ | ❌ | ❌ (manual) |
| containers-multiarch.yml | ❌ | ❌ | ❌ | ❌ | ❌ (manual) |
| rollback.yml | ❌ | ❌ | ❌ | ❌ | ❌ (manual) |
| promote.yml | ❌ | ❌ | ❌ | ❌ | ❌ (manual) |
| Category E: Scheduled | |||||
| nightly-regression.yml | ❌ | ❌ | ❌ | ❌ | ✅ 2AM |
| dependency-security-scan.yml | ❌ | ✅* | ❌ | ❌ | ✅ Sun 2AM |
| container-scan.yml | ❌ | ❌ | ✅* | ❌ | ✅ 4AM |
| renovate.yml | ❌ | ❌ | ❌ | ❌ | ✅ 3AM/3PM |
| migration-test.yml | ❌ | ❌ | ❌ | ❌ | ✅ 4:30AM |
Legend: ✅ = with path filter, ✅ = always, ❌ = never*