Skip to content

Commit 276f295

Browse files
Pinbump cron (pytorch#19034)
Adds two new workflows: - weekly-pytorch-pin-bump.yml: Weekly cron that bumps the PyTorch nightly pin, syncs c10 headers, and creates a PR - pin-bump-ci-handler.yml: Watches trunk CI on pin bump PRs and posts @claude comments to fix failures (up to 3 attempts), then escalates to a human Authored with Claude.
1 parent e6efe18 commit 276f295

2 files changed

Lines changed: 210 additions & 0 deletions

File tree

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
name: Pin Bump CI Handler
2+
3+
on:
4+
workflow_run:
5+
workflows: ["trunk"]
6+
types: [completed]
7+
8+
jobs:
9+
handle-ci-result:
10+
if: github.repository_owner == 'pytorch'
11+
runs-on: ubuntu-latest
12+
environment: update-commit-hash
13+
permissions:
14+
pull-requests: write
15+
issues: write
16+
steps:
17+
- uses: actions/github-script@v7
18+
with:
19+
github-token: ${{ secrets.UPDATEBOT_TOKEN }}
20+
script: |
21+
const { owner, repo } = context.repo;
22+
const workflowRun = context.payload.workflow_run;
23+
const conclusion = workflowRun.conclusion;
24+
const runUrl = workflowRun.html_url;
25+
26+
const prs = workflowRun.pull_requests;
27+
if (!prs || prs.length === 0) {
28+
console.log('No PRs associated with this workflow run. Skipping.');
29+
return;
30+
}
31+
32+
const prNumber = prs[0].number;
33+
const pr = await github.rest.pulls.get({ owner, repo, pull_number: prNumber });
34+
35+
const isPinBump = pr.data.labels.some(l => l.name === 'ci/pytorch-pin-bump');
36+
if (!isPinBump) {
37+
console.log(`PR #${prNumber} is not a pin bump PR. Skipping.`);
38+
return;
39+
}
40+
41+
const allowedAuthors = new Set(['pytorchbot', 'pytorchupdatebot', 'facebook-github-bot']);
42+
if (!allowedAuthors.has(pr.data.user.login)) {
43+
console.log(`PR #${prNumber} was created by ${pr.data.user.login}, not an allowed automation account. Skipping.`);
44+
return;
45+
}
46+
47+
console.log(`Pin bump PR #${prNumber}, trunk concluded: ${conclusion}`);
48+
49+
const comments = await github.rest.issues.listComments({
50+
owner, repo, issue_number: prNumber, per_page: 100
51+
});
52+
const fixAttempts = comments.data.filter(
53+
c => c.body && c.body.startsWith('@claude [ci-fix-attempt')
54+
).length;
55+
56+
if (conclusion === 'success') {
57+
const note = fixAttempts > 0
58+
? `Claude fixed CI failures in ${fixAttempts} attempt(s).`
59+
: 'CI passed on the first try.';
60+
61+
await github.rest.issues.createComment({
62+
owner, repo, issue_number: prNumber,
63+
body: `## CI Passed\n\nAll trunk CI checks have passed on this pin bump PR. ${note}\n\n**This PR is ready for human review and merge.**\n\ncc @jakeszwe`
64+
});
65+
return;
66+
}
67+
68+
if (conclusion !== 'failure') {
69+
console.log(`Trunk concluded with "${conclusion}" (not failure). Skipping.`);
70+
return;
71+
}
72+
73+
if (fixAttempts >= 3) {
74+
await github.rest.issues.createComment({
75+
owner, repo, issue_number: prNumber,
76+
body: [
77+
'## Automated Fix Attempts Exhausted',
78+
'',
79+
`CI is still failing after ${fixAttempts} automated fix attempt(s).`,
80+
`Failed trunk run: ${runUrl}`,
81+
'',
82+
'This pin bump likely requires human intervention. Common causes:',
83+
'- BC-breaking API changes in PyTorch that need design discussion',
84+
'- New dependencies or build system changes',
85+
'- Test infrastructure issues unrelated to the pin bump',
86+
'',
87+
'cc @jakeszwe'
88+
].join('\n')
89+
});
90+
return;
91+
}
92+
93+
const attemptNum = fixAttempts + 1;
94+
await github.rest.issues.createComment({
95+
owner, repo, issue_number: prNumber,
96+
body: [
97+
`@claude [ci-fix-attempt ${attemptNum}/3]`,
98+
'',
99+
`The \`trunk\` CI workflow has failed on this automated PyTorch pin bump PR.`,
100+
`Failed run: ${runUrl}`,
101+
'',
102+
'Please:',
103+
'1. Read the Dr. CI comment on this PR for a summary of which jobs failed and whether they are flaky. Ignore failures marked as FLAKY.',
104+
'2. Use your CI tools to download the failure logs for the non-flaky failing jobs',
105+
'3. Identify the root cause of the failure',
106+
'4. If this is a build or test failure caused by PyTorch API changes, fix the ExecuTorch code to be compatible with the new PyTorch version',
107+
'5. If this is a c10 header sync issue, the headers have already been synced by the pin bump script — the issue is likely in ExecuTorch code that uses those headers',
108+
'6. Run `lintrunner -a` on any files you change',
109+
'7. Push your fix as a new commit to this PR branch',
110+
'',
111+
'Important constraints:',
112+
'- Do NOT modify torch_pin.py or .ci/docker/ci_commit_pins/pytorch.txt — the pin itself is correct',
113+
'- Do NOT modify files under runtime/core/portable_type/c10/ unless the sync introduced a new API that ExecuTorch code needs to adapt to',
114+
'- Focus on fixing ExecuTorch code to be compatible with the new PyTorch APIs',
115+
'- If this is a major BC-breaking change that requires architectural discussion, say so clearly and stop — do not attempt a fix'
116+
].join('\n')
117+
});
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
name: Weekly PyTorch Pin Bump
2+
3+
on:
4+
schedule:
5+
- cron: '0 9 * * 1' # Monday 9:00 UTC
6+
workflow_dispatch:
7+
8+
jobs:
9+
create-pin-bump-pr:
10+
if: github.repository_owner == 'pytorch'
11+
runs-on: ubuntu-latest
12+
environment: update-commit-hash
13+
permissions:
14+
contents: write
15+
pull-requests: write
16+
steps:
17+
- uses: actions/checkout@v4
18+
with:
19+
token: ${{ secrets.UPDATEBOT_TOKEN }}
20+
21+
- uses: actions/setup-python@v5
22+
with:
23+
python-version: '3.11'
24+
25+
- name: Determine nightly version
26+
id: nightly
27+
run: |
28+
NIGHTLY_DATE=$(date -u -d 'yesterday' '+%Y%m%d')
29+
NIGHTLY_VERSION="dev${NIGHTLY_DATE}"
30+
echo "version=${NIGHTLY_VERSION}" >> "$GITHUB_OUTPUT"
31+
32+
- name: Read current TORCH_VERSION
33+
id: torch
34+
run: |
35+
TORCH_VERSION=$(python -c "exec(open('torch_pin.py').read()); print(TORCH_VERSION)")
36+
echo "version=${TORCH_VERSION}" >> "$GITHUB_OUTPUT"
37+
38+
- name: Update torch_pin.py with new NIGHTLY_VERSION
39+
run: |
40+
printf 'TORCH_VERSION = "%s"\nNIGHTLY_VERSION = "%s"\n' \
41+
"${{ steps.torch.outputs.version }}" \
42+
"${{ steps.nightly.outputs.version }}" > torch_pin.py
43+
44+
- name: Run pin bump script
45+
run: python .github/scripts/update_pytorch_pin.py
46+
47+
- name: Create branch and PR
48+
env:
49+
GH_TOKEN: ${{ secrets.UPDATEBOT_TOKEN }}
50+
run: |
51+
BRANCH="automated/pytorch-pin-bump-${{ steps.nightly.outputs.version }}"
52+
53+
git config user.name "pytorchbot"
54+
git config user.email "pytorchbot@users.noreply.github.com"
55+
git checkout -b "${BRANCH}"
56+
git add torch_pin.py
57+
git add .ci/docker/ci_commit_pins/pytorch.txt
58+
git add runtime/core/portable_type/c10/
59+
60+
if git diff --cached --quiet; then
61+
echo "No changes to commit. Pin is already up to date."
62+
exit 0
63+
fi
64+
65+
git commit -m "Bump PyTorch pin to nightly ${{ steps.nightly.outputs.version }}"
66+
git push -u origin "${BRANCH}"
67+
68+
EXISTING=$(gh pr list --label "ci/pytorch-pin-bump" --state open --json number --jq '.[0].number')
69+
if [ -n "${EXISTING}" ]; then
70+
echo "Closing existing pin bump PR #${EXISTING} in favor of new one"
71+
gh pr close "${EXISTING}" --comment "Superseded by newer pin bump."
72+
fi
73+
74+
NIGHTLY="${{ steps.nightly.outputs.version }}"
75+
read -r -d '' PR_BODY <<EOF || true
76+
## Summary
77+
78+
Automated weekly PyTorch pin bump.
79+
80+
- Updates \`NIGHTLY_VERSION\` in \`torch_pin.py\` to \`${NIGHTLY}\`
81+
- Updates \`.ci/docker/ci_commit_pins/pytorch.txt\` to the corresponding nightly commit hash
82+
- Syncs c10 headers from PyTorch into \`runtime/core/portable_type/c10/\`
83+
84+
This PR was created automatically. If CI fails, Claude will attempt to fix issues (up to 3 attempts). If CI still fails, human review will be requested.
85+
86+
cc @jakeszwe
87+
EOF
88+
PR_BODY=$(echo "${PR_BODY}" | sed 's/^ //')
89+
90+
gh pr create \
91+
--title "Bump PyTorch pin to nightly ${NIGHTLY}" \
92+
--body "${PR_BODY}" \
93+
--label "ci/pytorch-pin-bump"

0 commit comments

Comments
 (0)