66 workflow_dispatch : {}
77
88jobs :
9- build :
9+ # ────────────────────────────────────────────────────────────────────
10+ # Build the libloot Python extension. Split out so it can be cached
11+ # independently — the Rust compile is ~80s and only needs to re-run
12+ # when libloot's master HEAD or the host Python ABI changes.
13+ # ────────────────────────────────────────────────────────────────────
14+ libloot :
15+ name : Build libloot extension
16+ runs-on : ubuntu-latest
17+ container : ghcr.io/pkgforge-dev/archlinux:latest
18+ outputs :
19+ so-name : ${{ steps.detect.outputs.so-name }}
20+ libloot-rev : ${{ steps.detect.outputs.libloot-rev }}
21+ steps :
22+ - uses : actions/checkout@v4
23+
24+ - name : Install build dependencies
25+ run : |
26+ pacman -Syy --noconfirm
27+ pacman -S --noconfirm \
28+ python python-pip base-devel rust git unzip
29+
30+ - name : Resolve libloot revision and Python ABI
31+ id : detect
32+ run : |
33+ # Latest libloot master commit — used as a cache key so that
34+ # bumps to libloot trigger a rebuild but unrelated re-runs hit
35+ # the cache.
36+ LIBLOOT_REV=$(git ls-remote https://github.com/loot/libloot.git HEAD | awk '{print substr($1,1,12)}')
37+ PY_TAG=$(python3 -c 'import sys; print(f"cp{sys.version_info.major}{sys.version_info.minor}")')
38+ SO_NAME="loot.cpython-${PY_TAG#cp}-x86_64-linux-gnu.so"
39+ echo "libloot-rev=$LIBLOOT_REV" >> "$GITHUB_OUTPUT"
40+ echo "py-tag=$PY_TAG" >> "$GITHUB_OUTPUT"
41+ echo "so-name=$SO_NAME" >> "$GITHUB_OUTPUT"
42+ echo "libloot=$LIBLOOT_REV py=$PY_TAG so=$SO_NAME"
43+
44+ - name : Cache built extension
45+ id : cache
46+ uses : actions/cache@v4
47+ with :
48+ path : src/LOOT/${{ steps.detect.outputs.so-name }}
49+ key : libloot-${{ steps.detect.outputs.libloot-rev }}-${{ steps.detect.outputs.py-tag }}
50+
51+ - name : Build extension
52+ if : steps.cache.outputs.cache-hit != 'true'
53+ run : bash src/LOOT/rebuild_libloot.sh
54+
55+ - name : Upload extension as job artifact
56+ uses : actions/upload-artifact@v4
57+ with :
58+ name : libloot-extension
59+ path : src/LOOT/loot.cpython-*-x86_64-linux-gnu.so
60+ if-no-files-found : error
61+ retention-days : 1
62+
63+ # ────────────────────────────────────────────────────────────────────
64+ # Build the AppImage. Pulls the precompiled libloot .so from the
65+ # previous job rather than rebuilding it.
66+ # ────────────────────────────────────────────────────────────────────
67+ appimage :
68+ name : Build AppImage
69+ needs : libloot
1070 runs-on : ubuntu-latest
1171 container : ghcr.io/pkgforge-dev/archlinux:latest
1272 steps :
@@ -22,28 +82,20 @@ jobs:
2282 # tk: tkinter import inside the bundled Python.
2383 # zenity: file-picker fallback used by portal_filechooser.py.
2484 # libarchive: bsdtar + libarchive.so.13 for fast extraction.
25- # python-pip + base-devel: pip install --target and the
26- # anylinux.so cc step.
27- # rust + git + unzip: building libloot from source via
28- # src/LOOT/rebuild_libloot.sh (the .so is gitignored, not
29- # shipped in the repo).
30- # python-customtkinter is pip-installed into _vendor/ via
31- # requirements-appimage.txt, no need to install it here.
3285 pacman -Syu --noconfirm \
3386 python-gobject \
3487 python-cairo \
3588 python-pip \
3689 tk \
3790 zenity \
3891 libarchive \
39- base-devel \
40- wget \
41- rust \
42- git \
43- unzip
92+ wget
4493
45- - name : Build libloot Python extension
46- run : bash src/LOOT/rebuild_libloot.sh
94+ - name : Download libloot extension
95+ uses : actions/download-artifact@v4
96+ with :
97+ name : libloot-extension
98+ path : src/LOOT/
4799
48100 - name : Build AppImage
49101 env :
0 commit comments