Files
omarchy-pkgs/bin/release
T
Ryan Hughes 00dd64db61 Accept multiple package names in bin/release --package
The rc trigger passes '--package omarchy omarchy-settings', and bin/build
already consumes every name up to the next --option, but bin/release only
took one — the second name fell through to 'Unknown option' and the
release exited before building anything. Parse greedily, like bin/build.
2026-08-30 13:25:13 -04:00

228 lines
7.2 KiB
Bash
Executable File

#!/bin/bash
# Run the complete release workflow: build, sign, promote, clean, sync
set -e
BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
source "$BUILD_ROOT/helpers/message-helpers.sh"
source "$BUILD_ROOT/helpers/paths.sh"
source "$BUILD_ROOT/helpers/lock-helpers.sh"
source "$BUILD_ROOT/helpers/basecamp-notifier.sh"
SYNC_REMOTE=""
SKIP_PROD_CHECK=false
DRY_RUN=false
print_header "Complete Release Workflow"
echo ""
print_info "This will run the complete release workflow:"
echo " 1. Build packages"
echo " 2. Sign packages"
echo " 3. Promote to production"
echo " 4. Clean old versions"
echo " 5. Update repository database"
echo " 6. Sync to remote"
echo ""
# Parse arguments
BUILD_ARGS=()
while [[ $# -gt 0 ]]; do
case $1 in
--arch)
ARCH="$2"
BUILD_ARGS+=("--arch" "$2")
update_arch_paths
shift 2
;;
--mirror)
MIRROR="$2"
BUILD_ARGS+=("--mirror" "$2")
update_arch_paths
shift 2
;;
--package)
# Greedy like bin/build: consume every name up to the next --option.
BUILD_ARGS+=("--package")
shift
while [[ $# -gt 0 && ! "$1" =~ ^-- ]]; do
BUILD_ARGS+=("$1")
shift
done
;;
--sync-remote)
SYNC_REMOTE="$2"
shift 2
;;
--skip-prod-check)
SKIP_PROD_CHECK=true
shift
;;
--dry-run)
DRY_RUN=true
BUILD_ARGS+=("--dry-run")
shift
;;
-h | --help)
echo "Usage: $0 [OPTIONS]"
echo ""
echo "Options:"
echo " --arch <arch> Target architecture (x86_64 or aarch64, default: x86_64)"
echo " --mirror <mirror> Mirror to use (edge, rc, or stable, default: edge)"
echo " --package <names> Build only the specified package(s) (space-separated)"
echo " --sync-remote <path> Rclone remote for sync (default: pkgs.omarchy.org:omarchy-pkgs)"
echo " --skip-prod-check Skip production environment check during sync
--dry-run Show build plan only; do not sign/promote/clean/update/sync"
echo " -h, --help Show this help message"
echo ""
echo "This script runs the complete workflow:"
echo " build → sign → promote → clean → sync"
exit 0
;;
*)
print_error "Unknown option: $1"
exit 1
;;
esac
done
echo ""
print_info "Target architecture: $ARCH"
print_info "Mirror: $MIRROR"
print_info "Build workspace: $BUILD_OUTPUT_DIR"
# One channel mutation at a time: a timer firing mid-run or a second operator
# waits here instead of interleaving a partial publish.
if [[ "$DRY_RUN" != true ]]; then
acquire_release_lock || exit 1
fi
# --- reporting ---------------------------------------------------------------
RELEASE_STARTED_AT=$(date +%s)
RELEASE_COMMIT=$(git -C "$BUILD_ROOT" rev-parse --short HEAD 2>/dev/null || echo "unknown")
RELEASE_COMMIT_SUBJECT=$(git -C "$BUILD_ROOT" log -1 --pretty=%s 2>/dev/null || echo "")
RELEASE_CONTEXT="Channel: <strong>$MIRROR</strong> · Arch: $ARCH · $(hostname -s 2>/dev/null || echo host)"
if [[ "$RELEASE_COMMIT" != "unknown" ]]; then
RELEASE_CONTEXT+="<br>Commit: <code>$RELEASE_COMMIT</code> $(basecamp_html_escape <<<"$RELEASE_COMMIT_SUBJECT")"
fi
# Captured after the build step: promote MOVES these files out of build-output,
# so the list has to be taken while they are still there.
BUILT_FILES=""
# What the scheduled version check queued, when it was the one that asked for
# this run. Absent for a manual run, which is fine — the report just omits it.
QUEUED_PACKAGES=""
QUEUE_FILE="${OMARCHY_STATE_DIR:-/root/.state}/.sync-needed-$MIRROR"
[[ -s "$QUEUE_FILE" ]] && QUEUED_PACKAGES=$(grep -c '' "$QUEUE_FILE")
if [[ "$DRY_RUN" != true ]]; then
start_details="$RELEASE_CONTEXT"
if [[ -n "$QUEUED_PACKAGES" && "$QUEUED_PACKAGES" != "0" ]]; then
start_details+="<br><br><strong>$QUEUED_PACKAGES package(s) queued:</strong><br>"
start_details+="$(head -25 "$QUEUE_FILE" | tr '\n' ' ' | basecamp_html_escape)"
((QUEUED_PACKAGES > 25)) && start_details+=" …and $((QUEUED_PACKAGES - 25)) more"
fi
notify_start "Release started: $MIRROR" "$start_details"
fi
# Step 1: Build
echo ""
if [[ "$DRY_RUN" == true ]]; then
print_info "Step 1/6: Planning build..."
else
print_info "Step 1/6: Building packages..."
fi
"$BUILD_ROOT/bin/build" "${BUILD_ARGS[@]}" || {
print_error "Build failed"
notify_error "Release failed: Build step failed" "$RELEASE_CONTEXT"
exit 1
}
if [[ "$DRY_RUN" == true ]]; then
echo ""
print_success "Release dry run complete (build plan only)."
exit 0
fi
BUILT_FILES=$(built_package_files "$BUILD_OUTPUT_DIR")
BUILT_COUNT=$(grep -c '' <<<"$BUILT_FILES")
[[ -z "$BUILT_FILES" ]] && BUILT_COUNT=0
print_info "Built $BUILT_COUNT package(s) this run"
# Step 2: Sign
echo ""
print_info "Step 2/6: Signing packages..."
"$BUILD_ROOT/bin/sign" --arch "$ARCH" --mirror "$MIRROR" || {
print_error "Signing failed"
notify_error "Release failed: Signing step failed" "$RELEASE_CONTEXT"
exit 1
}
# Step 3: Promote
echo ""
print_info "Step 3/6: Promoting to production..."
"$BUILD_ROOT/bin/promote-build" --arch "$ARCH" --mirror "$MIRROR" || {
print_error "Promotion failed"
notify_error "Release failed: Promotion step failed" "$RELEASE_CONTEXT"
exit 1
}
# Step 4: Clean
echo ""
print_info "Step 4/6: Cleaning old versions..."
"$BUILD_ROOT/bin/clean-repo" --arch "$ARCH" --mirror "$MIRROR" || {
print_error "Cleaning failed"
notify_error "Release failed: Clean step failed" "$RELEASE_CONTEXT"
exit 1
}
# Step 5: Update DB
echo ""
print_info "Step 5/6: Updating repository database..."
"$BUILD_ROOT/bin/update-repo" --arch "$ARCH" --mirror "$MIRROR" || {
print_error "Database update failed"
notify_error "Release failed: Database update step failed" "$RELEASE_CONTEXT"
exit 1
}
# Step 6: Sync
echo ""
print_info "Step 6/6: Syncing to remote..."
SYNC_ARGS=("--mirror" "$MIRROR" "--arch" "$ARCH")
if [[ -n "$SYNC_REMOTE" ]]; then
SYNC_ARGS+=("--remote" "$SYNC_REMOTE")
fi
if [[ "$SKIP_PROD_CHECK" == true ]]; then
SYNC_ARGS+=("--skip-prod-check")
fi
"$BUILD_ROOT/bin/sync-repo" "${SYNC_ARGS[@]}" || {
print_error "Sync failed"
notify_error "Release failed: Sync step failed" "$RELEASE_CONTEXT"
exit 1
}
duration=$(format_duration $(($(date +%s) - RELEASE_STARTED_AT)))
summary="$RELEASE_CONTEXT<br>Duration: $duration"
if ((BUILT_COUNT > 0)); then
summary+="<br><br><strong>$BUILT_COUNT package(s) published:</strong>"
summary+="$(format_package_list_html "$BUILT_FILES")"
summary+="<br><br>Live at https://pkgs.omarchy.org/$MIRROR/$ARCH/"
notify_success "Release published: $MIRROR" "$summary"
else
# Rare by construction: a release only runs when the version check queued
# work, so publishing nothing means the check and the builder disagreed
# about what needs building. Worth reporting for exactly that reason — if
# these start recurring, something is flagging a package that never builds.
summary+="<br>No packages needed building — the version check and the"
summary+=" builder disagree about what is out of date."
if [[ -n "$QUEUED_PACKAGES" && "$QUEUED_PACKAGES" != "0" ]]; then
summary+="<br>Queued but not built: $(head -25 "$QUEUE_FILE" | tr '\n' ' ' | basecamp_html_escape)"
fi
notify_info "Release ran with nothing to publish: $MIRROR" "$summary"
fi
echo ""
print_success "Release workflow completed successfully!"