fp6-img/.forgejo/workflows/build.yml
Jorijn van der Graaf a2726477ab
All checks were successful
image / image (push) Successful in 59m22s
build.yml: annotate the rolling 'latest' tag, so its release stays on top
Forgejo orders the releases page by each release's creation time and
resets that time from the tag at every tag push: a lightweight tag gives
the tagged commit's time, an annotated tag the tagger's. A push's dated
release is tagged at push time, after its commits, so the lightweight
'latest' tag always sorted below it (2026-11-01: 'latest' created
01:09:36Z = the tip's commit time, the dated release 02:02:09Z = its
tag's time). An annotated tag made when the run ends is newer than any
dated release tagged before the images were built.
2026-11-01 17:39:18 +01:00

135 lines
5.9 KiB
YAML

name: image
# Builds the flashable Nura images for the Fairphone 6 (kernel from
# milos-linux combined-stable + imsd) — Plasma Mobile (fp6-img-plasma.tar.xz) and
# Phosh (fp6-img-phosh.tar.xz) — and publishes both as the rolling 'latest'
# release.
#
# Runs on the dedicated privileged runner label "pmos" (loop devices for
# pmbootstrap install, qemu-user binfmt on the host for the aarch64 chroots).
# Until that runner is registered, dispatched runs will sit queued.
on:
workflow_dispatch:
# push trigger is temporary, for pipeline bring-up; narrow to
# workflow_dispatch + a nightly schedule once the pipeline is green:
push:
branches: [main]
# schedule:
# - cron: '30 3 * * *'
jobs:
image:
runs-on: pmos
timeout-minutes: 420
steps:
# actions/checkout & friends are Node actions; bare alpine has no node.
# bash, curl, jq: required by the forgejo-release composite action —
# its setup_api falls back to apt-get when jq/curl are missing, which
# exits 127 on alpine.
- name: Provision job container
run: apk add -q nodejs git bash curl jq
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: true
- name: Build image (Plasma Mobile)
run: ./build.sh
# Second UI from the same package builds (the kernel and the aports
# above are already current in pmbootstrap's work dir, so this is the
# install + export only): fp6-img-phosh.tar.xz next to fp6-img-plasma.tar.xz
# in the same release.
- name: Build image (Phosh)
run: FP6IMG_UI=phosh FP6IMG_KEEP_DIST=1 ./build.sh
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: fp6-image-${{ github.sha }}
path: dist/*
if-no-files-found: error
# Ship every locally built apk (kernel, modemmanager, callaudioshim,
# audio files, ...) to the Forgejo Alpine registry, so
# installed systems get updates via 'apk upgrade' instead of losing
# the FP6 patches to the next upstream version bump. Requires the
# PACKAGE_TOKEN repo secret (catbot account, package:write scope);
# skips quietly until it exists. 409 = same version already published.
# imsd and fingerprintd are skipped: build.sh 3b took them FROM the
# registry (re-signed for the chroot), so they are not ours to publish.
# libqmi is skipped too: its fork was retired and deleted from the
# registry (2026-10-12); should a leftover apk ever sit in the runner's
# package dir, it must not bring the fork back.
- name: Publish packages to the apk registry
env:
PACKAGE_TOKEN: ${{ secrets.PACKAGE_TOKEN }}
run: |
if [ -z "$PACKAGE_TOKEN" ]; then
echo "no PACKAGE_TOKEN secret configured; skipping package publish"
exit 0
fi
apk add -q curl
found=0
publish() {
case "$(basename "$1")" in
imsd-*|fingerprintd-*) echo "registry-sourced, not republished: $(basename "$1")"; return 0 ;;
libqmi-*|qmi-utils-*) echo "retired fork, not republished: $(basename "$1")"; return 0 ;;
esac
found=1
code=$(curl -s -o /dev/null -w '%{http_code}' \
--user "catbot:$PACKAGE_TOKEN" --upload-file "$1" \
"https://forgejo.catcrafts.net/api/packages/Catcrafts/alpine/edge/fp6")
case "$code" in
201) echo "published: $(basename "$1")" ;;
409) echo "already published: $(basename "$1")" ;;
*) echo "FAILED ($code): $(basename "$1")"; exit 1 ;;
esac
}
# The kernel goes last: a publish that fails part-way (the first
# failed upload ends this step) must never leave the registry serving
# a kernel without the userspace its card name needs - the 7.3 kernel
# has its topology and UCM only in soc-fairphone-fp6-audio >= 5.
for f in /home/build/.local/var/pmbootstrap/packages/*/aarch64/*.apk; do
[ -e "$f" ] || continue
case "$(basename "$f")" in linux-postmarketos-qcom-milos-*) continue ;; esac
publish "$f"
done
for f in /home/build/.local/var/pmbootstrap/packages/*/aarch64/linux-postmarketos-qcom-milos-*.apk; do
[ -e "$f" ] || continue
publish "$f"
done
[ "$found" = 1 ] || { echo "no packages found to publish"; exit 1; }
- name: Update rolling 'latest' tag
run: |
git config --global --add safe.directory "$PWD"
git config user.email "ci@catcrafts.net"
git config user.name "fp6-img CI"
# Annotated, so the release keeps the top of the releases page:
# Forgejo stamps a release with its tag's time at every tag push -
# a lightweight tag's is the commit's, older than the dated release
# tagged at push time; an annotated tag's is now.
git tag -a -f latest -m "Latest FP6 Nura image, built $(date -u +%Y-%m-%d) from $(git rev-parse --short HEAD)"
git push origin latest --force
- name: Publish rolling 'latest' release
uses: https://code.forgejo.org/actions/forgejo-release@v2
with:
direction: upload
url: ${{ github.server_url }}
repo: ${{ github.repository }}
tag: latest
title: Latest FP6 Nura image
prerelease: true
override: true
release-dir: dist
token: ${{ secrets.GITHUB_TOKEN }}
# Empty, NOT 'false': the action guards its release-notes-assistant
# cache step with `if: ${{ inputs.release-notes-assistant }}`, where
# the default string 'false' is truthy. That step then can't reach the
# runner's cache server (it advertises the host's public IP) and burns
# ~4m40s per run on a connect timeout before reporting a miss.
release-notes-assistant: ''