Fix terminal rejected state-loss replacement #8232
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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 | |
| # 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 | |
| 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: '16' | |
| execution-timeout-seconds: '1800' | |
| test-timeout-seconds: '1500' | |
| comment-section-key: test | |
| comment-section-title: Test | |
| secrets: inherit |