# 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. ```yaml 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. ```yaml on: pull_request: branches: [main, develop] # Target branch filter types: [opened, synchronize, reopened] # Event types paths: - 'src/**' ``` ### 3. Schedule Triggers Cron-based scheduled execution. ```yaml 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. ```yaml on: workflow_dispatch: inputs: environment: type: choice options: [staging, production] dry_run: type: boolean default: false ``` ### 5. Workflow Call (Reusable) Called by other workflows. ```yaml 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 ```yaml # 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 ```yaml # 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 ```yaml # 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 ```yaml # Run cleanup on failure cleanup: if: failure() # Run notification always notify: if: always() # Run only on success deploy: if: success() ``` ### Complex Conditions ```yaml # 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 ```yaml # 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 ```yaml # 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 ```yaml tags: - 'suite-*' # suite-2026.04, suite-2026.10 ``` ### Module Tags ```yaml tags: - 'module-*-v*' # module-authority-v1.2.3 # module-scanner-v2.0.0 # module-cli-v3.1.0 ``` --- ## Workflow Inputs Reference ### Common Input Types ```yaml 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 ```yaml 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 ```yaml # 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 ```yaml strategy: fail-fast: true # Stop all jobs if one fails matrix: category: [Unit, Integration, Security] ``` ### 3. Use Matrix for Parallel Execution ```yaml strategy: matrix: include: - category: Unit timeout: 20 - category: Integration timeout: 45 ``` ### 4. Preserve Artifacts ```yaml - 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 ```yaml - 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 1. **Check branch protection rules** - Ensure workflow runs are allowed 2. **Verify path filters** - File changes must match `paths` patterns 3. **Check `if` conditions** - Job may be skipped by condition 4. **Review concurrency settings** - May be cancelled by concurrent run ### Workflow Running Unexpectedly 1. **Check `paths-ignore`** - May need to exclude more paths 2. **Review schedule** - Cron schedule may overlap with events 3. **Check tag patterns** - Tag may match unexpected pattern ### Schedule Not Triggering 1. **Verify cron syntax** - Use [crontab.guru](https://crontab.guru/) 2. **Check workflow file location** - Must be on default branch 3. **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: ```yaml # 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* --- ## Related Documentation - [README - CI/CD Overview](./README.md) - [Release Pipelines](./release-pipelines.md) - [Test Strategy](./test-strategy.md) - [Path Filters Reference](./path-filters.md) - [Troubleshooting](../../.gitea/docs/troubleshooting.md)