commit ccd2525c35defdfa2cf9de1cc769665a4465da34
parent 940e2c245b4543acbc62b88ecbb796df085e9985
Author: Robin Bron <robin.bron@yourhosting.nl>
Date: Fri, 25 Sep 2026 00:23:29 +0200
Bootstrapping the repository
Diffstat:
3 files changed, 147 insertions(+), 6 deletions(-)
diff --git a/.conductor.yml b/.conductor.yml
@@ -31,6 +31,8 @@ defaults:
tasks:
check:
timeout: 30m
+ arch: [x86_64]
+ requires: [unos-sign-key]
script:
- ./mk/ci-setup.sh
# Before deps.sh check, not after: muon is a declared hostmakedepends of
@@ -40,8 +42,11 @@ tasks:
- ./mk/deps.sh check
- ./mk/gen-pipeline.sh --check
- ./tests/run.sh --unit
+ - ./mk/bootstrap-repo.sh
pkg-zlib:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -53,6 +58,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" zlib
pkg-openssl:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -65,6 +72,7 @@ tasks:
pkg-apk-tools:
needs:
+ - check
- pkg-zlib
- pkg-openssl
arch: [x86_64]
@@ -78,6 +86,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" apk-tools
pkg-base-files:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -89,6 +99,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" base-files
pkg-busybox:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -101,6 +113,7 @@ tasks:
pkg-curl:
needs:
+ - check
- pkg-openssl
- pkg-zlib
arch: [x86_64]
@@ -114,6 +127,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" curl
pkg-dosfstools:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -125,6 +140,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" dosfstools
pkg-e2fsprogs:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -136,6 +153,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" e2fsprogs
pkg-efivar:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -147,6 +166,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" efivar
pkg-popt:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -159,6 +180,7 @@ tasks:
pkg-efibootmgr:
needs:
+ - check
- pkg-efivar
- pkg-popt
arch: [x86_64]
@@ -172,6 +194,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" efibootmgr
pkg-glibc:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -183,6 +207,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" glibc
pkg-libstdcxx:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -195,6 +221,7 @@ tasks:
pkg-gptfdisk:
needs:
+ - check
- pkg-e2fsprogs
- pkg-popt
- pkg-libstdcxx
@@ -209,6 +236,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" gptfdisk
pkg-xz:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -221,6 +250,7 @@ tasks:
pkg-grub:
needs:
+ - check
- pkg-xz
arch: [x86_64]
requires: [unos-sign-key]
@@ -233,6 +263,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" grub
pkg-libmnl:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -244,6 +276,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" libmnl
pkg-libcap:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -256,6 +290,7 @@ tasks:
pkg-iproute2:
needs:
+ - check
- pkg-libmnl
- pkg-libcap
arch: [x86_64]
@@ -269,6 +304,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" iproute2
pkg-linkd:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -280,6 +317,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" linkd
pkg-linux-longterm:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -291,6 +330,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" linux-longterm
pkg-linux-mainline:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -302,6 +343,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" linux-mainline
pkg-linux-stable:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -314,6 +357,7 @@ tasks:
pkg-smartmontools:
needs:
+ - check
- pkg-libstdcxx
arch: [x86_64]
requires: [unos-sign-key]
@@ -326,6 +370,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" smartmontools
pkg-tinyssh:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -337,6 +383,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" tinyssh
pkg-unos-firstboot:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
@@ -348,6 +396,8 @@ tasks:
- ./mk/publish.sh --arch "$ARCH" unos-firstboot
pkg-unos-keys:
+ needs:
+ - check
arch: [x86_64]
requires: [unos-sign-key]
script:
diff --git a/mk/bootstrap-repo.sh b/mk/bootstrap-repo.sh
@@ -0,0 +1,89 @@
+#!/bin/sh
+# mk/bootstrap-repo.sh - ensure an APKINDEX exists in the S3 repo.
+#
+# If the bucket already has x86_64/APKINDEX.tar.gz, do nothing.
+# Otherwise publish an empty signed index so `apk add` against the
+# repo stops 404ing before the first real package has been published.
+set -eu
+
+HERE=$(cd "$(dirname "$0")" && pwd)
+ROOT=$(cd "${HERE}/.." && pwd)
+
+ARCH="${ARCH:-x86_64}"
+case "${ARCH}" in arm64) ARCH=aarch64 ;; esac
+
+for v in BUCKET_ACCESS_KEY BUCKET_SECRET_KEY BUCKET_NAME BUCKET_ENDPOINT BUCKET_REGION; do
+ eval "val=\${${v}:-}"
+ [ -n "${val}" ] || { echo "bootstrap-repo.sh: ${v} is not set" >&2; exit 1; }
+done
+
+url="${BUCKET_ENDPOINT%/}/${BUCKET_NAME}/${ARCH}/APKINDEX.tar.gz"
+code=$(curl -sS -o /dev/null -w '%{http_code}' \
+ --aws-sigv4 "aws:amz:${BUCKET_REGION}:s3" \
+ --user "${BUCKET_ACCESS_KEY}:${BUCKET_SECRET_KEY}" \
+ "${url}") || code=000
+
+case "${code}" in
+ 2*) echo "==> repo already has ${ARCH}/APKINDEX.tar.gz (${code}), nothing to do"; exit 0 ;;
+ 404|000) echo "==> no ${ARCH}/APKINDEX.tar.gz (${code}), bootstrapping empty index" ;;
+ *) echo "bootstrap-repo.sh: unexpected HTTP ${code} for ${url}" >&2; exit 1 ;;
+esac
+
+mkdir -p "${ROOT}/build/repo/${ARCH}"
+
+export PATH="${ROOT}/build/host/bin:${PATH}"
+command -v apk >/dev/null 2>&1 || { echo "bootstrap-repo.sh: no apk on PATH; run mk/bootstrap-host.sh first" >&2; exit 1; }
+
+. "${HERE}/sign-key.inc"
+KEY=$(resolve_sign_key) || { echo "bootstrap-repo.sh: no signing key" >&2; exit 1; }
+KEYNAME=$(basename "${KEY}" .rsa)
+
+if [ ! -x "${HERE}/pax-tar" ] || [ "${HERE}/pax-tar.c" -nt "${HERE}/pax-tar" ]; then
+ cc -std=c99 -O2 -Wall -Wextra -o "${HERE}/pax-tar" "${HERE}/pax-tar.c"
+fi
+
+cd "${ROOT}/build/repo/${ARCH}"
+
+# apk index with no inputs still needs to produce a valid archive;
+# `echo` avoids the shell expanding *.apk to a literal when empty.
+echo -n "" | tar -czf APKINDEX.tar.gz -T /dev/null 2>/dev/null || true
+# Try the real tool first; fall back to the empty tar if it produced nothing.
+if [ ! -s APKINDEX.tar.gz ] || ! tar -tzf APKINDEX.tar.gz >/dev/null 2>&1; then
+ : > APKINDEX
+ tar -czf APKINDEX.tar.gz APKINDEX
+ rm -f APKINDEX
+fi
+
+# Rebuild properly if apk can do it (covers the signed-index header fixup below)
+# and ensures the index is well-formed even when empty.
+if ls ./*.apk >/dev/null 2>&1; then
+ apk index --allow-untrusted -o APKINDEX.tar.gz ./*.apk
+else
+ # empty repo: create minimal index that `apk add` accepts
+ rm -f APKINDEX.tar.gz
+ mkdir -p .idx-empty
+ : > .idx-empty/APKINDEX
+ tar -czf APKINDEX.tar.gz -C .idx-empty APKINDEX
+ rm -rf .idx-empty
+fi
+
+echo "==> signing APKINDEX.tar.gz with ${KEYNAME}"
+openssl dgst -sha1 -sign "${KEY}" -out ".SIGN.RSA.${KEYNAME}.rsa.pub" APKINDEX.tar.gz
+mkdir -p "${ROOT}/build/work/.idxsig"
+cp ".SIGN.RSA.${KEYNAME}.rsa.pub" "${ROOT}/build/work/.idxsig/"
+"${HERE}/pax-tar" --no-checksum "${ROOT}/build/work/.idxsig" idxsig.tar
+sigsiz=$(stat -c%s idxsig.tar)
+head -c $((sigsiz - 1024)) idxsig.tar > idxsignotr.tar
+gzip -n -9 -f idxsignotr.tar
+cat idxsignotr.tar.gz APKINDEX.tar.gz > APKINDEX.signed.tar.gz
+mv APKINDEX.signed.tar.gz APKINDEX.tar.gz
+rm -f ".SIGN.RSA.${KEYNAME}.rsa.pub" idxsig.tar idxsignotr.tar.gz
+rm -rf "${ROOT}/build/work/.idxsig"
+
+echo "==> publishing ${ARCH}/APKINDEX.tar.gz"
+code=$(curl -sS -o /dev/null -w '%{http_code}' \
+ --aws-sigv4 "aws:amz:${BUCKET_REGION}:s3" \
+ --user "${BUCKET_ACCESS_KEY}:${BUCKET_SECRET_KEY}" \
+ -X PUT --upload-file APKINDEX.tar.gz \
+ "${url}") || { echo "bootstrap-repo.sh: upload failed" >&2; exit 1; }
+case "${code}" in 2*) echo "==> bootstrapped ${ARCH}/APKINDEX.tar.gz (${code})" ;; *) echo "bootstrap-repo.sh: upload returned HTTP ${code}" >&2; exit 1 ;; esac
diff --git a/mk/gen-pipeline.sh b/mk/gen-pipeline.sh
@@ -73,6 +73,8 @@ defaults:
tasks:
check:
timeout: 30m
+ arch: [x86_64]
+ requires: [unos-sign-key]
script:
- ./mk/ci-setup.sh
# Before deps.sh check, not after: muon is a declared hostmakedepends of
@@ -82,6 +84,7 @@ tasks:
- ./mk/deps.sh check
- ./mk/gen-pipeline.sh --check
- ./tests/run.sh --unit
+ - ./mk/bootstrap-repo.sh
HEADER
@@ -89,12 +92,11 @@ HEADER
for p in $(cd "${ROOT}" && ./mk/deps.sh order); do
deps=$(cd "${ROOT}" && ./mk/deps.sh vars "$p" | sed -n 's/^makedepends: *//p')
printf ' %s:\n' "$(task_name "$p")"
- if [ -n "${deps}" ]; then
- printf ' needs:\n'
- for d in ${deps}; do
- printf ' - %s\n' "$(task_name "$d")"
- done
- fi
+ printf ' needs:\n'
+ printf ' - check\n'
+ for d in ${deps}; do
+ printf ' - %s\n' "$(task_name "$d")"
+ done
# arch is declared so $ARCH exists in the script; it is only injected for
# tasks that declare it. One arch today, but adding aarch64 is then a
# single edit here rather than a rewrite.