mirror of
https://github.com/lynchaos/ashvale-station.git
synced 2026-09-12 12:47:49 +00:00
Prebuilt Pi image and a one-line installer
Two routes onto a Pi. The image for a blank card, the script for a board that already works, which is most of them. deploy/install.sh installs apt dependencies, clones to /opt/ashvale, builds a venv with --system-site-packages, enables I2C and installs a systemd unit. Tested end to end on the real Zero 2 W by installing a second instance on port 8099 alongside the live station: both served, and the live station was untouched throughout. That test earned its keep twice. The installer first declared success while the service was crash-looping on a port clash, because systemd reports active for the instant between exec and the first failed bind; it now polls the HTTP endpoint instead, which is the only check that means anything. And my first attempt to verify that fix was itself worthless, because curl on 127.0.0.1:8000 was answered by the live station rather than the instance under test. deploy/pi-image is a pi-gen stage on Raspberry Pi OS Lite, Trixie, arm64, which is exactly what the board runs. Built by .github/workflows/image.yml against a pinned pi-gen commit, so the artifact does not move when an upstream branch does, and published to Releases where the 2 GB asset limit comfortably fits a Lite image. The image ships no password, no WiFi and no SSH host keys. Baked host keys would give every person who flashed it the same identity and make them trivially impersonable on their own network. Coordinates default to Greenwich at 0 m, wrong for everybody on purpose, because a plausible wrong altitude quietly biases the sea-level reduction on every row. The source is copied through a .gitignore filter rather than a hand-written exclude list, and that is a security property rather than tidiness: the hand-written list I wrote first missed HANDOVER.md, which is gitignored precisely because it contains LAN addresses and SSH details. Verified: 69 files, no state, no local notes, all essentials present.
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
name: Pi image
|
||||
|
||||
# Builds a ready-to-flash Raspberry Pi OS Lite image with Ashvale Station
|
||||
# preinstalled, and attaches it to a GitHub Release.
|
||||
#
|
||||
# Built in CI rather than on a laptop on purpose. The artifact is something
|
||||
# other people flash onto their own hardware, so it should be reproducible from
|
||||
# a public log by anyone who wants to check what went into it, rather than
|
||||
# appearing from a machine only I can see.
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
publish:
|
||||
description: "Attach the image to a release"
|
||||
type: boolean
|
||||
default: false
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 180
|
||||
|
||||
steps:
|
||||
- name: Check out Ashvale
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
path: ashvale
|
||||
|
||||
# pi-gen needs about 10 GB and a stock runner does not have it spare.
|
||||
- name: Reclaim disk space
|
||||
run: |
|
||||
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc \
|
||||
/usr/local/share/boost "$AGENT_TOOLSDIRECTORY"
|
||||
df -h / | tail -1
|
||||
|
||||
- name: Install build dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y --no-install-recommends \
|
||||
coreutils quilt parted qemu-user-static debootstrap zerofree zip \
|
||||
dosfstools libarchive-tools libcap2-bin grep rsync xz-utils file \
|
||||
git curl bc gpg pigz kpartx arch-test
|
||||
|
||||
# Pinned to a commit, not a branch. An image other people flash should not
|
||||
# change because an upstream branch moved between builds.
|
||||
- name: Check out pi-gen
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: RPi-Distro/pi-gen
|
||||
ref: ca8aeed0ae300c2a89f55ce9617d5f96a27e99e5 # arm64 branch, pinned
|
||||
path: pi-gen
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Assemble the custom stage
|
||||
run: |
|
||||
cp ashvale/deploy/pi-image/config pi-gen/config
|
||||
cp -r ashvale/deploy/pi-image/stage-ashvale pi-gen/stage-ashvale
|
||||
# Lite only: everything from stage3 up is the desktop.
|
||||
touch pi-gen/stage3/SKIP pi-gen/stage4/SKIP pi-gen/stage5/SKIP
|
||||
touch pi-gen/stage4/SKIP_IMAGES pi-gen/stage5/SKIP_IMAGES
|
||||
# stage2 stops exporting so ours is the only image produced.
|
||||
rm -f pi-gen/stage2/EXPORT_IMAGE
|
||||
echo "ASHVALE_SRC=${GITHUB_WORKSPACE}/ashvale" >> pi-gen/config
|
||||
echo "--- config ---" && cat pi-gen/config
|
||||
|
||||
- name: Build
|
||||
working-directory: pi-gen
|
||||
run: sudo -E ./build.sh
|
||||
|
||||
- name: Collect artifact
|
||||
id: artifact
|
||||
run: |
|
||||
IMG=$(find pi-gen/deploy -name '*.img.xz' | head -1)
|
||||
test -n "$IMG" || { echo "no image produced"; ls -R pi-gen/deploy; exit 1; }
|
||||
mkdir -p out && mv "$IMG" out/
|
||||
cd out
|
||||
NAME=$(basename *.img.xz)
|
||||
sha256sum "$NAME" > "$NAME.sha256"
|
||||
echo "name=$NAME" >> "$GITHUB_OUTPUT"
|
||||
ls -lh
|
||||
# A release asset is capped at 2 GB; Lite compresses to well under that,
|
||||
# but fail loudly here rather than at upload time.
|
||||
SIZE=$(stat -c%s "$NAME")
|
||||
echo "compressed size: $((SIZE/1024/1024)) MiB"
|
||||
test "$SIZE" -lt 2000000000 || { echo "image exceeds the 2 GB release limit"; exit 1; }
|
||||
|
||||
- name: Upload as a workflow artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ashvale-pi-image
|
||||
path: out/*
|
||||
retention-days: 14
|
||||
|
||||
- name: Attach to release
|
||||
if: startsWith(github.ref, 'refs/tags/') || inputs.publish
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
TAG="${GITHUB_REF_NAME}"
|
||||
gh release view "$TAG" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1 \
|
||||
|| gh release create "$TAG" --repo "$GITHUB_REPOSITORY" \
|
||||
--title "$TAG" --notes "Ashvale Station image for Raspberry Pi."
|
||||
gh release upload "$TAG" out/* --repo "$GITHUB_REPOSITORY" --clobber
|
||||
Reference in New Issue
Block a user