chore(ci): document and harden workflow pipeline (#241)
* docs(ci): add CI workflow map and cross-links * chore(ci): harden workflow determinism and safety * chore(ci): address workflow review feedback * style(ci): normalize workflow and ci-map formatting
This commit is contained in:
parent
3014926687
commit
82ffb36f90
9 changed files with 322 additions and 260 deletions
35
.github/workflows/ci.yml
vendored
35
.github/workflows/ci.yml
vendored
|
|
@ -80,35 +80,14 @@ jobs:
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
with:
|
||||||
|
toolchain: 1.92
|
||||||
|
components: rustfmt, clippy
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
- name: Detect Rust source changes
|
|
||||||
id: rust_changes
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
if [ "${{ github.event_name }}" = "pull_request" ]; then
|
|
||||||
BASE="${{ github.event.pull_request.base.sha }}"
|
|
||||||
CHANGED="$(git diff --name-only "$BASE" HEAD -- '*.rs' || true)"
|
|
||||||
else
|
|
||||||
CHANGED="$(git diff --name-only "${{ github.event.before }}" HEAD -- '*.rs' || true)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$CHANGED" ]; then
|
|
||||||
echo "has_rust_changes=false" >> "$GITHUB_OUTPUT"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "has_rust_changes=true" >> "$GITHUB_OUTPUT"
|
|
||||||
- name: Run rustfmt
|
- name: Run rustfmt
|
||||||
if: steps.rust_changes.outputs.has_rust_changes == 'true'
|
|
||||||
run: cargo fmt --all -- --check
|
run: cargo fmt --all -- --check
|
||||||
- name: Run clippy
|
- name: Run clippy
|
||||||
if: steps.rust_changes.outputs.has_rust_changes == 'true'
|
run: cargo clippy --locked --all-targets -- -D warnings
|
||||||
run: cargo clippy --all-targets -- -D warnings
|
|
||||||
- name: Skip rust lint (no Rust changes)
|
|
||||||
if: steps.rust_changes.outputs.has_rust_changes != 'true'
|
|
||||||
run: echo "No Rust source changes detected; skipping rustfmt and clippy."
|
|
||||||
|
|
||||||
test:
|
test:
|
||||||
name: Test
|
name: Test
|
||||||
|
|
@ -119,9 +98,11 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
with:
|
||||||
|
toolchain: 1.92
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: cargo test --verbose
|
run: cargo test --locked --verbose
|
||||||
|
|
||||||
build:
|
build:
|
||||||
name: Build (Smoke)
|
name: Build (Smoke)
|
||||||
|
|
@ -133,6 +114,8 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
with:
|
||||||
|
toolchain: 1.92
|
||||||
- uses: Swatinem/rust-cache@v2
|
- uses: Swatinem/rust-cache@v2
|
||||||
- name: Build release binary
|
- name: Build release binary
|
||||||
run: cargo build --release --locked --verbose
|
run: cargo build --release --locked --verbose
|
||||||
|
|
|
||||||
2
.github/workflows/docker.yml
vendored
2
.github/workflows/docker.yml
vendored
|
|
@ -61,7 +61,7 @@ jobs:
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
name: Build and Push Docker Image
|
name: Build and Push Docker Image
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name == 'push'
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 25
|
timeout-minutes: 25
|
||||||
permissions:
|
permissions:
|
||||||
|
|
|
||||||
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
|
|
@ -14,7 +14,9 @@ jobs:
|
||||||
build-release:
|
build-release:
|
||||||
name: Build ${{ matrix.target }}
|
name: Build ${{ matrix.target }}
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
timeout-minutes: 40
|
||||||
strategy:
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
|
|
@ -73,6 +75,7 @@ jobs:
|
||||||
name: Publish Release
|
name: Publish Release
|
||||||
needs: build-release
|
needs: build-release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 15
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
|
|
||||||
10
.github/workflows/security.yml
vendored
10
.github/workflows/security.yml
vendored
|
|
@ -8,6 +8,13 @@ on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 6 * * 1" # Weekly on Monday 6am UTC
|
- cron: "0 6 * * 1" # Weekly on Monday 6am UTC
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: security-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
|
|
||||||
|
|
@ -15,10 +22,12 @@ jobs:
|
||||||
audit:
|
audit:
|
||||||
name: Security Audit
|
name: Security Audit
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 20
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
- uses: Swatinem/rust-cache@v2
|
||||||
|
|
||||||
- name: Install cargo-audit
|
- name: Install cargo-audit
|
||||||
run: cargo install --locked cargo-audit --version 0.22.1
|
run: cargo install --locked cargo-audit --version 0.22.1
|
||||||
|
|
@ -29,6 +38,7 @@ jobs:
|
||||||
deny:
|
deny:
|
||||||
name: License & Supply Chain
|
name: License & Supply Chain
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 20
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
|
|
||||||
2
.github/workflows/workflow-sanity.yml
vendored
2
.github/workflows/workflow-sanity.yml
vendored
|
|
@ -23,6 +23,7 @@ permissions:
|
||||||
jobs:
|
jobs:
|
||||||
no-tabs:
|
no-tabs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 10
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
@ -55,6 +56,7 @@ jobs:
|
||||||
|
|
||||||
actionlint:
|
actionlint:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 10
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ When PR traffic is high (especially with AI-assisted contributions), these rules
|
||||||
- **Security-first review**: changes in `src/security/`, runtime, and CI need stricter validation.
|
- **Security-first review**: changes in `src/security/`, runtime, and CI need stricter validation.
|
||||||
|
|
||||||
Full maintainer workflow: [`docs/pr-workflow.md`](docs/pr-workflow.md).
|
Full maintainer workflow: [`docs/pr-workflow.md`](docs/pr-workflow.md).
|
||||||
|
CI workflow ownership and triage map: [`docs/ci-map.md`](docs/ci-map.md).
|
||||||
|
|
||||||
## Agent Collaboration Guidance
|
## Agent Collaboration Guidance
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -441,6 +441,7 @@ MIT — see [LICENSE](LICENSE)
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
See [CONTRIBUTING.md](CONTRIBUTING.md). Implement a trait, submit a PR:
|
See [CONTRIBUTING.md](CONTRIBUTING.md). Implement a trait, submit a PR:
|
||||||
|
- CI workflow guide: [docs/ci-map.md](docs/ci-map.md)
|
||||||
- New `Provider` → `src/providers/`
|
- New `Provider` → `src/providers/`
|
||||||
- New `Channel` → `src/channels/`
|
- New `Channel` → `src/channels/`
|
||||||
- New `Observer` → `src/observability/`
|
- New `Observer` → `src/observability/`
|
||||||
|
|
|
||||||
60
docs/ci-map.md
Normal file
60
docs/ci-map.md
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
# CI Workflow Map
|
||||||
|
|
||||||
|
This document explains what each GitHub workflow does, when it runs, and whether it should block merges.
|
||||||
|
|
||||||
|
## Merge-Blocking vs Optional
|
||||||
|
|
||||||
|
Merge-blocking checks should stay small and deterministic. Optional checks are useful for automation and maintenance, but should not block normal development.
|
||||||
|
|
||||||
|
### Merge-Blocking
|
||||||
|
|
||||||
|
- `.github/workflows/ci.yml` (`CI`)
|
||||||
|
- Purpose: Rust validation (`fmt`, `clippy`, `test`, release build smoke)
|
||||||
|
- Merge gate: `CI Required Gate`
|
||||||
|
- `.github/workflows/workflow-sanity.yml` (`Workflow Sanity`)
|
||||||
|
- Purpose: lint GitHub workflow files (`actionlint`, tab checks)
|
||||||
|
- Recommended for workflow-changing PRs
|
||||||
|
|
||||||
|
### Non-Blocking but Important
|
||||||
|
|
||||||
|
- `.github/workflows/docker.yml` (`Docker`)
|
||||||
|
- Purpose: PR docker smoke check and publish images on `main`/tag pushes
|
||||||
|
- `.github/workflows/security.yml` (`Security Audit`)
|
||||||
|
- Purpose: dependency advisories (`cargo audit`) and policy/license checks (`cargo deny`)
|
||||||
|
- `.github/workflows/release.yml` (`Release`)
|
||||||
|
- Purpose: build tagged release artifacts and publish GitHub releases
|
||||||
|
|
||||||
|
### Optional Repository Automation
|
||||||
|
|
||||||
|
- `.github/workflows/labeler.yml` (`PR Labeler`)
|
||||||
|
- Purpose: path labels + size labels
|
||||||
|
- `.github/workflows/auto-response.yml` (`Auto Response`)
|
||||||
|
- Purpose: first-time contributor onboarding messages
|
||||||
|
- `.github/workflows/stale.yml` (`Stale`)
|
||||||
|
- Purpose: stale issue/PR lifecycle automation
|
||||||
|
|
||||||
|
## Trigger Map
|
||||||
|
|
||||||
|
- `CI`: push to `main`/`develop`, PRs to `main`
|
||||||
|
- `Docker`: push to `main`, tag push (`v*`), PRs touching docker/workflow files, manual dispatch
|
||||||
|
- `Release`: tag push (`v*`)
|
||||||
|
- `Security Audit`: push to `main`, PRs to `main`, weekly schedule
|
||||||
|
- `Workflow Sanity`: PR/push when `.github/workflows/**`, `.github/*.yml`, or `.github/*.yaml` change
|
||||||
|
- `PR Labeler`: `pull_request_target` lifecycle events
|
||||||
|
- `Auto Response`: issue opened, `pull_request_target` opened
|
||||||
|
- `Stale`: daily schedule, manual dispatch
|
||||||
|
|
||||||
|
## Fast Triage Guide
|
||||||
|
|
||||||
|
1. `CI Required Gate` failing: start with `.github/workflows/ci.yml`.
|
||||||
|
2. Docker failures on PRs: inspect `.github/workflows/docker.yml` `pr-smoke` job.
|
||||||
|
3. Release failures on tags: inspect `.github/workflows/release.yml`.
|
||||||
|
4. Security failures: inspect `.github/workflows/security.yml` and `deny.toml`.
|
||||||
|
5. Workflow syntax/lint failures: inspect `.github/workflows/workflow-sanity.yml`.
|
||||||
|
|
||||||
|
## Maintenance Rules
|
||||||
|
|
||||||
|
- Keep merge-blocking checks deterministic and reproducible (`--locked` where applicable).
|
||||||
|
- Prefer explicit workflow permissions (least privilege).
|
||||||
|
- Use path filters for expensive workflows when practical.
|
||||||
|
- Avoid mixing onboarding/community automation with merge-gating logic.
|
||||||
|
|
@ -9,6 +9,8 @@ This document defines how ZeroClaw handles high PR volume while maintaining:
|
||||||
- High sustainability
|
- High sustainability
|
||||||
- High security
|
- High security
|
||||||
|
|
||||||
|
Related reference: [`docs/ci-map.md`](ci-map.md) for per-workflow ownership, triggers, and triage flow.
|
||||||
|
|
||||||
## 1) Governance Goals
|
## 1) Governance Goals
|
||||||
|
|
||||||
1. Keep merge throughput predictable under heavy PR load.
|
1. Keep merge throughput predictable under heavy PR load.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue