Skip to content

12.2 CI CD Workflows

Nikolay Vyahhi edited this page Feb 19, 2026 · 4 revisions

CI/CD Workflows

Relevant source files

The following files were used as context for generating this wiki page:

Purpose and Scope

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


Workflow Architecture

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.

Workflow Tier Classification

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
Loading

Sources: docs/ci-map.md:7-37, docs/ci-map.md:66-79


Merge-Blocking Workflows

ci-run.yml (CI Required Gate)

The ci-run.yml workflow is the primary merge gate, running comprehensive Rust validation and documentation quality checks.

Validation Jobs

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

Special Behaviors

  1. Workflow Owner Approval: PRs changing .github/workflows/** require approval from WORKFLOW_OWNER_LOGINS (repository variable, fallback: theonlyhennygod,willsarg)
  2. Actionable Feedback: When lint/docs gates fail on PRs, CI posts a comment with failing gate names and local fix commands
  3. 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

workflow-sanity.yml (Workflow Sanity)

Validates GitHub Actions workflow files for syntax errors and policy compliance.

Validation Steps

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"]
Loading

Trigger Paths:

  • .github/workflows/**
  • .github/*.yml
  • .github/*.yaml

Sources: .github/workflows/workflow-sanity.yml:1-65, docs/ci-map.md:18-20

pr-intake-checks.yml (PR Intake Checks)

Runs safe pre-CI validation checks with immediate sticky feedback for common issues.

Check Categories

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


Non-Blocking Workflows

pub-docker-img.yml (Docker)

Builds and publishes Docker images with a PR smoke check path.

Execution Paths

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
Loading

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

sec-audit.yml (Security Audit)

Runs dependency security checks and policy validation.

Audit Components

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

sec-codeql.yml (CodeQL Analysis)

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

pub-release.yml (Release)

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

pr-label-policy-check.yml (Label Policy Sanity)

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

test-rust-build.yml (Rust Reusable Job)

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


Optional Automation Workflows

pr-labeler.yml (PR Labeler)

Applies comprehensive auto-labeling to PRs based on changed paths, size, risk heuristics, and contributor history.

Label Categories

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)

Advanced Behaviors

  1. Hierarchical De-duplication: When a specific module label is present (e.g., tool:composio), less specific labels (tool:core, tool) are removed
  2. Module Namespace Compaction: One specific module keeps prefix:component; multiple specifics collapse to base prefix
  3. Provider Keyword Promotion: Provider names in diffs promote to provider:* labels (e.g., provider:kimi, provider:deepseek)
  4. Priority Sorting: risk:*size:* → contributor tier → module/path labels
  5. Managed Label Colors: Arranged by display order for smooth visual gradient
  6. Auto-Managed Descriptions: Hover tooltips explain auto-judgment rules
  7. Risk Auto-Correction: Manual label edits trigger risk recalculation unless risk: manual is applied

High-Risk Path Heuristics

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

pr-auto-response.yml (PR Auto Responder)

Handles first-time contributor onboarding and label-driven response routing.

Response Routes

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

Contributor Tier Application

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

pr-check-stale.yml (Stale)

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

pr-check-status.yml (PR Hygiene)

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

Dependabot

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 Trigger Mapping

Trigger Reference Table

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

Event-by-Event Execution Flow

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
Loading

Sources: docs/ci-map.md:66-79


Security and Quality Gates

Multi-Layer Gate Architecture

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"]
Loading

Sources: docs/ci-map.md:13-17, docs/ci-map.md:95-100

Incremental vs Full Validation

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


Maintenance and Troubleshooting

Fast Triage Guide

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
Loading

Sources: docs/ci-map.md:81-92

Maintenance Rules

Merge-Blocking Check Requirements

  1. Deterministic: Use --locked for Cargo commands to ensure reproducibility
  2. Aligned: Keep quality policy synchronized across:
    • .github/workflows/ci-run.yml
    • dev/ci.sh
    • .githooks/pre-push
    • ./scripts/ci/rust_quality_gate.sh
    • ./scripts/ci/rust_strict_delta_gate.sh
  3. Incremental Merge Gates: Use ./scripts/ci/rust_strict_delta_gate.sh for changed Rust lines
  4. Full Audit Path: Run ./dev/ci.sh lint-strict for complete strict lint audit
  5. Docs Quality: Keep markdown gating incremental via ./scripts/ci/docs_quality_gate.sh
  6. Link Validation: Keep link checking incremental via ./scripts/ci/collect_changed_links.py + lychee

Sources: docs/ci-map.md:93-106

Workflow Security Policy

  1. Explicit Permissions: Use least privilege for workflow permissions
  2. Action Allowlist: Restrict action sources to approved allowlist patterns (see docs/actions-source-policy.md)
  3. Path Filters: Use path filters for expensive workflows when practical
  4. No Mixing: Avoid mixing onboarding/community automation with merge-gating logic

Sources: docs/ci-map.md:101-106

Automation Side-Effect Controls

  1. Deterministic Overrides: Support manual overrides (e.g., risk: manual) when automation lacks context
  2. Deduplication: Keep auto-response comments deduplicated to prevent triage noise
  3. Issue-Only Auto-Close: Limit automated close behavior to issues; maintainers own PR close/merge decisions
  4. 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

Local Development Commands

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


Code Ownership and Workflow Governance

CODEOWNERS Path Mapping

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


Related Documentation

Sources: docs/ci-map.md:1-115, docs/pr-workflow.md:1-364


Clone this wiki locally