Skip to content

Restrict auto-rebase fan-out to review-ready PRs (free, plan-independent mitigation) #465

Closed

Description

@don-petry

Implements the fan-out restriction from petry-projects/.github-private epic #736 / story #738 (idea discussion #735). The auto-rebase reusable currently calls update-branch on every behind non-Dependabot PR, generating ~170–220 redundant branch-update CI runs/day, most re-staled before review.
Change: In .github/workflows/auto-rebase-reusable.yml, narrow the "find behind non-Dependabot same-repo PRs" step so it updates a PR only if it is non-draft AND (has an APPROVED review OR carries an auto-rebase:ready label). Expose the predicate as a tunable workflow input so a "front-of-queue N" variant can be selected without a code change.
Must preserve: the merge-method update (so approvals aren't invalidated) and the <!-- auto-rebase-conflict: sentinel path (the agentic conflict-resolution feature). Dependabot/fork handling unchanged.
Implementer note: check the actual APPROVED review state (not only reviewDecision, which can be null without required-reviews). Update the source-of-truth docs standards/workflows/auto-rebase.yml and standards/ci-standards.md.
Acceptance criteria mirror .github-private story #738.

Activity

  1. don-petry commented on Jun 15, 2026

    @don-petry
    ContributorAuthor

    Dev-Lead Implementation Plan

    Issue: #465 — Restrict auto-rebase fan-out to review-ready PRs (free, plan-independent mitigation)

    Scope

    Narrow .github/workflows/auto-rebase-reusable.yml so it only updates a PR that is non-draft AND (has an APPROVED review OR carries the auto-rebase:ready label), exposing the predicate as a tunable eligible_filter workflow input — while preserving the merge-method update, the <!-- auto-rebase-conflict: sentinel path, and unchanged Dependabot/fork handling.

    Implementation Checklist

    • .github/workflows/auto-rebase-reusable.yml — add eligible_filter input (default = review-ready predicate); replace candidate discovery with a single GraphQL query enriching each PR with isDraft, labels, and actual APPROVED review state (not reviewDecision), then apply the tunable predicate. Loop body (compare → update-branch merge → blocked/conflict sentinels) preserved verbatim.
    • .github/workflows/auto-rebase-tests.yml — new CI gate (shellcheck + bats) mirroring add-to-project-tests.yml.
    • standards/workflows/auto-rebase.yml — document the review-ready gate + tunable input in the header (source-of-truth template).
    • standards/ci-standards.md — update §8 (Auto-Rebase) to describe the gate and input.

    Tests to Write

    • test/workflows/auto-rebase/eligible-filter.bats + helpers/setup.bash — extract the eligible_filter default from the reusable YAML and assert classification against PR fixtures:
      • non-draft + APPROVED → eligible
      • non-draft + auto-rebase:ready label → eligible
      • non-draft + no approval + no label → excluded
      • draft (even if approved/labelled) → excluded
      • default filter over a mixed set selects exactly the review-ready PRs
      • a front-of-queue-style override filter selects a different subset (tunable without code change)

    Test Command

    bats --print-output-on-failure test/workflows/auto-rebase/

  2. added
    dev-leadFor dev-lead agent pickup
    and removed
    dev-leadFor dev-lead agent pickup
    on Jun 15, 2026
  3. don-petry commented on Jun 15, 2026

    @don-petry
    ContributorAuthor

    Dev-Lead Implementation Plan

    Issue: #465 — Restrict auto-rebase fan-out to review-ready PRs (free, plan-independent mitigation)

    Scope

    Narrow the auto-rebase reusable so it only updates a behind, non-Dependabot, same-repo PR when the PR is non-draft AND (has a current APPROVED review OR carries the auto-rebase:ready label), exposing the predicate as a tunable eligibility workflow input. Merge-method update, the <!-- auto-rebase-conflict: sentinel path, and Dependabot/fork handling are preserved unchanged.

    Implementation Checklist

    • Add .github/scripts/auto-rebase/lib/eligibility.sh — pure, sourceable predicate functions (auto_rebase_has_current_approval, auto_rebase_has_ready_label, auto_rebase_pr_eligible)
    • Add .github/scripts/auto-rebase/README.md — contract docs for the lib
    • Edit .github/workflows/auto-rebase-reusable.yml — add eligibility (default review-ready), ready_label (default auto-rebase:ready), and tooling_ref (default v1) inputs; checkout tooling; source the lib; gate update-branch on the predicate using the actual APPROVED review state (reviews API, not reviewDecision)
    • Add .github/workflows/auto-rebase-tests.yml — CI gate (shellcheck + bats), mirroring feature-ideation-tests.yml
    • Update standards/workflows/auto-rebase.yml — document the new gating + tunable input (thin caller unchanged functionally)
    • Update standards/ci-standards.md §8 — describe eligibility gating and the eligibility input

    Tests to Write

    • test/workflows/auto-rebase/eligibility.bats + helpers/setup.bash
    • auto_rebase_has_current_approval: APPROVED present; latest-per-reviewer wins (approve→changes_requested = not approved); dismissed approval excluded; COMMENTED ignored; empty array
    • auto_rebase_has_ready_label: label present / absent / empty labels
    • auto_rebase_pr_eligible: review-ready gates draft out; approved-only eligible; label-only eligible; neither = ineligible; all mode always eligible; unknown mode errors

    Test Command

    bats test/workflows/auto-rebase/ (full suite: bats -r test/)

  4. don-petry commented on Jun 15, 2026

    @don-petry
    ContributorAuthor

    Dev-Lead: Implementation Complete

    Plan Execution

    • Added pure, sourceable eligibility predicates (.github/scripts/auto-rebase/lib/eligibility.sh) + contract README
    • Wired the predicate into auto-rebase-reusable.yml behind a tunable eligibility input (checks out tooling, sources the lib, gates update-branch)
    • Approval determined from actual review states (latest decision review per reviewer wins), not reviewDecision
    • Preserved the merge-method update and the <!-- auto-rebase-conflict: sentinel path; Dependabot/fork handling unchanged
    • Added CI gate auto-rebase-tests.yml (shellcheck + bats)
    • Updated source-of-truth docs: standards/workflows/auto-rebase.yml and standards/ci-standards.md §8

    Behavior

    A behind, non-Dependabot, same-repo PR is now updated only when eligible:

    eligibility Updates a behind PR when…
    review-ready (default) non-draft AND (current APPROVED review OR carries ready_label, default auto-rebase:ready)
    all always (restores the prior unrestricted fan-out)

    New modes (e.g. "front-of-queue N") can be added to the lib and selected via the input with no workflow change.

    Test Results

    # bats test/workflows/auto-rebase/  → 18/18 pass
    ok 1 has_current_approval: single APPROVED review counts as approved
    ok 4 has_current_approval: reviewer who approved then requested changes is not approved
    ok 5 has_current_approval: reviewer who requested changes then approved is approved
    ok 7 has_current_approval: a dismissed approval is not approved
    ok 12 pr_eligible review-ready: non-draft + approved is eligible
    ok 13 pr_eligible review-ready: non-draft + ready label is eligible
    ok 15 pr_eligible review-ready: draft is ineligible even when approved
    ok 16 pr_eligible all: always eligible (legacy fan-out escape hatch)
    ok 18 pr_eligible: unknown mode errors out (exit 2)
    
    # Full suite: bats -r test/  → 220/220 pass
    # shellcheck -x .github/scripts/auto-rebase/lib/eligibility.sh → clean
    # bash .dev-lead/scripts/dev-lead-lint.sh → all checks passed
    # markdownlint-cli2 (README + ci-standards.md) → 0 errors
    

    Files Changed

    • .github/scripts/auto-rebase/lib/eligibility.sh (new): predicate functions
    • .github/scripts/auto-rebase/README.md (new): contract docs
    • .github/workflows/auto-rebase-reusable.yml: tunable inputs, tooling checkout, eligibility gate
    • .github/workflows/auto-rebase-tests.yml (new): shellcheck + bats CI gate
    • test/workflows/auto-rebase/eligibility.bats + helpers/setup.bash (new): unit tests
    • standards/workflows/auto-rebase.yml: documents the new gating + override inputs
    • standards/ci-standards.md: §8 updated with eligibility table and approval semantics

    Notes

    • Approval edge cases covered by tests: approve→changes-requested (not approved), changes-requested→approve (approved), later COMMENTED doesn't cancel approval, dismissed approval excluded, multi-reviewer.
    • The reusable now checks out petry-projects/.github@tooling_ref (default v1) to source the lib, matching the feature-ideation pattern. Existing thin-caller stubs need no change — all new inputs default to the restrictive behavior.
  5. added a commit that references this issue on Jun 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    dev-leadFor dev-lead agent pickup

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions