Files
Charon/docs/reports/archive/ci_sequencing_audit.md
akanealw eec8c28fb3
Some checks failed
Go Benchmark / Performance Regression Check (push) Has been cancelled
Cerberus Integration / Cerberus Security Stack Integration (push) Has been cancelled
Upload Coverage to Codecov / Backend Codecov Upload (push) Has been cancelled
Upload Coverage to Codecov / Frontend Codecov Upload (push) Has been cancelled
CodeQL - Analyze / CodeQL analysis (go) (push) Has been cancelled
CodeQL - Analyze / CodeQL analysis (javascript-typescript) (push) Has been cancelled
CrowdSec Integration / CrowdSec Bouncer Integration (push) Has been cancelled
Docker Build, Publish & Test / build-and-push (push) Has been cancelled
Quality Checks / Auth Route Protection Contract (push) Has been cancelled
Quality Checks / Codecov Trigger/Comment Parity Guard (push) Has been cancelled
Quality Checks / Backend (Go) (push) Has been cancelled
Quality Checks / Frontend (React) (push) Has been cancelled
Rate Limit integration / Rate Limiting Integration (push) Has been cancelled
Security Scan (PR) / Trivy Binary Scan (push) Has been cancelled
Supply Chain Verification (PR) / Verify Supply Chain (push) Has been cancelled
WAF integration / Coraza WAF Integration (push) Has been cancelled
Docker Build, Publish & Test / Security Scan PR Image (push) Has been cancelled
changed perms
2026-04-22 18:19:14 +00:00

3.7 KiB
Executable File

CI Sequencing Audit

Date: 2026-02-08

Scope

Audit target: .github/workflows/ci-pipeline.yml

Focus areas:

  • YAML syntax validity
  • Job if condition patterns for e2e, coverage-*, and security-*
  • Job dependency sequencing (Lint -> Build -> Integration -> Gate -> E2E/Rest)
  • Fork behavior (integration skipped, E2E still runs)

Results

YAML syntax

  • Visual inspection indicates valid YAML structure and indentation.
  • No duplicate keys or malformed mappings detected.

if condition pattern review

The following jobs implement always() and use a success || skipped guard on the integration gate:

  • e2e: always() plus needs.integration-gate.result == 'success' || ... == 'skipped', and needs.build-image.result == 'success'.
  • e2e-gate: always() plus needs.integration-gate.result == 'success' || ... == 'skipped'.
  • coverage-backend: always() plus needs.integration-gate.result == 'success' || ... == 'skipped'.
  • coverage-frontend: always() plus needs.integration-gate.result == 'success' || ... == 'skipped'.
  • coverage-gate: always() plus needs.integration-gate.result == 'success' || ... == 'skipped'.
  • codecov-upload: always() plus needs.integration-gate.result == 'success' || ... == 'skipped'.
  • codecov-gate: always() plus needs.integration-gate.result == 'success' || ... == 'skipped' and needs.codecov-upload.result != 'skipped'.
  • security-codeql: always() plus needs.integration-gate.result == 'success' || ... == 'skipped'.
  • security-trivy: always() plus needs.integration-gate.result == 'success' || ... == 'skipped', and needs.build-image.result == 'success'.
  • security-supply-chain: always() plus needs.integration-gate.result == 'success' || ... == 'skipped', and needs.build-image.result == 'success'.
  • security-gate: always() plus needs.integration-gate.result == 'success' || ... == 'skipped'.

Sequencing (Lint -> Build -> Integration -> Gate -> E2E/Rest)

  • build-image depends on lint, establishing Lint -> Build.
  • Integration jobs depend on build-image.
  • integration-gate depends on build-image and all integration jobs.
  • e2e depends on build-image and integration-gate.
  • Coverage and security jobs depend on integration-gate (but not directly on build-image).
  • pipeline-gate depends on all gates.

Fork logic (Integration Skip -> E2E Run)

  • Fork PRs set push_image=false, which makes run_integration=false.
  • Integration jobs and integration-gate are skipped.
  • e2e still runs because it allows integration-gate to be skipped and only requires build-image to succeed.

Findings

IMPORTANT: Coverage and security jobs can run after a skipped integration gate caused by failed build

If lint or build-image fail, integration-gate is skipped. The coverage and security jobs only check (needs.integration-gate.result == 'success' || ... == 'skipped'), so they can run even when the build failed. This weakens the strict sequence guarantee (Lint -> Build -> Integration -> Gate -> E2E/Rest) for these jobs.

Suggested fix:

  • Add needs.build-image.result == 'success' to coverage-*, coverage-gate, codecov-*, and security-codeql conditions, or require needs.build-image.result == 'success' at the integration-gate level and check for success (not skipped) where strict sequencing is required.

Conclusion

  • YAML syntax appears valid on inspection.
  • always() && (success || skipped) pattern is applied consistently for the targeted jobs.
  • Fork logic correctly skips integration and still runs E2E.
  • Sequencing is mostly correct, with the exception noted for coverage and security jobs when the integration gate is skipped due to an upstream failure.