keep the packaging half off the public branch
primary still carries the whole workflow; the public projection carries the three portable gates and nothing that names the build host.
This commit is contained in:
parent
76846feb61
commit
2f685facda
2 changed files with 0 additions and 461 deletions
|
|
@ -131,8 +131,3 @@ jobs:
|
|||
exit 1
|
||||
fi
|
||||
echo "All action refs are SHA-pinned."
|
||||
|
||||
# Phone artifact on green. Runs on the ArchDev build node (host mode, label
|
||||
# archdev) where the aarch64 sysroot lives — no docker, no node, plain shell.
|
||||
# Publishes the cross-built binary to a rolling `edge` prerelease; the phone
|
||||
# updates itself from there instead of waiting on a laptop scp.
|
||||
|
|
|
|||
|
|
@ -1,456 +0,0 @@
|
|||
name: packages
|
||||
|
||||
# Internal only. Packaging, signing and archive publication run on the
|
||||
# build host where the aarch64 sysroot and the signing key live. This file
|
||||
# is not carried on the public branch; the gates in ci.yml are.
|
||||
on:
|
||||
push:
|
||||
branches: [primary, main]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
aarch64-artifact:
|
||||
runs-on: archdev
|
||||
needs: [rust-test, no-ai-attribution, action-pins]
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/primary'
|
||||
steps:
|
||||
- name: Clone repo + pinned tuie
|
||||
run: |
|
||||
set -euo pipefail
|
||||
rm -rf "$GITHUB_WORKSPACE/src"
|
||||
git -c http.extraheader="Authorization: token ${{ secrets.LOCAL_GITEA_TOKEN }}" \
|
||||
clone "${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git" "$GITHUB_WORKSPACE/src/Souveraine"
|
||||
git -C "$GITHUB_WORKSPACE/src/Souveraine" checkout "$GITHUB_SHA"
|
||||
git -c http.extraheader="Authorization: token ${{ secrets.LOCAL_GITEA_TOKEN }}" \
|
||||
clone "${GITHUB_SERVER_URL}/Fimeg/tuie.git" "$GITHUB_WORKSPACE/src/tuie"
|
||||
git -C "$GITHUB_WORKSPACE/src/tuie" checkout aa43e335c8f5a3cd2c78e397a1a8dfe534a6bc35
|
||||
|
||||
- name: Build release binaries
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd "$GITHUB_WORKSPACE/src/Souveraine"
|
||||
# Persistent target dirs: fresh clones per run, warm compile cache.
|
||||
export CARGO_TARGET_DIR="$HOME/.cache/souveraine-ci-target"
|
||||
export SOUVERAINE_AARCH64_SYSROOT="$HOME/aarch64-sysroot"
|
||||
./scripts/build-cross.sh
|
||||
BIN="$CARGO_TARGET_DIR/aarch64-unknown-linux-gnu/release/souveraine"
|
||||
file "$BIN" | grep -q aarch64 || { echo "built binary is not aarch64" >&2; exit 1; }
|
||||
cp "$BIN" souveraine-aarch64
|
||||
|
||||
# sessiond is a separate bin behind the sessiond feature. It was
|
||||
# hand-copied to the phone's /usr/local/bin and owned by no package,
|
||||
# so it never received updates; build and ship it with the rest.
|
||||
./scripts/build-cross.sh --features sessiond --bin souveraine-sessiond
|
||||
SBIN="$CARGO_TARGET_DIR/aarch64-unknown-linux-gnu/release/souveraine-sessiond"
|
||||
file "$SBIN" | grep -q aarch64 || { echo "sessiond is not aarch64" >&2; exit 1; }
|
||||
cp "$SBIN" souveraine-sessiond-aarch64
|
||||
|
||||
# The sensor reporter. Same story as sessiond: it replaces shell
|
||||
# scripts that shipped in rootfs-overlay/ and drifted per-device.
|
||||
./scripts/build-cross.sh --bin souveraine-sensord
|
||||
NBIN="$CARGO_TARGET_DIR/aarch64-unknown-linux-gnu/release/souveraine-sensord"
|
||||
file "$NBIN" | grep -q aarch64 || { echo "sensord is not aarch64" >&2; exit 1; }
|
||||
cp "$NBIN" souveraine-sensord-aarch64
|
||||
|
||||
# Full USB KVM receiver: GUD display-in and the HID return surface.
|
||||
./scripts/build-cross.sh --features usb-kvm --bin souveraine-usb-kvm
|
||||
UBIN="$CARGO_TARGET_DIR/aarch64-unknown-linux-gnu/release/souveraine-usb-kvm"
|
||||
file "$UBIN" | grep -q aarch64 || { echo "usb-kvm is not aarch64" >&2; exit 1; }
|
||||
cp "$UBIN" souveraine-usb-kvm-aarch64
|
||||
|
||||
# The wry host: self-hosted sites as apps, and the rig she wears.
|
||||
# Needs webkit2gtk on the build sysroot; it is already installed on
|
||||
# the phone (TASK-59 phase 1 measured against it).
|
||||
# Best effort: it links against the system webview, so it needs
|
||||
# webkit2gtk in the aarch64 sysroot. Until that is there this is the
|
||||
# one binary that may legitimately not build, and it must not stop the
|
||||
# ones that decide whether the phone locks.
|
||||
if ./scripts/build-cross.sh --features web --bin souveraine-web; then
|
||||
WBIN="$CARGO_TARGET_DIR/aarch64-unknown-linux-gnu/release/souveraine-web"
|
||||
if file "$WBIN" | grep -q aarch64; then
|
||||
cp "$WBIN" souveraine-web-aarch64
|
||||
else
|
||||
echo "::warning::web host built but is not aarch64; skipping it"
|
||||
fi
|
||||
else
|
||||
echo "::warning::the wry host did not cross-build (webkit2gtk sysroot?); skipping it"
|
||||
fi
|
||||
|
||||
# secrets rail + machined: also hand-copied on the phone until now.
|
||||
./scripts/build-cross.sh --features secrets --bin souveraine-secrets
|
||||
./scripts/build-cross.sh --bin souveraine-machined
|
||||
./scripts/build-cross.sh --bin souveraine-admit
|
||||
for b in souveraine-secrets souveraine-machined souveraine-admit; do
|
||||
B="$CARGO_TARGET_DIR/aarch64-unknown-linux-gnu/release/$b"
|
||||
file "$B" | grep -q aarch64 || { echo "$b is not aarch64" >&2; exit 1; }
|
||||
cp "$B" "$b-aarch64"
|
||||
done
|
||||
|
||||
export CARGO_TARGET_DIR="$HOME/.cache/souveraine-ci-target-x86_64"
|
||||
cargo build --release
|
||||
BIN="$CARGO_TARGET_DIR/release/souveraine"
|
||||
file "$BIN" | grep -q 'x86-64' || { echo "built binary is not x86_64" >&2; exit 1; }
|
||||
cp "$BIN" souveraine-x86_64
|
||||
|
||||
cargo build --release --features secrets --bin souveraine-secrets
|
||||
cargo build --release --bin souveraine-machined
|
||||
cargo build --release --bin souveraine-admit
|
||||
for b in souveraine-secrets souveraine-machined souveraine-admit; do
|
||||
B="$CARGO_TARGET_DIR/release/$b"
|
||||
file "$B" | grep -q 'x86-64' || { echo "$b is not x86_64" >&2; exit 1; }
|
||||
cp "$B" "$b-x86_64"
|
||||
done
|
||||
|
||||
# sessiond for x86_64 as well. It was skipped here with a comment
|
||||
# calling it deliberate; it never was (Casey, 2026-08-02) — the
|
||||
# laptop hit lock-screen errors with it once and it stayed
|
||||
# phone-only by inertia. That inertia is now load-bearing in the
|
||||
# wrong direction: viewtop targets the laptop screen too
|
||||
# (VIEWTOP-AND-DENIAL.md), and panel power, the LockedHint report and
|
||||
# button reporting all assume the daemon is there — so no session
|
||||
# authority on x86 means no viewtop on the laptop.
|
||||
#
|
||||
# Building and packaging are not enabling. The package-owned user
|
||||
# unit ships on both architectures, but package installation neither
|
||||
# enables nor starts it; target activation remains separately tested.
|
||||
cargo build --release --features sessiond --bin souveraine-sessiond
|
||||
B="$CARGO_TARGET_DIR/release/souveraine-sessiond"
|
||||
file "$B" | grep -q 'x86-64' || { echo "sessiond is not x86_64" >&2; exit 1; }
|
||||
cp "$B" souveraine-sessiond-x86_64
|
||||
|
||||
# sensord for x86_64 too. It stopped being phone-only when charge
|
||||
# became a source: sessiond no longer probes the supplies itself, so
|
||||
# a machine without the reporter has no charge evidence at all — and
|
||||
# the laptop is a machine with a battery.
|
||||
cargo build --release --bin souveraine-sensord
|
||||
B="$CARGO_TARGET_DIR/release/souveraine-sensord"
|
||||
file "$B" | grep -q 'x86-64' || { echo "sensord is not x86_64" >&2; exit 1; }
|
||||
cp "$B" souveraine-sensord-x86_64
|
||||
|
||||
sha256sum souveraine-aarch64 souveraine-x86_64 \
|
||||
souveraine-sessiond-aarch64 souveraine-sensord-aarch64 \
|
||||
souveraine-usb-kvm-aarch64 \
|
||||
souveraine-secrets-aarch64 souveraine-secrets-x86_64 \
|
||||
souveraine-machined-aarch64 souveraine-machined-x86_64 \
|
||||
souveraine-admit-aarch64 souveraine-admit-x86_64 \
|
||||
souveraine-sessiond-x86_64 souveraine-sensord-x86_64 \
|
||||
> souveraine-binaries.sha256
|
||||
|
||||
- name: Build UPower fork (per-arch install trees)
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd "$GITHUB_WORKSPACE/src/Souveraine"
|
||||
# The fork is a git submodule of Souveraine. The runner checkout
|
||||
# above is not recursive; clone it explicitly with the same LAN
|
||||
# token used for tuie, pinned to the submodule's recorded commit.
|
||||
UPOWER_URL=$(git config --file .gitmodules submodule."packaging/upower-souveraine".url)
|
||||
UPOWER_SHA=$(git ls-tree HEAD packaging/upower-souveraine | awk '{print $3}')
|
||||
git -c http.extraheader="Authorization: token ${{ secrets.LOCAL_GITEA_TOKEN }}" \
|
||||
clone "$UPOWER_URL" "$GITHUB_WORKSPACE/src/upower"
|
||||
git -C "$GITHUB_WORKSPACE/src/upower" checkout "$UPOWER_SHA"
|
||||
|
||||
SYSROOT="$HOME/aarch64-sysroot"
|
||||
# .cargo/aarch64-pkg-config reads SOUVERAINE_AARCH64_SYSROOT and falls
|
||||
# back to /usr/aarch64-linux-gnu, which has no glib. Steps do not share
|
||||
# environment, so exporting it in the binaries step does not reach here.
|
||||
export SOUVERAINE_AARCH64_SYSROOT="$SYSROOT"
|
||||
|
||||
# --- x86_64: native build on the archdev host ---
|
||||
(
|
||||
cd "$GITHUB_WORKSPACE/src/upower"
|
||||
# gtkdoc-scan is not installed on the runner, so gtk-doc=true fails
|
||||
# here too; man needs the same toolchain. Introspection is left ON
|
||||
# for the native build — it works, and costs nothing.
|
||||
meson setup build-x86_64 \
|
||||
--prefix=/usr --sysconfdir=/etc --localstatedir=/var \
|
||||
-Dsystemdsystemunitdir=/usr/lib/systemd/system \
|
||||
-Dgtk-doc=false -Dman=false
|
||||
meson compile -C build-x86_64
|
||||
DESTDIR="$GITHUB_WORKSPACE/src/upower/dest-x86_64" meson install -C build-x86_64
|
||||
)
|
||||
tar -C "$GITHUB_WORKSPACE/src/upower/dest-x86_64" \
|
||||
-cf "$GITHUB_WORKSPACE/src/Souveraine/upower-tree-x86_64.tar" .
|
||||
|
||||
# --- aarch64: cross build against the same sysroot souveraine uses ---
|
||||
CROSS="$GITHUB_WORKSPACE/src/upower/aarch64-cross.ini"
|
||||
cat > "$CROSS" <<EOF
|
||||
[binaries]
|
||||
c = 'aarch64-linux-gnu-gcc'
|
||||
cpp = 'aarch64-linux-gnu-g++'
|
||||
ar = 'aarch64-linux-gnu-ar'
|
||||
strip = 'aarch64-linux-gnu-strip'
|
||||
pkgconfig = '$PWD/.cargo/aarch64-pkg-config'
|
||||
# gobject-introspection is on by default and RUNS the aarch64 binary
|
||||
# it just built (g-ir-scanner). qemu needs -L to find the aarch64
|
||||
# loader; binfmt is registered on the Proxmox host so this works
|
||||
# inside the unprivileged archdev container.
|
||||
exe_wrapper = ['qemu-aarch64-static', '-L', '$SYSROOT']
|
||||
[built-in options]
|
||||
c_args = ['--sysroot=$SYSROOT']
|
||||
cpp_args = ['--sysroot=$SYSROOT']
|
||||
# -L as well as --sysroot: libc.so/libbsd.so in the sysroot are linker
|
||||
# SCRIPTS naming bare paths (libm, libmvec, -lmd), which ld resolves
|
||||
# against its own prefix and misses without an explicit search dir.
|
||||
c_link_args = ['--sysroot=$SYSROOT', '-L$SYSROOT/usr/lib']
|
||||
cpp_link_args = ['--sysroot=$SYSROOT', '-L$SYSROOT/usr/lib']
|
||||
[host_machine]
|
||||
system = 'linux'
|
||||
cpu_family = 'aarch64'
|
||||
cpu = 'aarch64'
|
||||
endian = 'little'
|
||||
EOF
|
||||
(
|
||||
cd "$GITHUB_WORKSPACE/src/upower"
|
||||
PKG_CONFIG_ALLOW_CROSS=1 \
|
||||
PKG_CONFIG_LIBDIR="$SYSROOT/usr/lib/pkgconfig" \
|
||||
PKG_CONFIG_SYSROOT_DIR="$SYSROOT" \
|
||||
# gtk-doc/man need host doc tooling, and introspection needs a
|
||||
# g-ir-scanner that can scan an aarch64 build (the host copy reads
|
||||
# its data files out of the sysroot and fails). None of the three
|
||||
# ship anything the phone uses — quickshell's UPower module is
|
||||
# native Qt, and the device carries no UPowerGlib typelib.
|
||||
meson setup build-aarch64 \
|
||||
--prefix=/usr --sysconfdir=/etc --localstatedir=/var \
|
||||
-Dsystemdsystemunitdir=/usr/lib/systemd/system \
|
||||
-Dgtk-doc=false -Dman=false -Dintrospection=disabled \
|
||||
--cross-file "$CROSS"
|
||||
meson compile -C build-aarch64
|
||||
DESTDIR="$GITHUB_WORKSPACE/src/upower/dest-aarch64" meson install -C build-aarch64
|
||||
)
|
||||
# Sanity: the aarch64 upowerd must actually be aarch64.
|
||||
# It installs to libexec/, not lib/ — the old path made this check
|
||||
# fail even on a good build.
|
||||
file "$GITHUB_WORKSPACE/src/upower/dest-aarch64/usr/libexec/upowerd" \
|
||||
| grep -q aarch64 || { echo "aarch64 upowerd is not aarch64" >&2; exit 1; }
|
||||
# Cross-install leak. upower asks pkg-config for the udev dir, and
|
||||
# with a sysroot in play that answer comes back sysroot-prefixed, so
|
||||
# the rules and hwdb install under $DESTDIR/home/casey/aarch64-sysroot/
|
||||
# instead of /usr/lib/udev. systemdsystemunitdir is passed explicitly
|
||||
# above for exactly this reason; the udev dir was missed. Measured on
|
||||
# the phone 2026-07-27: all four of 60-upower-battery.{rules,hwdb},
|
||||
# 95-upower-wup.rules and 95-upower-hid.hwdb were absent from
|
||||
# /usr/lib/udev and present only under the junk path — so the fork's
|
||||
# udev quirks had never once been applied on the device.
|
||||
# Fold any leaked tree back before the tar, then refuse to ship a
|
||||
# tree containing anything but the three prefixes upower legitimately
|
||||
# installs into: usr/, etc/ (UPower.conf) and var/ (var/lib/upower).
|
||||
# Leaving var/ out of that list is what failed run 1234.
|
||||
DEST="$GITHUB_WORKSPACE/src/upower/dest-aarch64"
|
||||
LEAK="$DEST$HOME/aarch64-sysroot"
|
||||
if [ -d "$LEAK" ]; then
|
||||
echo "cross install leaked into $HOME/aarch64-sysroot — relocating"
|
||||
cp -a "$LEAK/." "$DEST/"
|
||||
rm -rf "$LEAK"
|
||||
# Removing the sysroot subtree leaves its empty parents behind
|
||||
# ($DEST/home/casey), and an empty directory still ships AND still
|
||||
# trips the stray check below — which is how runs 1234 and 1248
|
||||
# failed. The PKGBUILD copy of this had the rmdir; this one did not.
|
||||
rmdir -p --ignore-fail-on-non-empty "$(dirname "$LEAK")" 2>/dev/null || true
|
||||
fi
|
||||
stray=$(find "$DEST" -mindepth 1 -maxdepth 1 \
|
||||
! -name usr ! -name etc ! -name var -printf '%f\n')
|
||||
if [ -n "$stray" ]; then
|
||||
echo "upower tree would ship outside usr/, etc/ and var/: $stray" >&2
|
||||
exit 1
|
||||
fi
|
||||
# And the rules must have landed where udev actually reads them.
|
||||
for f in usr/lib/udev/rules.d/60-upower-battery.rules \
|
||||
usr/lib/udev/hwdb.d/60-upower-battery.hwdb; do
|
||||
[ -e "$DEST/$f" ] || { echo "upower tree is missing $f" >&2; exit 1; }
|
||||
done
|
||||
tar -C "$GITHUB_WORKSPACE/src/upower/dest-aarch64" \
|
||||
-cf "$GITHUB_WORKSPACE/src/Souveraine/upower-tree-aarch64.tar" .
|
||||
|
||||
- name: Stage the shell surface for packaging
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd "$GITHUB_WORKSPACE/src/Souveraine"
|
||||
# deploy.sh composes ~/.config/quickshell/souveraine from repo files
|
||||
# (symlinks) plus ii dirs borrowed from the ii-base pin. Run it in a
|
||||
# scratch HOME and tar the result dereferenced, so the package is
|
||||
# self-contained real files and never ships dangling links.
|
||||
SHELL_STAGE="$GITHUB_WORKSPACE/shell-stage"
|
||||
SHELL_TAR="$GITHUB_WORKSPACE/shell-package-input"
|
||||
rm -rf "$SHELL_STAGE" "$SHELL_TAR"
|
||||
mkdir -p "$SHELL_STAGE" "$SHELL_TAR"
|
||||
HOME="$SHELL_STAGE" ./surfaces/quickshell/deploy.sh
|
||||
test -L "$SHELL_STAGE/.config/quickshell/souveraine/shell.qml"
|
||||
tar -h --zstd -C "$SHELL_STAGE/.config/quickshell" -cf "$SHELL_TAR/souveraine-shell-config.tar.zst" souveraine
|
||||
tar -tf "$SHELL_TAR/souveraine-shell-config.tar.zst" | grep -qx 'souveraine/shell.qml'
|
||||
|
||||
- name: Package and sign pacman repository
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd "$GITHUB_WORKSPACE/src/Souveraine"
|
||||
PKGVER="0.1.r$(git rev-list --count HEAD).g${GITHUB_SHA:0:12}"
|
||||
WORK="$GITHUB_WORKSPACE/pacman-package"
|
||||
REPO="$GITHUB_WORKSPACE/pacman-repo"
|
||||
ARCHIVE_KEY="3CD9E99E222C2A174986FC9AFF4949AA20C8E911"
|
||||
rm -rf "$WORK" "$REPO"
|
||||
mkdir -p "$WORK" "$REPO"
|
||||
|
||||
for ARCH in aarch64 x86_64; do
|
||||
PKG_WORK="$WORK/$ARCH"
|
||||
ARCH_REPO="$REPO/$ARCH"
|
||||
mkdir -p "$PKG_WORK" "$ARCH_REPO"
|
||||
cp "souveraine-$ARCH" "$PKG_WORK/souveraine-binary"
|
||||
cp "souveraine-secrets-$ARCH" "$PKG_WORK/souveraine-secrets-binary"
|
||||
cp "souveraine-machined-$ARCH" "$PKG_WORK/souveraine-machined-binary"
|
||||
cp "souveraine-admit-$ARCH" "$PKG_WORK/souveraine-admit-binary"
|
||||
cp "souveraine-sessiond-$ARCH" "$PKG_WORK/souveraine-sessiond-binary"
|
||||
cp "souveraine-sensord-$ARCH" "$PKG_WORK/souveraine-sensord-binary"
|
||||
cp packaging/souveraine.service packaging/souveraine-secrets.service \
|
||||
packaging/org.freedesktop.secrets.service \
|
||||
packaging/souveraine-machined.service \
|
||||
packaging/souveraine-sessiond.service \
|
||||
packaging/souveraine-sensord.service LICENSE "$PKG_WORK/"
|
||||
cp packaging/arch/souveraine.sysusers "$PKG_WORK/"
|
||||
# Phone-only reporters and surfaces remain aarch64-only.
|
||||
if [ "$ARCH" = aarch64 ]; then
|
||||
cp "souveraine-usb-kvm-$ARCH" "$PKG_WORK/souveraine-usb-kvm-binary"
|
||||
# The wry host. Guarded, and the PKGBUILD source line is removed
|
||||
# when it is absent: it needs webkit2gtk in the aarch64 sysroot,
|
||||
# and a missing avatar must not stop sessiond reaching the phone.
|
||||
# makepkg validates every entry in `source`, so leaving a name
|
||||
# there with no file fails the whole package.
|
||||
if [ -f "souveraine-web-$ARCH" ]; then
|
||||
cp "souveraine-web-$ARCH" "$PKG_WORK/souveraine-web-binary"
|
||||
fi
|
||||
fi
|
||||
cp packaging/souveraine-verify-trail "$PKG_WORK/"
|
||||
cp packaging/souveraine-button "$PKG_WORK/"
|
||||
cp packaging/souveraine-stepup.pam packaging/souveraine-sessiond.pam \
|
||||
packaging/org.souveraine.stepup.policy "$PKG_WORK/"
|
||||
cp packaging/arch/PKGBUILD.prebuilt "$PKG_WORK/PKGBUILD"
|
||||
(
|
||||
cd "$PKG_WORK"
|
||||
export SOUVERAINE_PKGVER="$PKGVER"
|
||||
export SOUVERAINE_PKGARCH="$ARCH"
|
||||
CARCH="$ARCH" makepkg --nodeps --noconfirm --cleanbuild
|
||||
)
|
||||
PKG=$(find "$PKG_WORK" -maxdepth 1 -name 'souveraine-*.pkg.tar.zst' -print -quit)
|
||||
test -n "$PKG"
|
||||
bsdtar -tf "$PKG" | grep -qx 'usr/bin/souveraine'
|
||||
bsdtar -tf "$PKG" | grep -qx 'usr/bin/souveraine-sessiond'
|
||||
bsdtar -tf "$PKG" | grep -qx 'usr/lib/systemd/user/souveraine-sessiond.service'
|
||||
bsdtar -tf "$PKG" | grep -qx 'usr/bin/souveraine-sensord'
|
||||
bsdtar -tf "$PKG" | grep -qx 'etc/pam.d/souveraine-sessiond'
|
||||
bsdtar -tf "$PKG" | grep -qx 'usr/lib/sysusers.d/souveraine.conf'
|
||||
bsdtar -tf "$PKG" | grep -qx 'usr/bin/souveraine-admit'
|
||||
if [ "$ARCH" = aarch64 ]; then
|
||||
bsdtar -tf "$PKG" | grep -qx 'usr/bin/souveraine-usb-kvm'
|
||||
fi
|
||||
cp "$PKG" "$ARCH_REPO/"
|
||||
gpg --batch --yes --local-user "$ARCHIVE_KEY" \
|
||||
--detach-sign "$ARCH_REPO/$(basename "$PKG")"
|
||||
|
||||
# UPower fork package — built from packaging/upower-souveraine
|
||||
# (git submodule of the Souveraine fork of upstream upower). Built
|
||||
# natively per-arch by the "Build UPower fork" step above into
|
||||
# upower-tree-$ARCH.tar, then folded into the SAME per-arch pacman
|
||||
# database so the phone installs upower-souveraine from the same
|
||||
# edge archive it already uses for souveraine.
|
||||
# Version from UPSTREAM upower + the fork commit, NOT souveraine's
|
||||
# r-count. The hand-built package on the phone was 1.91.3+<sha>;
|
||||
# reusing souveraine's 0.1.rN here sorts LOWER, so pacman treats
|
||||
# the repo copy as a downgrade and -Syu silently skips it.
|
||||
UPOWER_VER=$(sed -nE "s/^ *version *: *'([^']+)'.*/\1/p" \
|
||||
"$GITHUB_WORKSPACE/src/upower/meson.build" | head -1)
|
||||
# '.r' not '+': a literal + in a release asset filename cannot be
|
||||
# fetched from Gitea at all — it is stored decoded as a space, and
|
||||
# both the raw + and %2B forms 404. Still sorts above the old
|
||||
# hand-built 1.91.3+<sha> because vercmp reads + as a separator too.
|
||||
UPOWER_PKGVER="${UPOWER_VER}.r$(git -C "$GITHUB_WORKSPACE/src/upower" rev-parse --short HEAD)"
|
||||
|
||||
UPOWER_WORK="$WORK/upower-$ARCH"
|
||||
mkdir -p "$UPOWER_WORK"
|
||||
cp "upower-tree-$ARCH.tar" "$UPOWER_WORK/upower-tree.tar"
|
||||
cp packaging/upower-souveraine/dbus/org.freedesktop.UPower.Device.xml \
|
||||
"$UPOWER_WORK/" 2>/dev/null \
|
||||
|| cp "$GITHUB_WORKSPACE/src/upower/dbus/org.freedesktop.UPower.Device.xml" \
|
||||
"$UPOWER_WORK/"
|
||||
cp packaging/arch/PKGBUILD.upower.prebuilt "$UPOWER_WORK/PKGBUILD"
|
||||
(
|
||||
cd "$UPOWER_WORK"
|
||||
export SOUVERAINE_PKGVER="$UPOWER_PKGVER"
|
||||
export SOUVERAINE_PKGARCH="$ARCH"
|
||||
CARCH="$ARCH" makepkg --nodeps --noconfirm --cleanbuild
|
||||
)
|
||||
UPKG=$(find "$UPOWER_WORK" -maxdepth 1 -name 'upower-souveraine-*.pkg.tar.zst' -print -quit)
|
||||
test -n "$UPKG"
|
||||
# libexec/, not lib/ — same path correction as the sanity check above.
|
||||
bsdtar -tf "$UPKG" | grep -qx 'usr/libexec/upowerd'
|
||||
cp "$UPKG" "$ARCH_REPO/"
|
||||
gpg --batch --yes --local-user "$ARCHIVE_KEY" \
|
||||
--detach-sign "$ARCH_REPO/$(basename "$UPKG")"
|
||||
|
||||
# Shell package — the composed quickshell config, arch=any, from
|
||||
# the staged tar. Same per-arch database as the binaries above.
|
||||
SHELL_WORK="$WORK/shell-$ARCH"
|
||||
mkdir -p "$SHELL_WORK"
|
||||
cp "$GITHUB_WORKSPACE/shell-package-input/souveraine-shell-config.tar.zst" "$SHELL_WORK/"
|
||||
cp packaging/arch/PKGBUILD.shell.prebuilt "$SHELL_WORK/PKGBUILD"
|
||||
cp LICENSE "$SHELL_WORK/"
|
||||
(
|
||||
cd "$SHELL_WORK"
|
||||
export SOUVERAINE_PKGVER="$PKGVER"
|
||||
CARCH="$ARCH" makepkg --nodeps --noconfirm --cleanbuild
|
||||
)
|
||||
SPKG=$(find "$SHELL_WORK" -maxdepth 1 -name 'souveraine-shell-*.pkg.tar.zst' -print -quit)
|
||||
test -n "$SPKG"
|
||||
bsdtar -tf "$SPKG" | grep -qx 'etc/xdg/quickshell/souveraine/shell.qml'
|
||||
bsdtar -tf "$SPKG" | grep -qx 'usr/share/licenses/souveraine-shell/LICENSE'
|
||||
cp "$SPKG" "$ARCH_REPO/"
|
||||
gpg --batch --yes --local-user "$ARCHIVE_KEY" \
|
||||
--detach-sign "$ARCH_REPO/$(basename "$SPKG")"
|
||||
|
||||
# The per-arch database is NOT built here. `edge` is a shared archive
|
||||
# with more than one producer in it, so the database has to be
|
||||
# read-modify-written against the live copy rather than generated
|
||||
# fresh — packaging/arch/publish-edge.sh owns that, under a lock.
|
||||
done
|
||||
cp packaging/arch/souveraine-archive-key.asc "$REPO/"
|
||||
|
||||
- name: Publish rolling edge prerelease
|
||||
env:
|
||||
# A PAT rather than the job's own GITHUB_TOKEN, so the identical
|
||||
# invocation works from a producer repo other than this one.
|
||||
EDGE_TOKEN: ${{ secrets.LOCAL_GITEA_TOKEN }}
|
||||
ARCHIVE_KEY: 3CD9E99E222C2A174986FC9AFF4949AA20C8E911
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd "$GITHUB_WORKSPACE/src/Souveraine"
|
||||
# Additive: the release and tag are never deleted, the live databases
|
||||
# are merged into, and only this producer's own superseded packages
|
||||
# are removed. Before 2026-07-25 this step deleted and recreated the
|
||||
# release, which erased every other producer's packages on each push.
|
||||
export EDGE_TARGET_SHA="$GITHUB_SHA"
|
||||
export PRODUCER_VERSION="0.1.r$(git rev-list --count HEAD).g${GITHUB_SHA:0:12}"
|
||||
./packaging/arch/publish-edge.sh souveraine "$GITHUB_WORKSPACE/pacman-repo" \
|
||||
souveraine-aarch64 souveraine-x86_64 souveraine-binaries.sha256 \
|
||||
"$GITHUB_WORKSPACE/pacman-repo/souveraine-archive-key.asc"
|
||||
|
||||
- name: Mirror into the Gitea Arch registry (alongside edge)
|
||||
# Best-effort, never fails the publish: the registry sits alongside
|
||||
# release-assets until proven as the phone's source. A 409 means
|
||||
# (name, version) is already present immutably -- bump to republish.
|
||||
# Device-side auth is handled by souveraine-pacman-fetch; this only
|
||||
# uploads. Covers souveraine + upower-souveraine (both arches).
|
||||
env:
|
||||
EDGE_TOKEN: ${{ secrets.LOCAL_GITEA_TOKEN }}
|
||||
run: |
|
||||
set +e
|
||||
REG="$GITHUB_SERVER_URL/api/packages/${GITHUB_REPOSITORY%/*}/arch/edge"
|
||||
ok=0; skip=0; bad=0
|
||||
shopt -s nullglob
|
||||
for pkg in "$GITHUB_WORKSPACE"/pacman-repo/*/*.pkg.tar.zst; do
|
||||
code=$(curl -s -o /dev/null -w "%{http_code}" -X PUT \
|
||||
-H "Authorization: token $EDGE_TOKEN" --upload-file "$pkg" "$REG")
|
||||
case "$code" in
|
||||
200|201) echo "registry: published $(basename "$pkg")"; ok=$((ok+1));;
|
||||
409) echo "registry: present $(basename "$pkg") (bump to republish)"; skip=$((skip+1));;
|
||||
*) echo "::warning::registry $(basename "$pkg") -> HTTP $code"; bad=$((bad+1));;
|
||||
esac
|
||||
done
|
||||
echo "registry mirror: $ok new, $skip present, $bad failed"
|
||||
exit 0
|
||||
Loading…
Reference in a new issue