An empty home/casey still ships and still trips the stray check. Runs 1234 and 1248 were both this guard, not the build.
416 lines
22 KiB
YAML
416 lines
22 KiB
YAML
name: ci
|
|
# CI for souveraine — Rust crate. Tests + clippy on push/PR to primary (dev)
|
|
# and public (published). On push to public, mirror public:public to Codeberg
|
|
# on green. primary stays the private dev branch; public is what publishes.
|
|
#
|
|
# Required repo secrets:
|
|
# CODEBERG_TOKEN — push to codeberg.org/Fimeg/Souveraine (public branch)
|
|
on:
|
|
push:
|
|
branches: [primary, public]
|
|
pull_request:
|
|
branches: [primary, public]
|
|
|
|
jobs:
|
|
rust-test:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
- name: Install system deps
|
|
run: sudo apt-get update -qq && sudo apt-get install -y -qq libasound2-dev libchafa-dev
|
|
# Pinned fork on our Gitea (rgb patch committed there) — upstream HEAD
|
|
# must never decide whether our build passes.
|
|
- name: Clone tuie (pinned fork)
|
|
run: |
|
|
git -c http.extraheader="Authorization: token ${{ secrets.LOCAL_GITEA_TOKEN }}" \
|
|
clone "${GITHUB_SERVER_URL}/Fimeg/tuie.git" /workspace/Fimeg/tuie
|
|
git -C /workspace/Fimeg/tuie checkout aa43e335c8f5a3cd2c78e397a1a8dfe534a6bc35
|
|
- uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8
|
|
with:
|
|
toolchain: "1.94"
|
|
components: clippy
|
|
- name: cargo test
|
|
run: cargo test
|
|
- name: cargo clippy
|
|
run: cargo clippy -- -D warnings
|
|
|
|
no-ai-attribution:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
with:
|
|
fetch-depth: 0
|
|
- name: Check commit messages for AI attribution
|
|
run: |
|
|
if [ "${{ github.event_name }}" = "pull_request" ]; then
|
|
RANGE="${{ github.event.pull_request.base.sha }}..${{ github.sha }}"
|
|
else
|
|
RANGE="${{ github.event.before }}..${{ github.sha }}"
|
|
if [ "${{ github.event.before }}" = "0000000000000000000000000000000000000000" ]; then
|
|
RANGE="HEAD~10..HEAD"
|
|
fi
|
|
fi
|
|
# CO assembled from fragments so this guard file does not itself trip
|
|
# the public-branch pre-commit scanner (which bans the literal token).
|
|
CO="Co-Authored""-By:"
|
|
PATTERNS="${CO}.*[Cc]laude|${CO}.*OpenAI|${CO}.*ChatGPT|${CO}.*Copilot|${CO}.*Letta|${CO}.*Cursor|Generated by|Generated with|AI-assisted|Auto-generated by"
|
|
FAIL=0
|
|
while IFS= read -r msg; do
|
|
if echo "$msg" | grep -qiE "$PATTERNS"; then
|
|
echo "::error::AI attribution found in commit: $msg"
|
|
FAIL=1
|
|
fi
|
|
done < <(git log --format='%s%n%b' $RANGE 2>/dev/null)
|
|
if [ "$FAIL" -eq 1 ]; then
|
|
echo "::error::Commits contain AI attribution lines. Remove them before merging."
|
|
exit 1
|
|
fi
|
|
echo "No AI attribution found in commits."
|
|
|
|
action-pins:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
- name: Check for floating action refs
|
|
run: |
|
|
if grep -rE 'uses:.*@(v[0-9]+|stable|main|master)(\s|$)' .gitea/workflows/; then
|
|
echo "::error::Floating action refs found — pin every action to a commit SHA"
|
|
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.
|
|
aarch64-artifact:
|
|
runs-on: archdev
|
|
needs: [rust-test, no-ai-attribution, action-pins]
|
|
if: github.event_name == 'push' && github.ref == 'refs/heads/public'
|
|
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
|
|
|
|
# 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
|
|
for b in souveraine-secrets souveraine-machined; 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
|
|
for b in souveraine-secrets souveraine-machined; 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 is deliberately NOT built for x86_64: the laptop hit
|
|
# lock-screen errors with it, and it is the phone's session authority.
|
|
# Ship it on aarch64 only until the laptop side is sorted.
|
|
|
|
sha256sum souveraine-aarch64 souveraine-x86_64 \
|
|
souveraine-sessiond-aarch64 souveraine-sensord-aarch64 \
|
|
souveraine-secrets-aarch64 souveraine-secrets-x86_64 \
|
|
souveraine-machined-aarch64 souveraine-machined-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: 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 packaging/souveraine.service packaging/souveraine-secrets.service \
|
|
packaging/org.freedesktop.secrets.service \
|
|
packaging/souveraine-machined.service LICENSE "$PKG_WORK/"
|
|
# aarch64 only — see the sessiond note in the build step.
|
|
if [ "$ARCH" = aarch64 ]; then
|
|
cp "souveraine-sessiond-$ARCH" "$PKG_WORK/souveraine-sessiond-binary"
|
|
cp packaging/souveraine-sessiond.service "$PKG_WORK/"
|
|
cp "souveraine-sensord-$ARCH" "$PKG_WORK/souveraine-sensord-binary"
|
|
cp packaging/souveraine-sensord.service "$PKG_WORK/"
|
|
fi
|
|
cp packaging/souveraine-verify-trail "$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'
|
|
if [ "$ARCH" = aarch64 ]; then
|
|
bsdtar -tf "$PKG" | grep -qx 'usr/bin/souveraine-sessiond'
|
|
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")"
|
|
|
|
# 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"
|
|
|
|
# Mirror the published branch only. primary (dev) never reaches Codeberg.
|
|
sync-codeberg:
|
|
runs-on: ubuntu-latest
|
|
needs: [rust-test, no-ai-attribution, action-pins]
|
|
if: github.event_name == 'push' && github.ref == 'refs/heads/public'
|
|
steps:
|
|
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
with:
|
|
fetch-depth: 0
|
|
- name: Push public to Codeberg
|
|
run: |
|
|
if [ -z "${{ secrets.CODEBERG_TOKEN }}" ]; then
|
|
echo "[INFO] [sync] CODEBERG_TOKEN not set — skipping codeberg push"
|
|
exit 0
|
|
fi
|
|
git remote add codeberg-ci "https://${{ secrets.CODEBERG_TOKEN }}@codeberg.org/Fimeg/Souveraine.git"
|
|
git push codeberg-ci public:public
|
|
echo "Pushed public to codeberg.org/Fimeg/Souveraine"
|