-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
283 lines (259 loc) · 10.9 KB
/
Copy pathresource-diff.yml
File metadata and controls
283 lines (259 loc) · 10.9 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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
name: Resource Diff
on:
pull_request:
branches: [master]
workflow_dispatch:
inputs:
pull_request:
description: "Pull request number to compare. Enables manual maintainer-approved diff for fork PRs."
required: false
type: string
before_ref:
description: "Base ref/SHA to compare from. Defaults to the PR base or master."
required: false
type: string
after_ref:
description: "Head ref/SHA to compare. Defaults to the PR head or current ref."
required: false
type: string
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
diff:
permissions:
contents: read
pull-requests: read
runs-on: ubuntu-latest
steps:
- name: Resolve refs
id: refs
shell: bash
env:
EVENT_NAME: ${{ github.event_name }}
INPUT_PULL_REQUEST: ${{ inputs.pull_request }}
INPUT_BEFORE_REF: ${{ inputs.before_ref }}
INPUT_AFTER_REF: ${{ inputs.after_ref }}
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
PR_HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
PR_HEAD_REPO_URL: ${{ github.event.pull_request.head.repo.clone_url }}
GITHUB_SHA_VALUE: ${{ github.sha }}
GH_TOKEN: ${{ github.token }}
REPOSITORY: ${{ github.repository }}
run: |
pr_number=""
pr_head_repo=""
pr_head_repo_url=""
manual_pr=0
if [ "$EVENT_NAME" = "workflow_dispatch" ] && [ -n "$INPUT_PULL_REQUEST" ]; then
pr_number="$INPUT_PULL_REQUEST"
before_ref="${INPUT_BEFORE_REF:-$(gh api "repos/${REPOSITORY}/pulls/${pr_number}" --jq '.base.sha')}"
after_ref="${INPUT_AFTER_REF:-$(gh api "repos/${REPOSITORY}/pulls/${pr_number}" --jq '.head.sha')}"
pr_head_repo="$(gh api "repos/${REPOSITORY}/pulls/${pr_number}" --jq '.head.repo.full_name')"
pr_head_repo_url="$(gh api "repos/${REPOSITORY}/pulls/${pr_number}" --jq '.head.repo.clone_url')"
manual_pr=1
elif [ "$EVENT_NAME" = "pull_request" ]; then
before_ref="${INPUT_BEFORE_REF:-$PR_BASE_SHA}"
after_ref="${INPUT_AFTER_REF:-$PR_HEAD_SHA}"
pr_head_repo="$PR_HEAD_REPO"
pr_head_repo_url="$PR_HEAD_REPO_URL"
else
before_ref="${INPUT_BEFORE_REF:-master}"
after_ref="${INPUT_AFTER_REF:-$GITHUB_SHA_VALUE}"
pr_head_repo="$REPOSITORY"
fi
echo "before_ref=$before_ref" >> "$GITHUB_OUTPUT"
echo "after_ref=$after_ref" >> "$GITHUB_OUTPUT"
echo "pr_number=$pr_number" >> "$GITHUB_OUTPUT"
echo "pr_head_repo=$pr_head_repo" >> "$GITHUB_OUTPUT"
echo "pr_head_repo_url=$pr_head_repo_url" >> "$GITHUB_OUTPUT"
echo "manual_pr=$manual_pr" >> "$GITHUB_OUTPUT"
echo "Before: $before_ref"
echo "After: $after_ref"
if [ -n "$pr_number" ]; then
echo "Pull request: #$pr_number"
fi
if [ -n "$pr_head_repo" ]; then
echo "PR head repository: $pr_head_repo"
fi
- name: Check resource diff safety
id: safety
shell: bash
env:
EVENT_NAME: ${{ github.event_name }}
PR_HEAD_REPO: ${{ steps.refs.outputs.pr_head_repo }}
MANUAL_PR: ${{ steps.refs.outputs.manual_pr }}
REPOSITORY: ${{ github.repository }}
run: |
enabled=1
use_buildbuddy=1
if [ "$EVENT_NAME" = "pull_request" ] && [ "$PR_HEAD_REPO" != "$REPOSITORY" ]; then
enabled=0
fi
if [ "$PR_HEAD_REPO" != "$REPOSITORY" ]; then
use_buildbuddy=0
fi
echo "enabled=$enabled" >> "$GITHUB_OUTPUT"
echo "use_buildbuddy=$use_buildbuddy" >> "$GITHUB_OUTPUT"
if [ "$enabled" = "0" ]; then
{
echo "## Resource Diff Skipped"
echo
echo "Resource diff is skipped for fork pull requests because building"
echo "the resource zip executes repository Bazel/Python code from the PR."
echo
echo "- Repository: \`${REPOSITORY}\`"
echo "- PR head repository: \`${PR_HEAD_REPO}\`"
echo "- Before ref: \`${{ steps.refs.outputs.before_ref }}\`"
echo "- After ref: \`${{ steps.refs.outputs.after_ref }}\`"
echo
echo "A maintainer can run this workflow manually with the PR number after review."
} >> "$GITHUB_STEP_SUMMARY"
fi
if [ "$enabled" = "1" ] && [ "$MANUAL_PR" = "1" ]; then
{
echo "## Resource Diff Manually Approved"
echo
echo "This workflow was manually triggered for PR #${{ steps.refs.outputs.pr_number }}."
echo "- PR head repository: \`${PR_HEAD_REPO}\`"
echo "- BuildBuddy enabled: \`${use_buildbuddy}\`"
echo
} >> "$GITHUB_STEP_SUMMARY"
fi
- name: Checkout repository
if: steps.safety.outputs.enabled == '1'
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Create comparison worktrees
if: steps.safety.outputs.enabled == '1'
shell: bash
env:
EVENT_NAME: ${{ github.event_name }}
PR_HEAD_REPO_URL: ${{ steps.refs.outputs.pr_head_repo_url }}
run: |
before_ref="${{ steps.refs.outputs.before_ref }}"
after_ref="${{ steps.refs.outputs.after_ref }}"
git fetch --no-tags origin "${before_ref}:refs/resource-diff/before"
if [ -n "$PR_HEAD_REPO_URL" ]; then
git fetch --no-tags "$PR_HEAD_REPO_URL" "${after_ref}:refs/resource-diff/after"
else
git fetch --no-tags origin "${after_ref}:refs/resource-diff/after"
fi
git worktree add "$RUNNER_TEMP/opencc-before" refs/resource-diff/before
git worktree add "$RUNNER_TEMP/opencc-after" refs/resource-diff/after
- name: Verify checked out refs
if: steps.safety.outputs.enabled == '1'
shell: bash
run: |
before_head="$(git -C "$RUNNER_TEMP/opencc-before" rev-parse HEAD)"
after_head="$(git -C "$RUNNER_TEMP/opencc-after" rev-parse HEAD)"
{
echo "## Checked Out Refs"
echo
echo "- Expected before: \`${{ steps.refs.outputs.before_ref }}\`"
echo "- Actual before: \`${before_head}\`"
echo "- Expected after: \`${{ steps.refs.outputs.after_ref }}\`"
echo "- Actual after: \`${after_head}\`"
echo
} >> "$GITHUB_STEP_SUMMARY"
test "$before_head" = "${{ steps.refs.outputs.before_ref }}"
test "$after_head" = "${{ steps.refs.outputs.after_ref }}"
- uses: bazel-contrib/setup-bazel@0.19.0
if: steps.safety.outputs.enabled == '1'
with:
bazelisk-cache: true
- name: Set up Python
if: steps.safety.outputs.enabled == '1'
uses: actions/setup-python@v6
with:
python-version: "3.12"
- name: Configure BuildBuddy
if: steps.safety.outputs.enabled == '1' && steps.safety.outputs.use_buildbuddy == '1'
shell: bash
env:
BUILDBUDDY_API_KEY: ${{ secrets.BUILDBUDDY_API_KEY }}
run: |
if [ -n "${BUILDBUDDY_API_KEY}" ]; then
{
echo "build --config=buildbuddy"
echo "build --remote_header=x-buildbuddy-api-key=${BUILDBUDDY_API_KEY}"
echo "build --bes_header=x-buildbuddy-api-key=${BUILDBUDDY_API_KEY}"
} >> "$RUNNER_TEMP/opencc-before/.bazelrc.user"
echo "BuildBuddy enabled for before worktree."
else
echo "BUILDBUDDY_API_KEY not set; skipping BuildBuddy config."
fi
- name: Build before resource zip
if: steps.safety.outputs.enabled == '1'
shell: bash
working-directory: ${{ runner.temp }}/opencc-before
env:
MSYS_NO_PATHCONV: 1
run: |
args=()
if [ -x ./scripts/bazel-workspace-status.sh ]; then
args+=(--workspace_status_command=./scripts/bazel-workspace-status.sh)
fi
bazel build "${args[@]}" //data:opencc_resources_zip
mkdir -p "$GITHUB_WORKSPACE/dist"
cp -f bazel-bin/data/opencc-resources.zip "$GITHUB_WORKSPACE/dist/opencc-resources-before.zip"
- name: Build after resource zip
if: steps.safety.outputs.enabled == '1'
shell: bash
working-directory: ${{ runner.temp }}/opencc-after
env:
MSYS_NO_PATHCONV: 1
run: |
args=()
if [ -x ./scripts/bazel-workspace-status.sh ]; then
args+=(--workspace_status_command=./scripts/bazel-workspace-status.sh)
fi
bazel build "${args[@]}" //data:opencc_resources_zip
mkdir -p "$GITHUB_WORKSPACE/dist"
cp -f bazel-bin/data/opencc-resources.zip "$GITHUB_WORKSPACE/dist/opencc-resources-after.zip"
- name: Capture resource zip metadata
if: steps.safety.outputs.enabled == '1'
shell: bash
run: |
python3 - <<'PY' >> "$GITHUB_STEP_SUMMARY"
import hashlib
import json
import zipfile
print("## Resource Zip Metadata")
print()
for label, path in [
("Before", "dist/opencc-resources-before.zip"),
("After", "dist/opencc-resources-after.zip"),
]:
data = open(path, "rb").read()
with zipfile.ZipFile(path) as archive:
manifest_data = archive.read("opencc-resource-manifest.json")
manifest = json.loads(manifest_data)
print(f"- {label} zip SHA256: `{hashlib.sha256(data).hexdigest()}`")
print(
f"- {label} manifest SHA256: "
f"`{hashlib.sha256(manifest_data).hexdigest()}`"
)
print(f"- {label} manifest commit: `{manifest.get('commit_id')}`")
print(f"- {label} manifest built: `{manifest.get('build_time_utc')}`")
print()
PY
- name: Generate diff report
if: steps.safety.outputs.enabled == '1'
shell: bash
run: |
mkdir -p dist
python3 "$RUNNER_TEMP/opencc-before/data/scripts/opencc_resources_zip_diff.py" \
dist/opencc-resources-before.zip \
dist/opencc-resources-after.zip \
--markdown dist/opencc-resource-diff.md
cat dist/opencc-resource-diff.md >> "$GITHUB_STEP_SUMMARY"
- name: Upload diff report
if: steps.safety.outputs.enabled == '1'
uses: actions/upload-artifact@v7
with:
path: dist/opencc-resource-diff.md
archive: false
if-no-files-found: error