-
Notifications
You must be signed in to change notification settings - Fork 0
192 lines (175 loc) · 7.78 KB
/
Copy pathghidra-noprompt.yml
File metadata and controls
192 lines (175 loc) · 7.78 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
---
name: ghidra-noprompt
# xerootg/ghidra republishes every upstream Ghidra stable release with the
# "would you like to analyze it now?" prompt patched out. This job notices a new
# release there, repackages it for Arch, and serves it as its own small pacman
# repository hosted in a GitHub Release.
#
# It deliberately does not go through build-pacman-repo / GitHub Pages: the
# package is ~500 MB and GitHub rejects any pushed file over 100 MB, which would
# break the Pages repo for every other package too.
on:
schedule:
- cron: "40 8 * * *"
workflow_dispatch:
inputs:
force:
description: "Rebuild and re-upload even if the PKGBUILD is already current"
type: boolean
default: false
permissions:
contents: write
concurrency:
group: "${{ github.workflow }}"
cancel-in-progress: false
env:
FORK: xerootg/ghidra
PKGDIR: release-pkgbuilds/ghidra-noprompt
REPO_NAME: ghidra
RELEASE_TAG: pacman-repo
jobs:
build:
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- name: Checkout
uses: actions/checkout@v7
- name: Fetch the newest fork release metadata
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
tag="$(gh release view --repo "$FORK" --json tagName --jq .tagName)"
echo "Newest $FORK release: $tag"
# --dir rather than --output: gh rejects --output when the pattern
# could match more than one asset.
gh release download "$tag" --repo "$FORK" \
--pattern release-metadata.json --dir . --clobber
cat release-metadata.json
- name: Update PKGBUILD
id: bump
run: python3 .github/scripts/bump-ghidra-noprompt.py release-metadata.json "$PKGDIR"
- name: Decide whether to build
id: gate
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ steps.bump.outputs.version }}
run: |
set -euo pipefail
# The published release is the state, not the committed PKGBUILD.
# main is protected by a ruleset, so this job cannot commit a version
# bump; deciding from the release keeps the job stateless and correct
# whether or not the PKGBUILD in git happens to be current.
build=false
if [ "${{ inputs.force }}" = "true" ]; then
build=true
echo "Forced rebuild requested."
else
assets="$(gh release view "$RELEASE_TAG" --json assets --jq '.assets[].name' 2>/dev/null || true)"
if ! grep -q "^ghidra-noprompt-${VERSION}-" <<<"$assets"; then
build=true
echo "No ghidra-noprompt-${VERSION}-* asset published yet."
else
echo "ghidra-noprompt ${VERSION} is already published."
fi
fi
echo "build=$build" >> "$GITHUB_OUTPUT"
- name: Build the package and its pacman database
if: steps.gate.outputs.build == 'true'
env:
GPG_SIGNING_KEY: ${{ secrets.GPG_SIGNING_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
run: |
set -euo pipefail
docker run --rm \
-v "${{ github.workspace }}:/work" \
-e REPO_NAME="$REPO_NAME" \
-e GPG_SIGNING_KEY \
-e GPG_PASSPHRASE \
-w /work \
archlinux:base-devel \
bash .github/scripts/build-ghidra-noprompt.sh
- name: Publish to the pacman repo release
if: steps.gate.outputs.build == 'true'
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ steps.bump.outputs.version }}
run: |
set -euo pipefail
ls -lh out/
# Notes live in .github/release-notes/ so the same text is used when the
# release is first created and whenever sign-backfill refreshes it.
# Inline heredocs could only ever run at creation time, which meant the
# published install instructions could never be corrected.
if ! gh release view "$RELEASE_TAG" >/dev/null 2>&1; then
gh release create "$RELEASE_TAG" \
--title "pacman repo" --notes-file .github/release-notes/ghidra.md
else
gh release edit "$RELEASE_TAG" --notes-file .github/release-notes/ghidra.md
fi
# Only files that exist: gh treats each argument as a pattern and fails
# the whole call on one that matches nothing, and the signing
# artifacts are absent until the signing secrets are configured.
# nullglob covers *.sig but not a literal path.
uploads=(
out/ghidra-noprompt-*.pkg.tar.zst
"out/${REPO_NAME}.db" "out/${REPO_NAME}.files"
"out/${REPO_NAME}.db.tar.gz" "out/${REPO_NAME}.files.tar.gz"
)
shopt -s nullglob
uploads+=( out/*.sig )
shopt -u nullglob
[ -f out/xerootg.asc ] && uploads+=( out/xerootg.asc )
# Signatures go up in the same call as what they sign, so there is no
# window where pacman fetches a package it cannot verify.
printf 'uploading: %s\n' "${uploads[@]}"
gh release upload "$RELEASE_TAG" "${uploads[@]}" --clobber
# Drop superseded package assets, but only after the new one is up.
# In the steady state both greps come up empty -- there is one package
# asset and it is the one just uploaded -- and an empty grep exits 1,
# which under pipefail would fail the step after a successful publish.
keep="$(basename out/ghidra-noprompt-*.pkg.tar.zst)"
gh release view "$RELEASE_TAG" --json assets --jq '.assets[].name' \
| { grep -E '^ghidra-noprompt-.*\.pkg\.tar\.zst(\.sig)?$' || true; } \
| { grep -vxF -e "$keep" -e "${keep}.sig" || true; } \
| while read -r old; do
echo "Removing superseded asset $old"
gh release delete-asset "$RELEASE_TAG" "$old" --yes
done
{
echo "### Published ghidra-noprompt ${VERSION}"
echo
echo '```'
echo "$keep"
echo '```'
} >> "$GITHUB_STEP_SUMMARY"
- name: Refresh the PKGBUILD in the repository
# Best effort, and deliberately not fatal. main is covered by a
# repository ruleset requiring a pull request, which github-actions[bot]
# cannot bypass. The package and its database are already published at
# this point, so a rejected push must not fail the run -- it only means
# the checked-in recipe still names the previous version.
if: steps.gate.outputs.build == 'true'
run: |
set -euo pipefail
rm -f release-metadata.json release-notes.md
rm -rf out .build
git config user.name 'github-actions[bot]'
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
git add "$PKGDIR"
if git diff --cached --quiet; then
echo "PKGBUILD already matches the published release."
exit 0
fi
git commit -q -m "ghidra-noprompt: ${{ steps.bump.outputs.previous || 'rebuild' }} -> ${{ steps.bump.outputs.version }}"
if git push 2>&1; then
echo "Pushed the PKGBUILD refresh."
else
echo "::warning::Could not push the PKGBUILD refresh; main requires changes to go through a pull request. The published release is authoritative and is up to date."
{
echo
echo "> The PKGBUILD refresh could not be pushed: \`main\` requires a pull"
echo "> request. The release is published and correct regardless. To have this"
echo "> committed automatically, give the Actions bot a bypass on the ruleset."
} >> "$GITHUB_STEP_SUMMARY"
fi