Skip to content

Commit 7ce98d5

Browse files
authored
Add automation to reconcile release runner groups (#8332)
On-demand (and go-live-triggered) job that keeps the prod release runner groups (name matching `-prod-.*-release-runners`, e.g. `lf-prod-aws-ue1-release-runners`; staging clusters excluded) in sync, so we stop hand-editing their allowed-workflows and repo-access lists at each release milestone. `tools/scripts/release_manage_runner_groups.py` computes the desired state from pytorch/pytorch: - **Refs:** `main`, `nightly`, and the release branches around the release candidate version. The `release/X.Y` anchor is read from `generate_binary_build_matrix.py` (`CURRENT_CANDIDATE_VERSION`, the version used for release builds, advanced deliberately at go-live) rather than inferred from a branch-name scan; the preceding protected release branch is included too. - **Workflows (discovered by runner label, not hardcoded):** an entry workflow references a release runner label (the `rel-` marker, e.g. `rel-l-x86iavx512-44-340`); from there it follows `uses:` only into reusables invoked on a release label, so the build reusable (`_binary-build-linux`) is included while non-build/non-linux workflows are excluded. Content is fetched in a single GraphQL request (avoids raw.githubusercontent.com 429s). The full desired allow-list is logged. - Allowed-workflows are full-synced (stale branch pins pruned); repo access is add-only (`pytorch/pytorch`). **Triggers:** `workflow_dispatch`, and a `push` to `main` touching `generate_binary_build_matrix.py` (the go-live bump). No cron. The token is gated behind the `runner-group` environment (main only); PRs/dispatch default to dry-run, apply runs only on main via the push bump or `apply=true`. **Before applying:** create the `runner-group` environment (protected to main) with secret `RUNNER_GROUP_TOKEN`. ## Validation - Dry-run (this PR): https://github.com/pytorch/test-infra/actions/runs/29858710718/job/88729548933 — 7 workflows x 4 refs = 28 references. - Apply (temporary env/apply override, since removed): https://github.com/pytorch/test-infra/actions/runs/29858037095/job/88727234617 — reconciled the 5 prod groups to 28 references each. Test plan: `python3 -m unittest -v tools.tests.test_release_manage_runner_groups` (Ran 12 tests OK). _Authored with an AI assistant (Claude)._
1 parent b48159c commit 7ce98d5

5 files changed

Lines changed: 686 additions & 1 deletion

File tree

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
name: Release manage runner groups
2+
3+
on:
4+
# The desired state only changes at release milestones, so run on demand and
5+
# when the test-channel version is advanced (the go-live bump), rather than on
6+
# a cron.
7+
workflow_dispatch:
8+
inputs:
9+
apply:
10+
description: "Apply changes (otherwise dry-run)"
11+
type: boolean
12+
default: false
13+
push:
14+
branches:
15+
- main
16+
paths:
17+
- tools/scripts/generate_binary_build_matrix.py
18+
pull_request:
19+
paths:
20+
- .github/workflows/release-manage-runner-groups.yml
21+
- tools/scripts/release_manage_runner_groups.py
22+
- tools/scripts/generate_binary_build_matrix.py
23+
- tools/tests/test_release_manage_runner_groups.py
24+
25+
permissions:
26+
contents: read
27+
28+
concurrency:
29+
group: release-manage-runner-groups
30+
cancel-in-progress: true
31+
32+
jobs:
33+
reconcile:
34+
runs-on: ubuntu-latest
35+
# The token lives in the protected environment and is only selected on
36+
# main, so PRs and forks never see it and run discovery-only.
37+
environment: ${{ github.ref == 'refs/heads/main' && 'runner-group' || '' }}
38+
steps:
39+
- name: Checkout
40+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
41+
42+
- name: Install dependencies
43+
run: python3 -m pip install requests==2.32.3 PyYAML==6.0.2
44+
45+
- name: Reconcile release runner groups
46+
env:
47+
# Token for managing runner groups, only present in the runner-group
48+
# environment (i.e. on main). Falls back to the default token for
49+
# read-only discovery on PRs.
50+
RUNNER_GROUP_TOKEN: ${{ secrets.RUNNER_GROUP_TOKEN }}
51+
GITHUB_TOKEN: ${{ github.token }}
52+
# Apply only from main, and only for the go-live push (matrix version
53+
# bump) or an explicit dispatch with apply=true. Everything else is a
54+
# dry-run.
55+
SHOULD_APPLY: ${{ github.ref == 'refs/heads/main' && (github.event_name == 'push' || inputs.apply) }}
56+
run: |
57+
SCRIPT=tools/scripts/release_manage_runner_groups.py
58+
if [ "${SHOULD_APPLY}" = "true" ]; then
59+
python3 "${SCRIPT}" --apply
60+
else
61+
python3 "${SCRIPT}"
62+
fi

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
echo ::group::setup Python environment
2727
python -m venv .venv/
2828
source .venv/bin/activate
29-
pip install pip==23.0.1 pytest==7.2.0 jsonschema==4.17.3 clickhouse-connect==0.8.14 requests==2.32.2
29+
pip install pip==23.0.1 pytest==7.2.0 jsonschema==4.17.3 clickhouse-connect==0.8.14 requests==2.32.2 PyYAML==6.0.2
3030
echo ::endgroup::
3131
3232
# Test tools

mypy.ini

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ disable_error_code = no-any-return, no-untyped-def, no-untyped-call, import-not-
5151
[mypy-tools.self_hosted_runner_utils.check_runners_state_org]
5252
disable_error_code = no-any-return, no-untyped-def, no-untyped-call, import-not-found, import-untyped
5353

54+
[mypy-tools.scripts.release_manage_runner_groups]
55+
disable_error_code = no-any-return, no-untyped-def, no-untyped-call, import-not-found, import-untyped
56+
57+
[mypy-tools.tests.test_release_manage_runner_groups]
58+
disable_error_code = no-any-return, no-untyped-def, no-untyped-call, import-not-found, import-untyped
59+
5460
[mypy-tools.scripts.*]
5561
disable_error_code = var-annotated, import-untyped
5662

0 commit comments

Comments
 (0)