The fast-ring replication announced itself before the release that triggered it, so chat read as though an rc job had run on its own — the reverse of what happened. The publish report now fires first, and the replication says only how many packages were kept in parity: the release report immediately above it already lists them by name.
243 lines
7.9 KiB
Bash
Executable File
243 lines
7.9 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)
|
|
BUILD_ARGS+=("--package" "$2")
|
|
shift 2
|
|
;;
|
|
--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 <name> Build only the specified package"
|
|
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
|
|
|
|
# Step 7 (stable only): fast-ring packages publish to rc and stable together,
|
|
# so rc never falls behind what stable users actually run. Skipped until the
|
|
# rc channel has been bootstrapped.
|
|
if [[ "$MIRROR" == "stable" ]]; then
|
|
echo ""
|
|
if [[ -f "$REPO_ROOT/rc/$ARCH/omarchy.db.tar.zst" ]]; then
|
|
print_info "Step 7: Replicating fast-ring packages to rc (parity)..."
|
|
REPLICATE_ARGS=(--from stable --to rc --fast-ring --arch "$ARCH")
|
|
[[ -n "$SYNC_REMOTE" ]] && REPLICATE_ARGS+=(--sync-remote "$SYNC_REMOTE")
|
|
[[ "$SKIP_PROD_CHECK" == true ]] && REPLICATE_ARGS+=(--skip-prod-check)
|
|
"$BUILD_ROOT/bin/advance-channel" "${REPLICATE_ARGS[@]}" || {
|
|
print_error "Fast-ring replication to rc failed"
|
|
notify_error "Release failed: rc parity replication failed" "$RELEASE_CONTEXT"
|
|
exit 1
|
|
}
|
|
else
|
|
print_info "rc channel not bootstrapped; skipping fast-ring replication"
|
|
fi
|
|
fi
|
|
|
|
echo ""
|
|
print_success "Release workflow completed successfully!"
|