burrow/Scripts/package/build-repositories.sh
Conrad Kramer 002bd382e9
Some checks failed
Cache: Publish Nix / Publish Nix Cache (push) Waiting to run
Build Rust / Cargo Test (push) Successful in 4m14s
Build Site / Next.js Build (push) Failing after 6s
Infra: OpenTofu / OpenTofu (grafana) (push) Successful in 5s
Lint Governance / BEP Metadata (push) Successful in 0s
Build: Android / Android Rust Core Stub (push) Failing after 23s
Wire Forge-native release infrastructure
2026-06-07 05:51:12 -07:00

248 lines
8.8 KiB
Bash
Executable file

#!/usr/bin/env bash
set -euo pipefail
repo_root="$(
git rev-parse --show-toplevel 2>/dev/null || {
cd "$(dirname "${BASH_SOURCE[0]}")/../.."
pwd
}
)"
input_dir="${BURROW_PACKAGE_INPUT_DIR:-${repo_root}/dist/packages}"
output_dir="${BURROW_PACKAGE_REPOSITORY_DIR:-${repo_root}/publish/repositories}"
channel="${BURROW_PACKAGE_CHANNEL:-stable}"
suite="${BURROW_APT_SUITE:-stable}"
component="${BURROW_APT_COMPONENT:-main}"
apt_arch="${BURROW_APT_ARCH:-${BURROW_PACKAGE_ARCH:-amd64}}"
rpm_arch="${BURROW_RPM_ARCH:-x86_64}"
pacman_arch="${BURROW_PACMAN_ARCH:-x86_64}"
repo_name="${BURROW_ARCH_REPO_NAME:-burrow}"
generic_kms_public_key_pem="${BURROW_PACKAGE_REPO_KMS_PUBLIC_KEY_PEM:-}"
generic_kms_key="${BURROW_PACKAGE_REPO_KMS_KEY:-}"
apt_kms_public_key_pem="${BURROW_APT_REPO_KMS_PUBLIC_KEY_PEM:-$generic_kms_public_key_pem}"
apt_kms_key="${BURROW_APT_REPO_KMS_KEY:-${generic_kms_key:-package-apt-repository}}"
rpm_kms_public_key_pem="${BURROW_RPM_REPO_KMS_PUBLIC_KEY_PEM:-$generic_kms_public_key_pem}"
rpm_kms_key="${BURROW_RPM_REPO_KMS_KEY:-${generic_kms_key:-package-rpm-repository}}"
pacman_kms_public_key_pem="${BURROW_PACMAN_REPO_KMS_PUBLIC_KEY_PEM:-$generic_kms_public_key_pem}"
pacman_kms_key="${BURROW_PACMAN_REPO_KMS_KEY:-${generic_kms_key:-package-pacman-repository}}"
usage() {
cat <<'EOF'
Usage: Scripts/package/build-repositories.sh [apt|rpm|arch|keys|all]
Builds native Linux package repositories from existing package artifacts.
Inputs:
BURROW_PACKAGE_INPUT_DIR directory containing .deb, .rpm, and .pkg.tar.* files
BURROW_PACKAGE_REPOSITORY_DIR output directory, default publish/repositories
BURROW_APT_REPO_KMS_PUBLIC_KEY_PEM Google KMS public key PEM for APT OpenPGP signatures
BURROW_APT_REPO_KMS_KEY Google KMS key name for APT signatures
BURROW_RPM_REPO_KMS_PUBLIC_KEY_PEM Google KMS public key PEM for RPM repository signatures
BURROW_RPM_REPO_KMS_KEY Google KMS key name for RPM repository signatures
BURROW_PACMAN_REPO_KMS_PUBLIC_KEY_PEM Google KMS public key PEM for pacman signatures
BURROW_PACMAN_REPO_KMS_KEY Google KMS key name for pacman signatures
BURROW_PACKAGE_REPO_KMS_PUBLIC_KEY_PEM fallback public key PEM for all formats
BURROW_PACKAGE_REPO_KMS_KEY fallback KMS key name for all formats
BURROW_KMS_KEYRING/BURROW_KMS_LOCATION/BURROW_KMS_VERSION/GOOGLE_CLOUD_PROJECT
The repository metadata is signed with Google KMS-backed OpenPGP detached
signatures when each format's KMS public key and key name are configured.
EOF
}
if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
usage
exit 0
fi
mode="${1:-all}"
sha256_file() {
local file="$1"
if command -v shasum >/dev/null 2>&1; then
shasum -a 256 "$file" > "${file}.sha256"
else
sha256sum "$file" > "${file}.sha256"
fi
}
sign_file() {
local file="$1"
local output="${2:-${file}.sig}"
local armor="${3:-0}"
local kms_key="$4"
local kms_public_key_pem="$5"
if [[ -z "$kms_public_key_pem" || -z "$kms_key" ]]; then
echo "warning: KMS OpenPGP signing disabled for ${file}; set the ${file} repository KMS public key and key name" >&2
return 0
fi
args=(
"${repo_root}/Scripts/package/google-kms-openpgp.py"
detach-sign
--public-key-pem "$kms_public_key_pem"
--kms-key "$kms_key"
--input "$file"
--output "$output"
)
if [[ "$armor" == "1" ]]; then
args+=(--armor)
fi
"${args[@]}"
}
write_public_key() {
local name="$1"
local kms_key="$2"
local kms_public_key_pem="$3"
local user_id="$4"
local output="${output_dir}/keys/${name}.asc"
if [[ -z "$kms_public_key_pem" || -z "$kms_key" ]]; then
echo "warning: KMS OpenPGP public key export disabled for ${name}; set the repository KMS public key and key name" >&2
return 0
fi
mkdir -p "$(dirname "$output")"
"${repo_root}/Scripts/package/google-kms-openpgp.py" \
public-key \
--public-key-pem "$kms_public_key_pem" \
--kms-key "$kms_key" \
--user-id "$user_id" \
--output "$output" \
--armor
}
write_release_file() {
local release_path="$1"
local dist_dir="$2"
local now
now="$(LC_ALL=C date -u '+%a, %d %b %Y %H:%M:%S +0000')"
{
printf 'Origin: Burrow\n'
printf 'Label: Burrow\n'
printf 'Suite: %s\n' "$suite"
printf 'Codename: %s\n' "$suite"
printf 'Date: %s\n' "$now"
printf 'Architectures: %s\n' "$apt_arch"
printf 'Components: %s\n' "$component"
printf 'Description: Burrow native package repository\n'
printf 'SHA256:\n'
(
cd "$dist_dir"
find . -type f ! -name Release -print | LC_ALL=C sort | while read -r file; do
clean="${file#./}"
sum="$(sha256sum "$clean" | awk '{print $1}')"
size="$(wc -c < "$clean" | tr -d ' ')"
printf ' %s %s %s\n' "$sum" "$size" "$clean"
done
)
} > "$release_path"
}
build_apt() {
local root binary_dir pool_dir release_dir release_file
root="${output_dir}/apt"
pool_dir="${root}/pool/${component}/b/burrow"
binary_dir="${root}/dists/${suite}/${component}/binary-${apt_arch}"
release_dir="${root}/dists/${suite}"
mkdir -p "$pool_dir" "$binary_dir" "$release_dir"
find "$input_dir" -type f -name '*.deb' -exec cp {} "$pool_dir/" \; 2>/dev/null || true
if ! find "$pool_dir" -type f -name '*.deb' -print -quit | grep -q .; then
echo "warning: no .deb packages found under ${input_dir}; apt repository contains README only" >&2
printf 'Place Burrow .deb artifacts in this repository pool before publishing.\n' > "${root}/README.txt"
return 0
fi
if ! command -v dpkg-scanpackages >/dev/null 2>&1; then
echo "error: dpkg-scanpackages is required to build the apt repository" >&2
exit 127
fi
(
cd "$root"
dpkg-scanpackages --arch "$apt_arch" "pool/${component}" /dev/null > "dists/${suite}/${component}/binary-${apt_arch}/Packages"
gzip -9cn "dists/${suite}/${component}/binary-${apt_arch}/Packages" > "dists/${suite}/${component}/binary-${apt_arch}/Packages.gz"
)
release_file="${release_dir}/Release"
write_release_file "$release_file" "$release_dir"
sign_file "$release_file" "${release_file}.gpg" 1 "$apt_kms_key" "$apt_kms_public_key_pem"
sha256_file "$release_file"
}
build_rpm() {
local root repomd
root="${output_dir}/rpm/${channel}/${rpm_arch}"
mkdir -p "$root"
find "$input_dir" -type f -name '*.rpm' -exec cp {} "$root/" \; 2>/dev/null || true
if ! find "$root" -maxdepth 1 -type f -name '*.rpm' -print -quit | grep -q .; then
echo "warning: no .rpm packages found under ${input_dir}; rpm repository contains README only" >&2
printf 'Place Burrow .rpm artifacts in this directory before publishing.\n' > "${root}/README.txt"
return 0
fi
if ! command -v createrepo_c >/dev/null 2>&1; then
echo "error: createrepo_c is required to build the rpm repository" >&2
exit 127
fi
createrepo_c "$root"
repomd="${root}/repodata/repomd.xml"
sign_file "$repomd" "${repomd}.asc" 1 "$rpm_kms_key" "$rpm_kms_public_key_pem"
sha256_file "$repomd"
}
build_arch() {
local root db
root="${output_dir}/arch/${repo_name}/${pacman_arch}"
mkdir -p "$root"
find "$input_dir" -type f \( -name '*.pkg.tar.zst' -o -name '*.pkg.tar.xz' -o -name '*.pkg.tar.gz' \) -exec cp {} "$root/" \; 2>/dev/null || true
if ! find "$root" -maxdepth 1 -type f -name '*.pkg.tar.*' -print -quit | grep -q .; then
echo "warning: no Arch packages found under ${input_dir}; pacman repository contains README only" >&2
printf 'Place Burrow .pkg.tar.* artifacts in this directory before publishing.\n' > "${root}/README.txt"
return 0
fi
if ! command -v repo-add >/dev/null 2>&1; then
echo "error: repo-add is required to build the Arch repository" >&2
exit 127
fi
(
cd "$root"
repo-add "${repo_name}.db.tar.gz" ./*.pkg.tar.*
)
db="${root}/${repo_name}.db.tar.gz"
sign_file "$db" "${db}.sig" 0 "$pacman_kms_key" "$pacman_kms_public_key_pem"
find "$root" -maxdepth 1 -type f -name '*.pkg.tar.*' ! -name '*.sig' -print | while read -r package; do
sign_file "$package" "${package}.sig" 0 "$pacman_kms_key" "$pacman_kms_public_key_pem"
done
sha256_file "$db"
}
build_keys() {
write_public_key "burrow-package-apt-repository" "$apt_kms_key" "$apt_kms_public_key_pem" "Burrow APT Package Repository <packages@burrow.net>"
write_public_key "burrow-package-rpm-repository" "$rpm_kms_key" "$rpm_kms_public_key_pem" "Burrow RPM Package Repository <packages@burrow.net>"
write_public_key "burrow-package-pacman-repository" "$pacman_kms_key" "$pacman_kms_public_key_pem" "Burrow pacman Package Repository <packages@burrow.net>"
}
mkdir -p "$output_dir"
case "$mode" in
apt)
build_apt
;;
rpm)
build_rpm
;;
arch)
build_arch
;;
keys)
build_keys
;;
all)
build_keys
build_apt
build_rpm
build_arch
;;
*)
echo "unknown repository mode: ${mode}" >&2
exit 64
;;
esac