Files
2026-10-30 13:11:36 +01:00

105 lines
3.7 KiB
Bash
Executable File

#!/usr/bin/env bash
set -Eeuo pipefail
ROOT=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
cd "$ROOT"
ENV_FILE="$ROOT/.env"
DATA_DIR="$ROOT/data"
GPG_DIR="$ROOT/gpg"
DEFAULT_HTTP_PORT=18965
log() { printf '[rustbox-package-builder] %s\n' "$*"; }
die() { printf '[rustbox-package-builder] ERROR: %s\n' "$*" >&2; exit 1; }
require_cmd() { command -v "$1" >/dev/null 2>&1 || die "missing command: $1"; }
require_cmd docker
if ! docker info >/dev/null 2>&1; then
die "Docker daemon is unavailable for the current user"
fi
if docker compose version >/dev/null 2>&1; then
COMPOSE=(docker compose)
elif command -v docker-compose >/dev/null 2>&1; then
COMPOSE=(docker-compose)
else
die "Docker Compose is required"
fi
if [[ ! -f "$ENV_FILE" ]]; then
cp "$ROOT/.env.example" "$ENV_FILE"
chmod 0600 "$ENV_FILE"
die "created .env; set SOURCE_REPO and REPOSITORY_URL, then run ./start.sh again"
fi
set -a
source "$ENV_FILE"
set +a
: "${SOURCE_REPO:?SOURCE_REPO is required in .env}"
: "${REPOSITORY_URL:?REPOSITORY_URL is required in .env}"
HTTP_PORT=${HTTP_PORT:-$DEFAULT_HTTP_PORT}
[[ "$HTTP_PORT" =~ ^[0-9]+$ ]] || die "HTTP_PORT must be numeric"
(( HTTP_PORT >= 1024 && HTTP_PORT <= 65535 )) || die "HTTP_PORT must be between 1024 and 65535"
REPOSITORY_URL=${REPOSITORY_URL%/}
case "$REPOSITORY_URL" in
http://*|https://*) ;;
*) die "REPOSITORY_URL must start with http:// or https://" ;;
esac
if [[ "$REPOSITORY_URL" == http://* && ! "$REPOSITORY_URL" =~ :[0-9]+$ ]]; then
REPOSITORY_URL="${REPOSITORY_URL}:${HTTP_PORT}"
if grep -q '^REPOSITORY_URL=' "$ENV_FILE"; then
sed -i "s#^REPOSITORY_URL=.*#REPOSITORY_URL=${REPOSITORY_URL}#" "$ENV_FILE"
fi
export REPOSITORY_URL
log "REPOSITORY_URL updated to $REPOSITORY_URL"
fi
mkdir -p "$DATA_DIR"/{repository,state,cargo,work,packages} "$GPG_DIR"
chmod 0700 "$GPG_DIR" 2>/dev/null || true
log "building builder and repository dashboard"
"${COMPOSE[@]}" --env-file "$ENV_FILE" build rustbox-package-builder repository-dashboard
if [[ ! -s "$GPG_DIR/private-key.asc" ]]; then
log "generating persistent GPG signing key"
IMAGE_REF=$("${COMPOSE[@]}" --env-file "$ENV_FILE" config | awk '
$1 == "rustbox-package-builder:" { in_builder=1; next }
in_builder && $1 == "image:" { print $2; exit }
')
[[ -n "$IMAGE_REF" ]] || die "cannot resolve builder image name"
uid=$(id -u)
gid=$(id -g)
docker run --rm --user "$uid:$gid" --entrypoint /bin/bash -e HOME=/tmp \
-v "$GPG_DIR:/out" "$IMAGE_REF" -lc '
set -Eeuo pipefail
export GNUPGHOME=/tmp/rustbox-keygen
mkdir -p "$GNUPGHOME" && chmod 0700 "$GNUPGHOME"
cat > /tmp/gpg-batch <<"KEY"
Key-Type: RSA
Key-Length: 3072
Key-Usage: sign
Name-Real: RustBox Package Repository
Name-Email: packages@localhost
Expire-Date: 0
%no-protection
%commit
KEY
gpg --batch --generate-key /tmp/gpg-batch
fingerprint=$(gpg --batch --with-colons --list-secret-keys | awk -F: '\''/^sec:/ {seen=1; next} seen && /^fpr:/ {print $10; exit}'\'')
test -n "$fingerprint"
gpg --batch --armor --export-secret-keys "$fingerprint" > /out/private-key.asc
gpg --batch --armor --export "$fingerprint" > /out/public-key.asc
printf "%s\n" "$fingerprint" > /out/fingerprint
chmod 0600 /out/private-key.asc
chmod 0644 /out/public-key.asc /out/fingerprint
'
fi
log "starting builder and repository HTTP service"
"${COMPOSE[@]}" --env-file "$ENV_FILE" up -d rustbox-package-builder repository-http
printf '\nRepository: %s/\n' "$REPOSITORY_URL"
printf 'Local HTTP: http://127.0.0.1:%s/\n' "$HTTP_PORT"
printf 'Health: http://127.0.0.1:%s/healthz\n' "$HTTP_PORT"
printf 'Builder log: '
printf '%q ' "${COMPOSE[@]}"
printf 'logs -f rustbox-package-builder\n'