release #
Version tags (v*) build albedo for Linux x86_64 as one AppImage and as deb,
rpm and Arch packages, smoke-test each on a clean distro, and upload them with
SHA256SUMS to https://albedo-artifacts.fsn1.your-objectstorage.com/releases/<tag>/
(.tangled/workflows/release.yml). A manual run builds and tests the current
commit and uploads nothing.
what is built #
release/build.sh [version] runs release/inside.sh in an Ubuntu 22.04
container (podman or docker) and writes build/release/<version>/. The
version is semver without the v; the default is git describe. Downloads and
the compiled OTP are cached in ~/.cache/albedo-release (ALBEDO_RELEASE_CACHE).
Everything is bundled except glibc (2.35 or newer: Ubuntu 22.04, Debian 12, current Fedora and Arch; not RHEL 9 or Debian 11). One tree serves every format:
bin/albedo the CLI (static, CGO_ENABLED=0)
bin/rg ripgrep (musl, static)
bin/albedo-daemon release/albedo-daemon: bundled tools first on PATH, then the shipment
lib/albedo/ the sealed daemon shipment (gleam export erlang-shipment)
erlang/ OTP 29, built from source: only the apps the daemon calls,
no wx, termcap or other GUI apps, OpenSSL linked into crypto,
libstdc++/libgcc linked into the emulator
python/ python-build-standalone 3.11, without tests, Tk, IDLE, crypt
web/ the web client (ALBEDO_WEB_DIST)
inside.sh refuses to package a tree in which any ELF needs a host library
other than glibc (or one the tree ships); NixOS hosts have none of the usual
ones, so a missing library shows there first. The shipment is sealed
(albedo_daemon:seal_build/1, see runtime.md) after Python is compiled, since
sealing hashes the finished tree.
- packages install the tree to
/usr/lib/albedoandrelease/packages/albedoto/usr/bin/albedo, which setsALBEDO_DAEMONandALBEDO_WEB_DIST.bin/albedo-daemonbesidelib/albedo/albedois the layout the CLI finds a build seal in, so packaged installs use standbys. nfpm builds all three fromrelease/packages/nfpm.yaml; the maintainer field defaults tonekomimi.pet <meowskulls@nekomimi.pet>;PACKAGE_MAINTAINERoverrides it. - AppImage is the tree plus
release/appimage/AppRun, assembled by hand (mksquashfs, then the pinned type2 runtime prepended), never by running appimagetool: a host that registers AppImages with binfmt_misc (NixOS) routes every AppImage, inside containers too, to its own launcher. AppRun runs the CLI withALBEDO_DAEMON=$APPIMAGEandALBEDO_APPIMAGE_DAEMON=1, so the CLI starts the daemon by running the image again: the daemon holds its own mount and keeps its files after the CLI exits.ALBEDO_BUILDnames the version, because the image path stays the same across upgrades; replace an image by rename, never in place, since a running daemon reads the old file. The AppImage has no seal path the CLI finds, so it boots cold. Its runtime cannot start under an open-file limit below about 1024.
testing #
release/smoke.sh <artifact> <image> installs the artifact on a clean
container the way a user would, then checks that the CLI runs, that
albedo daemon starts a daemon that outlives it and answers albedo sessions,
and that albedo daemon --stop ends it. The e2e suite runs against an AppImage
daemon through a wrapper given as ALBEDO_TEST_DAEMON
(ALBEDO_APPIMAGE_DAEMON=1 exec <image> "$@"); tests that require the compiled
test snapshot's layout fail there by design.
storage #
The bucket lives in a Hetzner project; keys of a project reach every bucket in
it. The CI key lives in a separate project with no buckets, so it has no access
until the bucket policy grants it: s3:PutObject under releases/ only. The
same policy makes releases/ publicly readable and listable (s3:ListBucket
with an s3:prefix condition, which Hetzner enforces):
?list-type=2&prefix=releases/&delimiter=/ names one prefix per release. The key reaches CI as the
spindle secrets S3_ACCESS_KEY_ID and S3_SECRET_ACCESS_KEY;
release/upload.sh signs with curl --aws-sigv4 (awscli misreads Hetzner's
error bodies) and passes the key on stdin.