-
Notifications
You must be signed in to change notification settings - Fork 4.4k
12.2 CI CD Workflows
Relevant source files
The following files were used as context for generating this wiki page:
This document provides a technical reference for all GitHub Actions workflows in the ZeroClaw CI/CD pipeline. It covers workflow architecture, trigger patterns, merge gate logic, security gates, and troubleshooting procedures. For PR review procedures and collaboration governance, see PR Workflow. For code ownership and review responsibilities, see Code Ownership.
Sources: docs/ci-map.md:1-115
The ZeroClaw CI/CD system uses a three-tier workflow architecture: merge-blocking gates, non-blocking validation, and optional automation. This design keeps the critical merge path fast and deterministic while enabling extensive quality checks and repository automation.
graph TB
subgraph "Tier 1: Merge-Blocking Gates"
CI["ci-run.yml<br/>(CI Required Gate)"]
Sanity["workflow-sanity.yml<br/>(Workflow Sanity)"]
Intake["pr-intake-checks.yml<br/>(PR Intake Checks)"]
end
subgraph "Tier 2: Non-Blocking Validation"
Docker["pub-docker-img.yml<br/>(Docker)"]
SecAudit["sec-audit.yml<br/>(Security Audit)"]
CodeQL["sec-codeql.yml<br/>(CodeQL Analysis)"]
Release["pub-release.yml<br/>(Release)"]
LabelPolicy["pr-label-policy-check.yml<br/>(Label Policy Sanity)"]
RustReusable["test-rust-build.yml<br/>(Rust Reusable Job)"]
end
subgraph "Tier 3: Optional Automation"
Labeler["pr-labeler.yml<br/>(PR Labeler)"]
AutoResponse["pr-auto-response.yml<br/>(PR Auto Responder)"]
Stale["pr-check-stale.yml<br/>(Stale)"]
Hygiene["pr-check-status.yml<br/>(PR Hygiene)"]
Dependabot["dependabot.yml<br/>(Dependabot)"]
end
PR[Pull Request] --> Intake
Intake --> CI
CI --> Sanity
PR -.optional.-> Docker
PR -.optional.-> SecAudit
PR -.optional.-> CodeQL
PR --> Labeler
PR --> AutoResponse
Schedule[Scheduled Events] --> Stale
Schedule --> Hygiene
Schedule --> Dependabot
Tag[Tag Push v*] --> Release
Main[Push to main] --> Docker
Main --> SecAudit
Sources: docs/ci-map.md:7-37, docs/ci-map.md:66-79
The ci-run.yml workflow is the primary merge gate, running comprehensive Rust validation and documentation quality checks.
| Job | Purpose | Scope |
|---|---|---|
cargo fmt |
Code formatting | All Rust files with --check flag |
cargo clippy |
Linter correctness | All targets with -D clippy::correctness
|
lint-strict-delta |
Strict lint on changes | Changed Rust lines only via ./scripts/ci/rust_strict_delta_gate.sh
|
cargo test |
Unit and integration tests | All test targets with --locked
|
release build |
Release compilation smoke | Build with release profile |
docs-quality |
Markdown linting | Changed lines only via ./scripts/ci/docs_quality_gate.sh
|
link-check |
Link validation | Added links only via ./scripts/ci/collect_changed_links.py
|
-
Workflow Owner Approval: PRs changing
.github/workflows/**require approval fromWORKFLOW_OWNER_LOGINS(repository variable, fallback:theonlyhennygod,willsarg) - Actionable Feedback: When lint/docs gates fail on PRs, CI posts a comment with failing gate names and local fix commands
- Docs Fast Path: Docs-only PRs skip heavy Rust jobs for faster feedback
Execution Order: Lint gates run before test/build to provide fast feedback on formatting issues.
Sources: docs/ci-map.md:13-17, docs/ci-map.md:95-100
Validates GitHub Actions workflow files for syntax errors and policy compliance.
graph LR
WorkflowChange["Workflow File Change"] --> TabCheck["no-tabs job"]
TabCheck --> ActionLint["actionlint job"]
TabCheck --> CheckTabs["Check .github/workflows/**<br/>for tab characters"]
ActionLint --> LintSyntax["rhysd/actionlint@v1.7.11<br/>syntax and schema validation"]
Trigger Paths:
.github/workflows/**.github/*.yml.github/*.yaml
Sources: .github/workflows/workflow-sanity.yml:1-65, docs/ci-map.md:18-20
Runs safe pre-CI validation checks with immediate sticky feedback for common issues.
| Check | Detection | Trigger Event |
|---|---|---|
| Template completeness | Missing PR template sections |
pull_request_target opened/synchronize |
| Added-line tabs | Tab characters in diff | All PR events |
| Trailing whitespace | Line-end whitespace in diff | All PR events |
| Conflict markers |
<<<<<<<, =======, >>>>>>>
|
All PR events |
Security Model: Uses pull_request_target for write access to post feedback comments, but operates only on safe metadata (no code execution).
Sources: docs/ci-map.md:21-22
Builds and publishes Docker images with a PR smoke check path.
graph TB
Trigger{Trigger Type}
Trigger -->|PR| PRSmoke["pr-smoke job<br/>Build image only"]
Trigger -->|Push to main| MainPublish["build-and-publish job<br/>Push to registry"]
Trigger -->|Tag v*| TagPublish["build-and-publish job<br/>Push with version tag"]
Trigger -->|Manual dispatch| ManualPublish["build-and-publish job<br/>Push to registry"]
PRSmoke --> BuildCheck["Multi-stage Dockerfile<br/>verify build succeeds"]
MainPublish --> Registry["Container Registry"]
TagPublish --> Registry
ManualPublish --> Registry
Build Input Paths: Docker build triggers only when relevant files change (Rust source, Cargo files, Dockerfile, scripts).
Sources: docs/ci-map.md:26-27, docs/ci-map.md:69
Runs dependency security checks and policy validation.
| Component | Tool | Purpose |
|---|---|---|
| Advisory check |
rustsec/audit-check (pinned SHA) |
CVE detection in dependencies |
| License check | cargo deny |
License policy enforcement |
| Policy check | cargo deny |
Dependency policy validation |
Trigger Pattern: Push to main, PRs to main, weekly schedule.
Sources: docs/ci-map.md:28-29, docs/ci-map.md:71
Scheduled static analysis for security findings using GitHub's CodeQL engine.
Execution: Manual dispatch or scheduled runs (no PR blocking).
Sources: docs/ci-map.md:30-31
Builds release artifacts and publishes GitHub releases on version tags.
Trigger: Tag push matching v* pattern.
Artifacts: Compiled binaries for supported platforms.
Sources: docs/ci-map.md:32-33, docs/ci-map.md:70
Validates that shared contributor-tier policy in .github/label-policy.json matches usage in label workflows.
Validation: Ensures pr-labeler.yml and pr-auto-response.yml consume the same tier thresholds.
Sources: docs/ci-map.md:34-35, docs/ci-map.md:74
Reusable workflow providing standardized Rust setup, caching, and command execution for workflow-call consumers.
Purpose: DRY pattern for Rust CI jobs across multiple workflows.
Sources: docs/ci-map.md:36-37
Applies comprehensive auto-labeling to PRs based on changed paths, size, risk heuristics, and contributor history.
| Category | Label Pattern | Source |
|---|---|---|
| Scope/Path |
channel:*, provider:*, tool:*, gateway, security
|
Changed file paths |
| Size | size: XS/S/M/L/XL |
Effective changed lines |
| Risk | risk: low/medium/high |
Path heuristics |
| Module | <module>: <component> |
Fine-grained path mapping |
| Contributor Tier | trusted/experienced/principal/distinguished |
Merged PR count (>=5/>=10/>=20/>=50) |
-
Hierarchical De-duplication: When a specific module label is present (e.g.,
tool:composio), less specific labels (tool:core,tool) are removed -
Module Namespace Compaction: One specific module keeps
prefix:component; multiple specifics collapse to baseprefix -
Provider Keyword Promotion: Provider names in diffs promote to
provider:*labels (e.g.,provider:kimi,provider:deepseek) -
Priority Sorting:
risk:*→size:*→ contributor tier → module/path labels - Managed Label Colors: Arranged by display order for smooth visual gradient
- Auto-Managed Descriptions: Hover tooltips explain auto-judgment rules
-
Risk Auto-Correction: Manual label edits trigger risk recalculation unless
risk: manualis applied
| Path Pattern | Risk Level |
|---|---|
src/security/** |
High |
src/runtime/** |
High |
src/gateway/** |
High |
src/tools/** |
High |
.github/workflows/** |
High |
Manual Governance: Supports workflow_dispatch with mode=audit|repair for repository-wide label metadata inspection and normalization.
Sources: docs/ci-map.md:41-52, docs/pr-workflow.md:113-119
Handles first-time contributor onboarding and label-driven response routing.
| Label | Behavior | Target |
|---|---|---|
r:support |
Route to community support | Issues only |
r:needs-repro |
Request deterministic reproduction | Issues only |
invalid / duplicate
|
Auto-close with guidance | Issues only |
Applies contributor tiers on issues using the same thresholds as pr-labeler.yml:
-
trusted>= 5 merged PRs -
experienced>= 10 merged PRs -
principal>= 20 merged PRs -
distinguished>= 50 merged PRs
Guardrails:
- Contributor-tier labels are automation-managed (manual add/remove is auto-corrected)
- Label-based close routes are issue-only; PRs are never auto-closed by route labels
Sources: docs/ci-map.md:54-58, docs/pr-workflow.md:119
Stale issue/PR lifecycle automation for queue health maintenance.
Execution: Daily schedule, manual dispatch.
Override: Maintainers apply no-stale to preserve accepted-but-blocked work.
Sources: docs/ci-map.md:59-60, docs/ci-map.md:77
Nudges stale-but-active PRs to rebase or re-run required checks before queue starvation.
Check Criteria: PR has no new commits for 48+ hours AND is either behind main OR missing/failing CI Required Gate on head commit.
Execution: Every 12 hours schedule, manual dispatch.
Sources: docs/ci-map.md:63-64, docs/ci-map.md:79, docs/pr-workflow.md:216
Grouped, rate-limited dependency update PRs for Cargo and GitHub Actions.
Schedule: Weekly maintenance windows.
Grouping: Dependencies are batched to reduce PR volume.
Sources: docs/ci-map.md:61-62, docs/ci-map.md:78
| Workflow | Push to main | PR to main | Tag v* | Schedule | Manual Dispatch |
|---|---|---|---|---|---|
ci-run.yml |
✓ | ✓ | - | - | - |
workflow-sanity.yml |
✓ (path filter) | ✓ (path filter) | - | - | - |
pr-intake-checks.yml |
- | ✓ (pull_request_target) | - | - | - |
pub-docker-img.yml |
✓ (path filter) | ✓ (path filter) | ✓ | - | ✓ |
sec-audit.yml |
✓ | ✓ | - | Weekly | - |
sec-codeql.yml |
- | - | - | Scheduled | ✓ |
pub-release.yml |
- | - | ✓ | - | - |
pr-label-policy-check.yml |
✓ (path filter) | ✓ (path filter) | - | - | - |
pr-labeler.yml |
- | ✓ (pull_request_target) | - | - | ✓ |
pr-auto-response.yml |
- | ✓ (issue/PR opened/labeled) | - | - | - |
pr-check-stale.yml |
- | - | - | Daily | ✓ |
pr-check-status.yml |
- | - | - | Every 12h | ✓ |
Sources: docs/ci-map.md:66-79
graph TB
PROpen["PR opened to main"] --> Intake["pr-intake-checks.yml"]
PROpen --> Labeler["pr-labeler.yml"]
PROpen --> AutoResponse["pr-auto-response.yml"]
PROpen --> CI["ci-run.yml"]
PROpen --> Sanity["workflow-sanity.yml<br/>(if workflow files changed)"]
PROpen --> Docker["pub-docker-img.yml<br/>(if Docker inputs changed)"]
PROpen --> SecAudit["sec-audit.yml"]
PRSync["PR synchronized"] --> Intake
PRSync --> Labeler
PRSync --> CI
PRSync --> Sanity
PRSync --> Docker
PRSync --> SecAudit
MainPush["Push to main"] --> CI
MainPush --> Docker
MainPush --> SecAudit
MainPush --> Sanity
TagPush["Tag push v*"] --> Release["pub-release.yml"]
TagPush --> Docker
IssueOpen["Issue opened"] --> AutoResponse
IssueLabel["Issue/PR labeled"] --> AutoResponse
Sources: docs/ci-map.md:66-79
graph TB
Code["Code Change"] --> Layer1["Layer 1: Pre-CI Intake"]
Layer1 --> TemplateCheck["Template completeness<br/>pr-intake-checks.yml"]
Layer1 --> TabCheck["Tab detection<br/>pr-intake-checks.yml"]
Layer1 --> WhitespaceCheck["Trailing whitespace<br/>pr-intake-checks.yml"]
Layer1 --> ConflictCheck["Conflict markers<br/>pr-intake-checks.yml"]
Layer1 --> Layer2["Layer 2: Rust Quality"]
Layer2 --> FmtCheck["cargo fmt --check<br/>ci-run.yml"]
Layer2 --> ClippyCheck["cargo clippy -D correctness<br/>ci-run.yml"]
Layer2 --> DeltaLint["rust_strict_delta_gate.sh<br/>Changed lines only"]
Layer2 --> Layer3["Layer 3: Functional Validation"]
Layer3 --> TestCheck["cargo test --locked<br/>ci-run.yml"]
Layer3 --> BuildCheck["cargo build --release<br/>ci-run.yml"]
Layer3 --> Layer4["Layer 4: Documentation Quality"]
Layer4 --> MarkdownLint["docs_quality_gate.sh<br/>Changed lines only"]
Layer4 --> LinkCheck["collect_changed_links.py + lychee<br/>Added links only"]
Layer4 --> Layer5["Layer 5: Workflow Governance"]
Layer5 --> WorkflowOwner["WORKFLOW_OWNER_LOGINS approval<br/>for .github/workflows/** changes"]
Layer5 --> ActionlintCheck["actionlint<br/>workflow-sanity.yml"]
Layer5 --> MergeGate["CI Required Gate<br/>Merge Allowed"]
Sources: docs/ci-map.md:13-17, docs/ci-map.md:95-100
The CI system uses incremental validation for merge gates to keep feedback fast, while supporting full audits for periodic cleanup.
| Check | Merge Gate Scope | Full Audit Command |
|---|---|---|
| Rust strict lint | Changed lines only | ./dev/ci.sh lint-strict |
| Markdown lint | Changed lines only |
./scripts/ci/docs_quality_gate.sh (reports baseline) |
| Link check | Added links only | Full lychee scan |
Rationale: Incremental gates prevent new issues while allowing gradual cleanup of baseline issues via focused PRs.
Sources: docs/ci-map.md:97-100
graph TB
Failure{Which Check Failed?}
Failure -->|CI Required Gate| CIRoute["Check ci-run.yml logs<br/>docs/ci-map.md Section 1"]
Failure -->|Docker| DockerRoute["Check pub-docker-img.yml<br/>pr-smoke job logs"]
Failure -->|Release| ReleaseRoute["Check pub-release.yml logs<br/>Tag validation"]
Failure -->|Security Audit| SecRoute["Check sec-audit.yml logs<br/>deny.toml policy"]
Failure -->|Workflow Sanity| SanityRoute["Check workflow-sanity.yml<br/>actionlint output"]
Failure -->|PR Intake| IntakeRoute["Check pr-intake-checks.yml<br/>sticky comment"]
Failure -->|Label Policy| LabelRoute["Check pr-label-policy-check.yml<br/>.github/label-policy.json"]
Failure -->|Docs Quality| DocsRoute["Check docs-quality job<br/>ci-run.yml logs"]
Failure -->|Strict Delta Lint| DeltaRoute["Check lint-strict-delta job<br/>Compare with BASE_SHA diff"]
CIRoute --> LocalRepro["Reproduce locally:<br/>./dev/ci.sh"]
DockerRoute --> LocalRepro
SecRoute --> LocalRepro
SanityRoute --> LocalRepro
DeltaRoute --> LocalRepro
Sources: docs/ci-map.md:81-92
-
Deterministic: Use
--lockedfor Cargo commands to ensure reproducibility -
Aligned: Keep quality policy synchronized across:
.github/workflows/ci-run.ymldev/ci.sh.githooks/pre-push./scripts/ci/rust_quality_gate.sh./scripts/ci/rust_strict_delta_gate.sh
-
Incremental Merge Gates: Use
./scripts/ci/rust_strict_delta_gate.shfor changed Rust lines -
Full Audit Path: Run
./dev/ci.sh lint-strictfor complete strict lint audit -
Docs Quality: Keep markdown gating incremental via
./scripts/ci/docs_quality_gate.sh -
Link Validation: Keep link checking incremental via
./scripts/ci/collect_changed_links.py+ lychee
Sources: docs/ci-map.md:93-106
- Explicit Permissions: Use least privilege for workflow permissions
-
Action Allowlist: Restrict action sources to approved allowlist patterns (see
docs/actions-source-policy.md) - Path Filters: Use path filters for expensive workflows when practical
- No Mixing: Avoid mixing onboarding/community automation with merge-gating logic
Sources: docs/ci-map.md:101-106
-
Deterministic Overrides: Support manual overrides (e.g.,
risk: manual) when automation lacks context - Deduplication: Keep auto-response comments deduplicated to prevent triage noise
- Issue-Only Auto-Close: Limit automated close behavior to issues; maintainers own PR close/merge decisions
- Label Correction: If automation is wrong, correct labels first, then continue review with explicit rationale
Sources: docs/ci-map.md:108-114, docs/pr-workflow.md:234-239
| Command | Purpose | CI Equivalent |
|---|---|---|
./dev/ci.sh |
Run all CI checks locally |
ci-run.yml (merge gate subset) |
./dev/ci.sh lint-delta |
Incremental strict lint |
lint-strict-delta job |
./dev/ci.sh lint-strict |
Full strict lint audit | Full audit (periodic cleanup) |
cargo fmt --all -- --check |
Format validation |
ci-run.yml fmt job |
cargo clippy --locked --all-targets -- -D clippy::correctness |
Lint validation |
ci-run.yml clippy job |
cargo test --locked |
Test execution |
ci-run.yml test job |
./scripts/ci/docs_quality_gate.sh |
Markdown quality |
docs-quality job |
./scripts/ci/collect_changed_links.py |
Changed link extraction |
link-check job (pre-lychee) |
Sources: docs/ci-map.md:95-100
Workflow files have dedicated owners to maintain governance over CI/CD changes:
| Path Pattern | Owner | Purpose |
|---|---|---|
/.github/workflows/** |
@theonlyhennygod @willsarg |
Workflow definitions |
/.github/codeql/** |
@willsarg |
CodeQL configuration |
/.github/dependabot.yml |
@willsarg |
Dependency automation |
/docs/ci-map.md |
@willsarg |
CI documentation |
/docs/actions-source-policy.md |
@willsarg |
Action security policy |
Additional Workflow Governance: PRs changing .github/workflows/** require at least one approving review from WORKFLOW_OWNER_LOGINS repository variable (fallback: theonlyhennygod,willsarg), enforced by ci-run.yml.
Sources: .github/CODEOWNERS:12-28, docs/ci-map.md:15
- Contributing - PR workflow and collaboration governance
- Testing - Testing strategy and test suite organization
- Code Ownership - Detailed CODEOWNERS structure
- Security Model - Five-layer security architecture
- Docker Deployment - Docker image structure and deployment
Sources: docs/ci-map.md:1-115, docs/pr-workflow.md:1-364