forked from amule-project/amule
-
Notifications
You must be signed in to change notification settings - Fork 0
424 lines (415 loc) · 17.9 KB
/
Copy pathpackaging.yml
File metadata and controls
424 lines (415 loc) · 17.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
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
# Packaging CI — verifies the recipes in packaging/{linux,macos,windows}/
# still produce working artifacts on every push to a branch that includes
# packaging/ changes. NOT tag-triggered (that's release.yml later); this
# is the per-PR sanity gate.
#
# Each platform builds on its native GHA runner (no QEMU emulation).
# macOS Universal2 is the special case — built by parallel arm64 + x86_64
# jobs and merged in a follow-up `lipo` job, since standard Homebrew on
# Apple Silicon ships native-arch-only dylibs.
#
# Artifacts uploaded per matrix entry; not assembled into a Release here.
name: Packaging
on:
# Auto-fires only on push to master — i.e. when a PR is merged. Open
# PRs do NOT trigger this workflow; reviewers who want to inspect a
# PR's artifacts before merging can run `workflow_dispatch` against
# the PR branch from the Actions UI. This avoids the double-fire of
# "fires on PR open AND on merge" which is the most expensive shape.
# Path filter ensures doc-only commits don't burn CI either.
push:
branches:
- master
- 'packaging**'
paths:
- 'packaging/**'
- '.github/workflows/packaging.yml'
- 'src/**'
- 'CMakeLists.txt'
- 'cmake/**'
workflow_dispatch:
inputs:
only:
description: >-
Comma-separated list of platform tracks to run.
Default empty = run all. Useful during iteration to focus
on the failing tracks without paying for the green ones.
Valid: appimage, flatpak, macos, windows.
required: false
type: string
default: ''
checkout_ref:
description: >-
Optional git ref to check out for packaging. Defaults to the
workflow ref. Used by upstream nightly automation.
required: false
type: string
default: ''
# Lets release.yml invoke this matrix as a reusable workflow on tag
# pushes — same artifact set, no duplication of the build steps.
workflow_call:
inputs:
only:
required: false
type: string
default: ''
checkout_ref:
required: false
type: string
default: ''
permissions:
contents: read
jobs:
# ------------------------------------------------------------------
# Linux — AppImage on x86_64 + aarch64 native runners
# ------------------------------------------------------------------
appimage:
name: AppImage (${{ matrix.arch }})
if: >-
github.event_name != 'workflow_dispatch' ||
inputs.only == '' ||
contains(inputs.only, 'appimage')
strategy:
fail-fast: false
matrix:
include:
- { arch: x86_64, artifact_arch: x64, runs-on: ubuntu-22.04 }
- { arch: aarch64, artifact_arch: arm64, runs-on: ubuntu-22.04-arm }
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0 # for git describe in build.sh
ref: ${{ inputs.checkout_ref || github.ref }}
- name: Build AppImage
run: packaging/linux/build.sh appimage
- name: Validate via cross-distro Docker matrix
run: packaging/linux/build.sh validate
- uses: actions/upload-artifact@v7
with:
name: appimage-${{ matrix.arch }}
path: dist/aMule-*-Linux-${{ matrix.artifact_arch }}.AppImage
if-no-files-found: error
retention-days: 3
# ------------------------------------------------------------------
# Linux — Flatpak on x86_64 + aarch64 native runners
# ------------------------------------------------------------------
flatpak:
name: Flatpak (${{ matrix.arch }})
if: >-
github.event_name != 'workflow_dispatch' ||
inputs.only == '' ||
contains(inputs.only, 'flatpak')
strategy:
fail-fast: false
matrix:
# ubuntu-24.04 (not 22.04 like the AppImage job) so the host
# ships appstream 1.0+ which provides /usr/bin/appstream-compose.
# flatpak-builder shells out to that binary at the end of every
# build to compose AppStream metadata; on 22.04 (appstream 0.15)
# the binary is absent and flatpak-builder fails with
# "bwrap: execvp appstream-compose: No such file or directory".
# Host glibc doesn't matter for Flatpak builds (output runs
# inside the GNOME Platform sandbox), so bumping the runner
# has no compat downside, unlike the AppImage matrix.
include:
- { arch: x86_64, artifact_arch: x64, runs-on: ubuntu-24.04 }
- { arch: aarch64, artifact_arch: arm64, runs-on: ubuntu-24.04-arm }
runs-on: ${{ matrix.runs-on }}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
ref: ${{ inputs.checkout_ref || github.ref }}
- name: Install flatpak + flatpak-builder + GNOME runtime
run: |
sudo apt-get update
sudo apt-get install -y flatpak flatpak-builder gettext-base
flatpak remote-add --user --if-not-exists flathub \
https://flathub.org/repo/flathub.flatpakrepo
# Read GNOME_RUNTIME_VERSION from versions.env so this stays
# in sync with whatever the manifest pins.
set -a; . packaging/linux/versions.env; set +a
flatpak install --user --noninteractive flathub \
"org.gnome.Platform//${GNOME_RUNTIME_VERSION}" \
"org.gnome.Sdk//${GNOME_RUNTIME_VERSION}"
- name: Build Flatpak
run: packaging/linux/build.sh flatpak
- uses: actions/upload-artifact@v7
with:
name: flatpak-${{ matrix.arch }}
path: dist/aMule-*-Linux-${{ matrix.artifact_arch }}.flatpak
if-no-files-found: error
retention-days: 3
# ------------------------------------------------------------------
# macOS — native arm64 + x86_64 builds, then lipo-merge to Universal2
# ------------------------------------------------------------------
macos-build:
name: macOS .app (${{ matrix.arch }})
if: >-
github.event_name != 'workflow_dispatch' ||
inputs.only == '' ||
contains(inputs.only, 'macos')
# Both arches build on macos-15 (Apple Silicon) — the legacy
# macos-13 (Intel) runner is being retired by GitHub and has been
# flaky for months. The x86_64 build uses Rosetta: a parallel Intel
# Homebrew install at /usr/local supplies x86_64 dep bottles, and
# every command that produces x86_64 output is wrapped in
# `arch -x86_64`. CMake honours MACOS_ARCHITECTURES from the env
# (handled in packaging/macos/build.sh) so clang emits the right
# slice. End result is identical to a native Intel build, with the
# benefit of running on a much beefier ARM host.
strategy:
fail-fast: false
matrix:
include:
- arch: arm64
archcmd: ''
brew_prefix: /opt/homebrew
- arch: x86_64
archcmd: 'arch -x86_64'
brew_prefix: /usr/local
runs-on: macos-15
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
ref: ${{ inputs.checkout_ref || github.ref }}
- name: Bootstrap x86_64 Homebrew (Rosetta)
if: matrix.arch == 'x86_64'
run: |
# Apple Silicon runners ship Rosetta preinstalled. Install
# x86_64 Homebrew at /usr/local so we can fetch x86_64 bottles
# for our deps. The native /opt/homebrew install is left alone.
arch -x86_64 /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
- name: Install Homebrew deps
run: |
BREW=${{ matrix.brew_prefix }}/bin/brew
${{ matrix.archcmd }} $BREW update
${{ matrix.archcmd }} $BREW install --quiet \
cmake wxwidgets cryptopp libupnp gd gettext boost dylibbundler libmaxminddb
# Prepend the matrix-selected brew prefix to PATH so every
# `brew --prefix` / `cmake` / `pkg-config` invocation in the
# build script resolves against the right install. gettext
# is keg-only on macOS; add msgfmt to PATH for the NLS probe.
echo "${{ matrix.brew_prefix }}/bin" >> "$GITHUB_PATH"
echo "${{ matrix.brew_prefix }}/opt/gettext/bin" >> "$GITHUB_PATH"
- name: Build native-arch .app
env:
MACOS_ARCHITECTURES: ${{ matrix.arch }}
run: ${{ matrix.archcmd }} packaging/macos/build.sh
- name: Smoke-test amuled --version
run: |
# Mount the produced .dmg at a fixed path. The volume name
# contains spaces (e.g. "aMule 2.3.3-foo"), and parsing it
# out of hdiutil's tabular output is fragile — supply
# -mountpoint instead.
DMG=$(ls dist/aMule-*-macOS.dmg | head -1)
MNT=/tmp/amulemnt
mkdir -p "${MNT}"
hdiutil attach -nobrowse -mountpoint "${MNT}" "${DMG}"
# x86_64 binaries on Apple Silicon run via Rosetta automatically
# (no explicit arch prefix needed for execution), but be
# consistent. amuled --version exits 255 (wxApp::OnInit returns
# false after printing version → wxEntry returns -1). Check the
# banner via grep instead of relying on exit code. Pattern
# accepts the dev placeholder ("aMuleD GIT ...") and any
# tagged-release banner ("aMuleD 3.0.0 ...", etc.).
${{ matrix.archcmd }} "${MNT}/aMule.app/Contents/MacOS/amuled" --version 2>&1 | grep -q '^aMuleD '
# Sanity-check that aMuleGUI.app (the remote-GUI client) is
# also at the dmg root — packaging/macos/build.sh stages it
# next to aMule.app via make_dmg, so its absence would mean
# BUILD_REMOTEGUI didn't actually produce a bundle.
[ -d "${MNT}/aMuleGUI.app" ] || { echo "aMuleGUI.app missing from per-arch dmg" >&2; exit 1; }
hdiutil detach "${MNT}"
- uses: actions/upload-artifact@v7
with:
# Upload the produced .app tree (not the .dmg) so the merge
# job can lipo-merge mach-o files. The final lipo'd .app gets
# re-wrapped into a Universal2 .dmg in the merge job.
name: macos-app-${{ matrix.arch }}
path: build-macos/src/aMule.app
if-no-files-found: error
# Preserve symlinks + permissions inside the .app.
retention-days: 1
- uses: actions/upload-artifact@v7
with:
# aMuleGUI.app is a separate bundle (the remote-GUI client);
# uploaded alongside aMule.app so the merge job can lipo it
# the same way and ship both in the Universal2 .dmg.
name: macos-gui-${{ matrix.arch }}
path: build-macos/src/aMuleGUI.app
if-no-files-found: error
retention-days: 1
macos-universal2:
name: macOS Universal2 .dmg
needs: macos-build
if: >-
github.event_name != 'workflow_dispatch' ||
inputs.only == '' ||
contains(inputs.only, 'macos')
runs-on: macos-15
steps:
- uses: actions/checkout@v6
with:
ref: ${{ inputs.checkout_ref || github.ref }}
- uses: actions/download-artifact@v8
with:
name: macos-app-arm64
path: arm64.app
- uses: actions/download-artifact@v8
with:
name: macos-app-x86_64
path: x86_64.app
- uses: actions/download-artifact@v8
with:
name: macos-gui-arm64
path: arm64-gui.app
- uses: actions/download-artifact@v8
with:
name: macos-gui-x86_64
path: x86_64-gui.app
- name: lipo-merge into Universal2 .app bundles
run: |
# Merges two per-arch .app bundles (BASE = arm64, OTHER =
# x86_64) into a Universal2 OUT bundle. Uses the arm64 .app
# as the base layout; for every Mach-O file inside it, runs
# lipo-create with the matching x86_64 sibling. Side files
# (Info.plist, .icns, locale catalogs) are arch-agnostic
# and inherited from arm64 unchanged.
merge_app() {
local BASE="$1"
local OTHER="$2"
local OUT="$3"
cp -R "${BASE}" "${OUT}"
local rel local_arm local_x86
while IFS= read -r -d '' rel; do
local_arm="${BASE}/${rel}"
local_x86="${OTHER}/${rel}"
if file "${local_arm}" | grep -q "Mach-O" && [ -f "${local_x86}" ]; then
lipo -create -output "${OUT}/${rel}" "${local_arm}" "${local_x86}"
# `lipo -create -output` writes the new file with the
# process umask (default 022 -> rw-r--r--), discarding
# the executable bit on the source. macOS launchd then
# refuses to spawn the bundle with errno 13 (EACCES)
# because access(X_OK) on the main exec fails. Restore
# the executable bit so launchd can spawn the binary.
chmod +x "${OUT}/${rel}"
fi
done < <(cd "${BASE}" && find . -type f -print0 | sed 's|^\./||g')
# Re-apply ad-hoc signatures to every nested Mach-O. clang on
# Apple Silicon emits ad-hoc-signed binaries by default; lipo
# invalidates those signatures on merge, and macOS amfid then
# refuses to load the resulting fat binary. `codesign --force
# --deep --sign -` rewrites valid ad-hoc sigs across the whole
# bundle. Required even before notarization for the binary to
# launch at all on Apple Silicon.
codesign --force --deep --sign - "${OUT}"
}
merge_app arm64.app x86_64.app aMule.app
merge_app arm64-gui.app x86_64-gui.app aMuleGUI.app
- name: Build Universal2 .dmg
run: |
VERSION=$(git describe --tags --always)
mkdir -p dist
STAGE=$(mktemp -d)
cp -R aMule.app "${STAGE}/"
cp -R aMuleGUI.app "${STAGE}/"
ln -s /Applications "${STAGE}/Applications"
hdiutil create -volname "aMule ${VERSION}" \
-srcfolder "${STAGE}" -ov -format UDZO \
"dist/aMule-${VERSION}-macOS-universal2.dmg"
- uses: actions/upload-artifact@v7
with:
name: macos-universal2
path: dist/aMule-*-macOS-universal2.dmg
if-no-files-found: error
# ------------------------------------------------------------------
# Windows — portable .zip for x64 (MINGW64) and ARM64 (CLANGARM64).
# ------------------------------------------------------------------
windows-zip:
name: Windows portable .zip (${{ matrix.arch }})
if: >-
github.event_name != 'workflow_dispatch' ||
inputs.only == '' ||
contains(inputs.only, 'windows')
strategy:
fail-fast: false
matrix:
include:
- arch: x64
msystem: MINGW64
runs-on: windows-2025
pkg_prefix: mingw-w64-x86_64
- arch: arm64
msystem: CLANGARM64
runs-on: windows-11-arm
pkg_prefix: mingw-w64-clang-aarch64
runs-on: ${{ matrix.runs-on }}
defaults:
run:
shell: msys2 {0}
steps:
- uses: actions/checkout@v6
with:
fetch-depth: 0
ref: ${{ inputs.checkout_ref || github.ref }}
- name: Set up MSYS2
uses: msys2/setup-msys2@v2
with:
msystem: ${{ matrix.msystem }}
update: true
install: >-
${{ matrix.pkg_prefix }}-boost
${{ matrix.pkg_prefix }}-cmake
${{ matrix.pkg_prefix }}-crypto++
${{ matrix.pkg_prefix }}-gettext
${{ matrix.pkg_prefix }}-libgd
${{ matrix.pkg_prefix }}-libmaxminddb
${{ matrix.pkg_prefix }}-make
${{ matrix.pkg_prefix }}-pkgconf
${{ matrix.pkg_prefix }}-pupnp
${{ matrix.pkg_prefix }}-readline
${{ matrix.pkg_prefix }}-toolchain
${{ matrix.pkg_prefix }}-wxwidgets3.2-msw
${{ matrix.pkg_prefix }}-zlib
git
zip
- name: Configure git safe.directory for MSYS2 git
# MSYS2 git (now installed above) uses a global config separate
# from the Windows git at C:\Program Files\Git\bin\git.exe that
# actions/checkout configures. Without this entry, MSYS2 git
# may trip the "dubious ownership" guard on the workspace dir,
# which would cause `git describe --tags` inside
# packaging/windows/build.sh to fall through the `2>/dev/null
# || echo "snapshot"` fallback and produce
# aMule-snapshot-Windows-*.zip instead of
# aMule-<tag>-Windows-*.zip.
run: git config --global --add safe.directory '*'
- name: Build portable .zip
env:
WINDOWS_MSYSTEM: ${{ matrix.msystem }}
run: packaging/windows/build.sh
- name: Smoke-test amuled.exe --version
run: |
# Two layered quirks here:
# 1. amuled.exe --version exits 255 (wxApp::OnInit returns
# false after banner → wxEntry returns -1). || true
# swallows that.
# 2. Piping `amuled.exe ... | grep -q` on MSYS2 bash exits
# 127: grep -q closes its pipe end at first match,
# amuled.exe gets SIGPIPE on its next stdout flush, MSYS2
# surfaces that as 127. Capture to a file first, then
# grep the file — no pipe race.
./amule-portable-${{ matrix.arch }}/bin/amuled.exe --version \
> /tmp/version.txt 2>&1 || true
cat /tmp/version.txt
# Pattern accepts the dev placeholder ("aMuleD GIT ...") and
# any tagged-release banner ("aMuleD 3.0.0 ...", etc.).
grep -q '^aMuleD ' /tmp/version.txt
- uses: actions/upload-artifact@v7
with:
name: windows-${{ matrix.arch }}
path: dist/aMule-*-Windows-${{ matrix.arch }}.zip
if-no-files-found: error
retention-days: 3