-
Notifications
You must be signed in to change notification settings - Fork 1
159 lines (142 loc) · 5.99 KB
/
Copy pathrenovate-snapshot-autofix.yml
File metadata and controls
159 lines (142 loc) · 5.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# This workflow lets maintainers explicitly request snapshot autofixes on Renovate PRs.
# It runs tests, updates snapshots only when failures are snapshot-related, and pushes
# the snapshot commit back to the Renovate branch while blocking non-snapshot changes.
name: renovate-snapshot-autofix
on:
# Request-driven mode on Renovate PRs.
# We include synchronize/reopened so reruns happen automatically after updates
# when the label is still present.
pull_request_target:
types:
- labeled
- synchronize
- reopened
# Alternative request mode: comment `/autofix-snapshots` on a Renovate PR.
issue_comment:
types:
- created
# Fallback manual trigger from Actions UI for a specific branch.
workflow_dispatch:
inputs:
branch:
description: 'Renovate branch to update snapshots for (e.g. renovate/pkg-1.x)'
required: true
type: string
permissions:
# Needed to push snapshot updates back to the Renovate branch.
contents: write
# Needed to read PR metadata (label + head branch).
pull-requests: read
jobs:
autofix-snapshots:
name: Autofix Snapshot Updates
runs-on: ubuntu-latest
timeout-minutes: 20
# Run when:
# 1) a Renovate PR has the opt-in label,
# 2) a maintainer comments `/autofix-snapshots` on a PR, or
# 3) the workflow is manually dispatched.
if: >-
${{
(github.event_name == 'pull_request_target' &&
contains(github.event.pull_request.labels.*.name, 'autofix:snapshots') &&
github.event.pull_request.head.repo.full_name == github.repository &&
startsWith(github.event.pull_request.head.ref, 'renovate/')) ||
(github.event_name == 'issue_comment' &&
github.event.issue.pull_request &&
contains(github.event.comment.body, '/autofix-snapshots')) ||
github.event_name == 'workflow_dispatch'
}}
steps:
- name: Resolve PR head branch for issue comment trigger
id: pr-head
if: github.event_name == 'issue_comment'
uses: actions/github-script@v9
with:
script: |
const { owner, repo } = context.repo;
const issueNumber = context.payload.issue.number;
const { data: pr } = await github.rest.pulls.get({
owner,
repo,
pull_number: issueNumber,
});
if (!pr.head.ref.startsWith('renovate/')) {
core.setFailed(`PR head '${pr.head.ref}' is not a renovate branch.`);
return;
}
if (pr.head.repo.full_name !== `${owner}/${repo}`) {
core.setFailed(
`Refusing to push to external repo '${pr.head.repo.full_name}'.`,
);
return;
}
core.setOutput('ref', pr.head.ref);
core.setOutput('repository', pr.head.repo.full_name);
- uses: actions/checkout@v6
with:
token: ${{ secrets.GITHUB_TOKEN }}
fetch-depth: 0
# For label-triggered runs, check out the Renovate PR head branch.
# For issue comments, resolve PR head via API first.
# For manual runs, use the branch provided as workflow input.
ref: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.ref || github.event_name == 'issue_comment' && steps.pr-head.outputs.ref || github.event.inputs.branch }}
# For Renovate PRs this can point to a fork; for manual runs use current repo.
repository: ${{ github.event_name == 'pull_request_target' && github.event.pull_request.head.repo.full_name || github.event_name == 'issue_comment' && steps.pr-head.outputs.repository || github.repository }}
- name: Setup project
uses: ./.github/actions/setup-project
- name: Run tests and detect snapshot-only failures
id: test-run
shell: bash
run: |
set +e
pnpm test 2>&1 | tee test-output.log
test_exit=$?
set -e
# Green run: no fix needed.
if [ "$test_exit" -eq 0 ]; then
echo "status=passed" >> "$GITHUB_OUTPUT"
exit 0
fi
# Only proceed when failure output indicates snapshot mismatch.
if rg -i "snapshot|snapshots|inline snapshot|to match snapshot" test-output.log >/dev/null; then
echo "status=snapshot_failure" >> "$GITHUB_OUTPUT"
exit 0
fi
# Non-snapshot failures should fail this job and require human action.
echo "status=non_snapshot_failure" >> "$GITHUB_OUTPUT"
exit 1
- name: Update snapshots
if: steps.test-run.outputs.status == 'snapshot_failure'
run: pnpm test -u
- name: Ensure only snapshot files changed
if: steps.test-run.outputs.status == 'snapshot_failure'
shell: bash
run: |
changed_files="$(git diff --name-only)"
# Nothing changed after update command -> nothing to commit.
if [ -z "$changed_files" ]; then
echo "No file changes after snapshot update."
exit 0
fi
# Safety gate: only allow known snapshot file patterns.
non_snapshot_files="$(printf '%s\n' "$changed_files" | rg -v '(^|/)__snapshots__/|\.snap$|(\.|/)(test|spec)\.(ts|tsx|js|jsx|mjs|cjs)$' || true)"
if [ -n "$non_snapshot_files" ]; then
echo "Found non-snapshot changes after update:"
printf '%s\n' "$non_snapshot_files"
exit 1
fi
- name: Commit and push snapshot updates
if: steps.test-run.outputs.status == 'snapshot_failure'
shell: bash
run: |
# Avoid empty commits if rerun has no diffs.
if git diff --quiet; then
echo "No snapshot updates to commit."
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add -A
git commit -m "test: update snapshots"
git push