Skip to content

Contain source-upgrade process trees #8377

Contain source-upgrade process trees

Contain source-upgrade process trees #8377

Workflow file for this run

# PR quality pipeline.
#
# Keep fast checks direct. Test uses Homeboy Action's changed-scope routing;
# the workspace compile gate below covers every test target's wiring.
name: CI
on:
pull_request:
branches: [main]
# A closed PR starts one lightweight run in the existing concurrency group.
# That cancels an in-flight candidate DAG, while pr-state keeps this run from
# admitting the reusable workflow's binary, inventory, and shard jobs.
types: [opened, synchronize, reopened, closed]
workflow_dispatch:
concurrency:
group: ci-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
permissions:
actions: read
contents: write
pull-requests: write
issues: write
jobs:
# The event payload is authoritative for a closure run. Non-PR invocations
# remain active so manual CI and future push CI behavior are unchanged. Check
# out the default branch: the closure decision must not come from PR code.
pr-state:
name: homeboy / PR State
runs-on: ubuntu-latest
outputs:
active: ${{ steps.state.outputs.active }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.repository.default_branch }}
- name: Determine whether candidate work may start
id: state
env:
GITHUB_EVENT_NAME: ${{ github.event_name }}
GITHUB_EVENT_ACTION: ${{ github.event.action }}
run: bash .github/ci-pr-state.sh
# This repository owns how much work it asks the reusable workflow to admit.
# The action owns deterministic shard planning and aggregation, not this
# repository's GitHub-hosted runner budget.
ci-capacity-admission:
name: homeboy / CI Capacity Admission
needs: pr-state
if: ${{ needs.pr-state.outputs.active == 'true' }}
runs-on: ubuntu-latest
outputs:
test-shards: ${{ steps.admit.outputs.test-shards }}
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- id: admit
name: Admit configured Test capacity
run: bash .github/ci-capacity-admission.sh
# Named for what a green tick here actually proves: the DECLARATION is intact.
# It used to be called "Required Gates Policy" and run `--local`, which reads
# as "GitHub requires these checks" while only proving "ci.yml emits these
# job names" — PR #11069 merged nine minutes ahead of a red `homeboy / Test`
# under a green tick from this job, because the live ruleset requires nothing
# (#11084). `--report` additionally probes the live ruleset and annotates the
# enforcement outcome loudly, but never fails on it: enforcement is repository
# state a PR cannot change, and this repository merges fast on purpose, so
# this stays reporting and no PR is newly blocked by it.
required-gates-declaration:
name: homeboy / Required Gates Declaration
needs: pr-state
if: ${{ needs.pr-state.outputs.active == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Validate required check contexts and report live enforcement
env:
GH_TOKEN: ${{ github.token }}
run: bash .github/validate-required-gates.sh --report
# Non-differential safety net for crate-topology changes. The `review test`
# gate below is changed-file scoped, so a crate extraction that orphans a
# DONOR crate's test wiring (e.g. a test file left referencing a `super::foo`
# module after `foo` moved to its own crate) can pass unnoticed — the donor
# isn't in the changed scope. This job compiles EVERY crate's test target
# (codegen-free, so it's cheap) and fails closed if any of them break.
workspace-tests-compile:
name: homeboy / Workspace Tests Compile
needs: pr-state
if: ${{ needs.pr-state.outputs.active == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- uses: dtolnay/rust-toolchain@1.95.0
- name: Compile all workspace test targets
run: cargo check --workspace --tests --locked
warning-clean:
name: homeboy / Warning Clean
needs: pr-state
if: ${{ needs.pr-state.outputs.active == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- uses: dtolnay/rust-toolchain@1.95.0
- name: Build the shipped CLI without warnings
run: RUSTFLAGS=-Dwarnings cargo build --locked -p homeboy --bin homeboy
- name: Run a focused agent test without warnings
run: RUSTFLAGS=-Dwarnings cargo test --locked -p homeboy-agents --lib agent_task_timeout::tests::timeout_grace_is_bounded
# Unix-only `libc` constants (`SIGKILL` has no Windows definition) and other
# cfg-gating misses compile fine on Linux (#10398). The release has no Windows
# artifact consumer, so keep this codegen-free source check on every PR rather
# than paying for a native release build. Deliberately no `--tests`: some
# Unix-only test helpers rely on that boundary.
windows-compile:
name: homeboy / Windows Compile
needs: pr-state
if: ${{ needs.pr-state.outputs.active == 'true' }}
runs-on: windows-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- uses: dtolnay/rust-toolchain@1.95.0
- name: Check all workspace crates for Windows
run: cargo check --workspace --locked
# Keep `main` rustfmt-clean so a feature branch's `cargo fmt` only ever touches
# the files it changed. Without this gate, unformatted files drift onto main
# and get pulled into unrelated PRs (a bare `cargo fmt` reformats them, or a
# `rustfmt mod.rs` cascades across the module tree), ballooning otherwise-small
# diffs and forcing manual `git checkout --` of noise files (#6860). This is a
# non-differential whole-workspace check, so it catches drift anywhere.
rustfmt:
name: homeboy / Rustfmt
needs: pr-state
if: ${{ needs.pr-state.outputs.active == 'true' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- uses: dtolnay/rust-toolchain@1.95.0
with:
components: rustfmt
- name: Check workspace formatting
run: cargo fmt --all --check
homeboy-fast:
name: homeboy / ${{ matrix.title }}
needs: pr-state
if: ${{ needs.pr-state.outputs.active == 'true' }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- command: review audit
title: Audit
section_key: audit
section_title: Audit
# Audit and Lint are nowhere near their budget; leave them at the
# action defaults so raising the Test gate cannot mask a genuine
# hang in either of them.
execution_timeout_seconds: '1800'
test_timeout_seconds: '1500'
- command: review lint
title: Lint
section_key: lint
section_title: Lint
execution_timeout_seconds: '1800'
test_timeout_seconds: '1500'
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
fetch-depth: 0
- name: Check out Homeboy Action
uses: actions/checkout@v6
with:
repository: Extra-Chill/homeboy-action
ref: v2
path: .homeboy-action
- name: Generate GitHub App token
id: app-token
uses: actions/create-github-app-token@v3
continue-on-error: true
with:
client-id: ${{ secrets.HOMEBOY_APP_ID }}
private-key: ${{ secrets.HOMEBOY_APP_PRIVATE_KEY }}
- uses: ./.homeboy-action
with:
source: .
component: homeboy
commands: ${{ matrix.command }}
expected-commands: review audit,review lint,review test
differential-gating: true
execution-timeout-seconds: ${{ matrix.execution_timeout_seconds }}
app-token: ${{ steps.app-token.outputs.token || github.token }}
comment-section-key: ${{ matrix.section_key }}
comment-section-title: ${{ matrix.section_title }}
# The caller job name plus the called reconciliation job name preserves the
# required `homeboy / Test` context. PRs execute the affected test closure;
# ambiguous source changes fail closed or use Homeboy's full-scope fallback.
homeboy:
name: homeboy
needs: [pr-state, ci-capacity-admission]
if: ${{ needs.pr-state.outputs.active == 'true' }}
uses: Extra-Chill/homeboy-action/.github/workflows/ci.yml@v2
with:
commands: review test
# `review test` defaults to running the extension's pre-test lint, which
# for Rust is a full `cargo clippy` over the workspace. The `Lint` job in
# the homeboy-fast matrix above already runs `review lint`, so every shard
# was repeating work that is covered once, costing roughly three minutes
# each across all `test-shards`.
#
# This matches the umbrella `review` command, which sets `skip_lint: true`
# when building its test stage for the same reason, and matches
# release.yml, which already passes `--skip-lint` here.
args: --skip-lint
expected-commands: review audit,review lint,review test
component: homeboy
source: .
scope: auto
differential-gating: 'false'
baseline-commands: none
test-shards: ${{ needs.ci-capacity-admission.outputs.test-shards }}
execution-timeout-seconds: '1800'
test-timeout-seconds: '1500'
comment-section-key: test
comment-section-title: Test
secrets: inherit
ci-capacity-evidence:
name: homeboy / CI Capacity Evidence
needs: [required-gates-declaration, workspace-tests-compile, warning-clean, windows-compile, rustfmt, homeboy-fast, homeboy]
if: ${{ always() }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
- name: Publish queue, execution, and critical-path timing evidence
env:
GH_TOKEN: ${{ github.token }}
run: bash .github/ci-capacity-evidence.sh
- uses: actions/upload-artifact@v7
if: always()
with:
name: homeboy-ci-capacity-evidence-${{ github.run_attempt }}
path: ci-capacity-evidence.json
if-no-files-found: warn