The three portable jobs stay; the archdev packaging and archive publish move to packages.yml, which the public branch does not carry. The handoff document is operator archaeology and does not travel.
138 lines
6.8 KiB
YAML
138 lines
6.8 KiB
YAML
name: ci
|
|
# CI for souveraine — Rust crate. Tests + clippy, then the aarch64 artifact,
|
|
# all on `primary`.
|
|
#
|
|
# There used to be a second branch, `public`, which was the only ref that
|
|
# published, so a green run on `primary` meant the gates passed and NOTHING
|
|
# SHIPPED — indistinguishable from a run that did. It existed to mirror to
|
|
# Codeberg; the mirror never worked and nothing else consumed it. Unified
|
|
# 2026-07-31 after it stranded three commits, including TASK-48's fix. One
|
|
# branch, one meaning: green on primary means it built and it shipped.
|
|
on:
|
|
push:
|
|
branches: [primary]
|
|
pull_request:
|
|
branches: [primary]
|
|
|
|
jobs:
|
|
rust-test:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
|
- name: Install system deps
|
|
# Retried because the runner's ephemeral job containers lose DNS for
|
|
# minutes at a time (four builds lost on 2026-08-13). A transient
|
|
# resolver blip must not decide whether our build passes, for the same
|
|
# reason the tuie pin exists below.
|
|
#
|
|
# The retry wraps *both* commands: `apt-get update` exits 0 when every
|
|
# index fails to download — it warns "old ones used instead" — so only
|
|
# the install reports the failure.
|
|
run: |
|
|
for attempt in 1 2 3; do
|
|
if sudo apt-get update -qq \
|
|
&& sudo apt-get install -y -qq libasound2-dev libchafa-dev libwayland-dev; then
|
|
exit 0
|
|
fi
|
|
echo "system deps attempt $attempt failed; retrying in $((attempt * 15))s"
|
|
sleep $((attempt * 15))
|
|
done
|
|
echo "system deps unavailable after 3 attempts — check runner DNS"
|
|
exit 1
|
|
# 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
|
|
# Pinned to a MASTER commit, deliberately, not to a `stable`-branch tip.
|
|
# The old pin (29eef336, "toolchain: stable") was the tip of that repo's
|
|
# `stable` branch when it was taken. dtolnay force-moves `stable` on every
|
|
# Rust release, which orphaned the commit: it still exists as an object on
|
|
# GitHub, but is reachable from no ref, so act's clone resolves it as
|
|
# "reference not found" and rust-test dies before it compiles anything.
|
|
# That failure skipped aarch64-artifact and silently stopped publishing to
|
|
# `edge` — the phone sat on an old build with nothing saying why.
|
|
# master is append-only, so a commit on it stays reachable. The toolchain
|
|
# is chosen by the `toolchain:` input below, never by the branch.
|
|
- uses: dtolnay/rust-toolchain@2c7215f132e9ebf062739d9130488b56d53c060c
|
|
with:
|
|
toolchain: "1.94"
|
|
components: clippy
|
|
- name: cargo test
|
|
run: cargo test
|
|
# `souveraine-sessiond` is `required-features = ["sessiond"]`, which is
|
|
# not in `default` — so the line above never compiled the device state
|
|
# authority, let alone ran its tests. Every sessiond change since the
|
|
# daemon existed has been type-checked only by the aarch64 cross-build,
|
|
# which builds and does not test. A green rust-test meant nothing for the
|
|
# one binary that decides whether the phone is locked. Same trap as the
|
|
# old primary/public split: a signal that reads like coverage and isn't.
|
|
- name: cargo test (sessiond)
|
|
run: cargo test --features sessiond --bin souveraine-sessiond
|
|
- name: cargo test (USB KVM receiver)
|
|
run: cargo test --features usb-kvm --bin souveraine-usb-kvm
|
|
- name: cargo clippy
|
|
run: cargo clippy -- -D warnings
|
|
# Advisory, deliberately. Turning this on for the first time surfaced 9
|
|
# pre-existing warnings in code clippy had never seen (dead
|
|
# `update_sensors`, unused re-exports in device_state, a nul-terminated
|
|
# string built by hand). None are from the change that added this step,
|
|
# and blocking the phone's only shipping path on them would be the wrong
|
|
# trade. Read it, burn the list down, then make it -D warnings and hard.
|
|
- name: cargo clippy (sessiond)
|
|
continue-on-error: true
|
|
run: cargo clippy --features sessiond --bin souveraine-sessiond -- -D warnings
|
|
- name: cargo clippy (USB KVM receiver)
|
|
run: cargo clippy --features usb-kvm --bin souveraine-usb-kvm -- -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.
|