Name the server OMARCHY_REPO_HOST, not OMARCHY_BUILD_HOST

Builds now happen wherever the operator likes, so naming the destination after
building described the old arrangement rather than the current one. What the
push and deploy commands reach is the machine that serves pkgs.omarchy.org and
holds the signing key: the repository host. It also runs the scheduled builds,
which is why the trigger in omarchy-pkgs release points at the same place.

Resolution moves into helpers/host-helpers.sh, which all three commands now
share instead of repeating: --host, then OMARCHY_REPO_HOST, then .repo-host.
OMARCHY_BUILD_HOST and .build-host keep working as fallbacks, so existing
environments and checkouts are unaffected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
David Heinemeier Hansson
2026-08-12 03:46:58 -07:00
co-authored by Claude Opus 5
parent fd9c078bf2
commit 34326295e9
7 changed files with 101 additions and 57 deletions
+1
View File
@@ -34,3 +34,4 @@ pkgbuilds/symfony-cli/symfony*
pkgbuilds/yay/yay/ pkgbuilds/yay/yay/
.srcdest/ .srcdest/
.build-host .build-host
.repo-host
+20 -13
View File
@@ -78,7 +78,8 @@ bin/repo sync # Sync to remote
### Building Heavy Packages Locally ### Building Heavy Packages Locally
Large packages build faster on a local machine than on the server. Build them Large packages build faster on a local machine than on the server. Build them
here, then hand the artifacts to the build host, which signs and publishes them: here, then hand the artifacts to the repository host, which signs and publishes
them:
```bash ```bash
bin/repo deploy --package nvidia-580xx-utils # Build here, publish from the host bin/repo deploy --package nvidia-580xx-utils # Build here, publish from the host
@@ -94,7 +95,7 @@ bin/repo push --package nvidia-580xx-utils # Upload + publish on the host
`push` uploads to the host's `build-output/`, verifies checksums, and runs `push` uploads to the host's `build-output/`, verifies checksums, and runs
`bin/upload-prebuilt` there. Do not publish from a local checkout instead: only `bin/upload-prebuilt` there. Do not publish from a local checkout instead: only
the build host holds the complete repository and the signing key. the repository host holds the complete repository and the signing key.
## Commands ## Commands
@@ -182,25 +183,25 @@ publish packages built on another machine.
```bash ```bash
bin/repo deploy --package nvidia-580xx-utils # Build locally, publish from the host bin/repo deploy --package nvidia-580xx-utils # Build locally, publish from the host
bin/repo deploy --host root@example.com # Point at a specific build host bin/repo deploy --host root@example.com # Point at a specific repo host
bin/repo deploy --dry-run # Show the plan, change nothing bin/repo deploy --dry-run # Show the plan, change nothing
``` ```
Runs `build` then `push` in one command. The build host is resolved before the Runs `build` then `push` in one command. The repository host is resolved before
build starts, so a missing `--host` fails immediately rather than after a long the build starts, so a missing `--host` fails immediately rather than after a long
compile. compile.
### Push to the Build Host ### Push to the Repository Host
```bash ```bash
bin/repo push # Push everything in build-output bin/repo push # Push everything in build-output
bin/repo push --package nvidia-580xx-utils # Push one package bin/repo push --package nvidia-580xx-utils # Push one package
bin/repo push --mirror stable --arch aarch64 # Pick mirror and architecture bin/repo push --mirror stable --arch aarch64 # Pick mirror and architecture
bin/repo push --host root@example.com # Override the build host bin/repo push --host root@example.com # Override the repo host
bin/repo push --dry-run # Show the plan, transfer nothing bin/repo push --dry-run # Show the plan, transfer nothing
``` ```
Uploads packages from `build-output/` to the build host and publishes them there Uploads packages from `build-output/` to the repository host and publishes them there
with `bin/upload-prebuilt` (sign → promote → update → sync). Use it when a package with `bin/upload-prebuilt` (sign → promote → update → sync). Use it when a package
is quicker to build on a local machine than on the server. is quicker to build on a local machine than on the server.
@@ -209,9 +210,14 @@ signing key lives there and nowhere else, and only the host holds the complete
repository that a correct database and sync require. Local machines therefore repository that a correct database and sync require. Local machines therefore
need no secrets. need no secrets.
The host comes from `--host`, `$OMARCHY_BUILD_HOST`, or `.build-host`, in that The host comes from `--host`, `$OMARCHY_REPO_HOST`, then `.repo-host`. One
order. Note that `.build-host` also arms the automatic build trigger in machine both serves pkgs.omarchy.org and runs the scheduled builds, so the
`bin/omarchy-pkgs release`; pass `--host` or set `OMARCHY_BUILD_HOST` to keep the setting is named for the repository rather than for building, which now happens
wherever you like. `OMARCHY_BUILD_HOST` and `.build-host` are the previous names
and still work.
Note that `.repo-host` also arms the automatic build trigger in
`bin/omarchy-pkgs release`; pass `--host` or set `OMARCHY_REPO_HOST` to keep the
two separate. two separate.
Split packages are selected by their own names, not their pkgbase — pushing Split packages are selected by their own names, not their pkgbase — pushing
@@ -315,8 +321,9 @@ stable — promotion is always this explicit step.
### Build trigger ### Build trigger
After pushing, the command triggers the build host over ssh when After pushing, the command triggers the build host over ssh when
`OMARCHY_BUILD_HOST` is set (env var, or a hostname in the git-ignored `OMARCHY_REPO_HOST` is set (env var, or a hostname in the git-ignored
`.build-host` file). Without it, the 6-hourly auto-release timer picks up the `.repo-host` file; `OMARCHY_BUILD_HOST` and `.build-host` still work). Without
it, the 6-hourly auto-release timer picks up the
change on its own. change on its own.
## Directory Structure ## Directory Structure
+9 -16
View File
@@ -1,5 +1,5 @@
#!/bin/bash #!/bin/bash
# Build packages locally, then publish them from the build host. # Build packages locally, then publish them from the repository host.
# #
# The two halves of shipping a package built on a local machine: bin/build # The two halves of shipping a package built on a local machine: bin/build
# produces the artifacts, bin/push-build hands them to the host that owns the # produces the artifacts, bin/push-build hands them to the host that owns the
@@ -11,6 +11,7 @@ SCRIPT_DIR=$(realpath "${BASH_SOURCE[0]%/*}")
BUILD_ROOT=$(realpath "$SCRIPT_DIR/..") BUILD_ROOT=$(realpath "$SCRIPT_DIR/..")
source "$BUILD_ROOT/helpers/message-helpers.sh" source "$BUILD_ROOT/helpers/message-helpers.sh"
source "$BUILD_ROOT/helpers/paths.sh" source "$BUILD_ROOT/helpers/paths.sh"
source "$BUILD_ROOT/helpers/host-helpers.sh"
PACKAGES=() PACKAGES=()
PACKAGE_FLAG_GIVEN=false PACKAGE_FLAG_GIVEN=false
@@ -64,13 +65,13 @@ while [[ $# -gt 0 ]]; do
-h | --help) -h | --help)
echo "Usage: $0 [OPTIONS]" echo "Usage: $0 [OPTIONS]"
echo "" echo ""
echo "Build packages here, then publish them from the build host." echo "Build packages here, then publish them from the repository host."
echo "" echo ""
echo "Options:" echo "Options:"
echo " --arch <arch> Target architecture (default: x86_64)" echo " --arch <arch> Target architecture (default: x86_64)"
echo " --mirror <mirror> Mirror to publish to (edge or stable, default: edge)" echo " --mirror <mirror> Mirror to publish to (edge or stable, default: edge)"
echo " --package <names> Build and push only these packages (space-separated)" echo " --package <names> Build and push only these packages (space-separated)"
echo " --host <host> ssh destination (default: \$OMARCHY_BUILD_HOST or .build-host)" echo " --host <host> ssh destination (default: \$OMARCHY_REPO_HOST or .repo-host)"
echo " --remote-root <path> Repository path on the host (default: /root/omarchy-pkgs)" echo " --remote-root <path> Repository path on the host (default: /root/omarchy-pkgs)"
echo " --dry-run Show the plan, build nothing and transfer nothing" echo " --dry-run Show the plan, build nothing and transfer nothing"
echo " -y, --yes Do not ask for confirmation before publishing" echo " -y, --yes Do not ask for confirmation before publishing"
@@ -96,7 +97,7 @@ fi
echo "" echo ""
print_info "This will:" print_info "This will:"
echo " 1. Build packages locally" echo " 1. Build packages locally"
echo " 2. Upload them to the build host" echo " 2. Upload them to the repository host"
echo " 3. Sign, promote, update and sync them there" echo " 3. Sign, promote, update and sync them there"
echo "" echo ""
@@ -112,18 +113,10 @@ fi
[[ "$DRY_RUN" == true ]] && BUILD_ARGS+=("--dry-run") && PUSH_ARGS+=("--dry-run") [[ "$DRY_RUN" == true ]] && BUILD_ARGS+=("--dry-run") && PUSH_ARGS+=("--dry-run")
[[ "$ASSUME_YES" == true ]] && PUSH_ARGS+=("--yes") [[ "$ASSUME_YES" == true ]] && PUSH_ARGS+=("--yes")
# Resolve the host before spending build time on packages that cannot ship. # Resolve the repository host before spending build time on packages that cannot ship.
if [[ "$DRY_RUN" != true ]]; then if [[ "$DRY_RUN" != true ]]; then
resolved_host="$HOST" if ! resolve_repo_host "$HOST" >/dev/null; then
if [[ -z "$resolved_host" ]]; then print_no_repo_host
resolved_host="${OMARCHY_BUILD_HOST:-}"
[[ -z "$resolved_host" && -f "$BUILD_ROOT/.build-host" ]] && resolved_host=$(<"$BUILD_ROOT/.build-host")
fi
if [[ -z "$resolved_host" ]]; then
print_error "No build host configured"
echo ""
echo "Pass --host, set OMARCHY_BUILD_HOST, or write the destination to:"
echo " $BUILD_ROOT/.build-host"
exit 1 exit 1
fi fi
fi fi
@@ -133,6 +126,6 @@ echo ""
"$SCRIPT_DIR/build" "${BUILD_ARGS[@]}" "$SCRIPT_DIR/build" "${BUILD_ARGS[@]}"
echo "" echo ""
print_info "Step 2/2: Pushing to the build host..." print_info "Step 2/2: Pushing to the repository host..."
echo "" echo ""
"$SCRIPT_DIR/push-build" "${PUSH_ARGS[@]}" "$SCRIPT_DIR/push-build" "${PUSH_ARGS[@]}"
+7 -8
View File
@@ -15,6 +15,7 @@ set -e
BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..") BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
source "$BUILD_ROOT/helpers/message-helpers.sh" source "$BUILD_ROOT/helpers/message-helpers.sh"
source "$BUILD_ROOT/helpers/host-helpers.sh"
UPSTREAM_URL="${OMARCHY_UPSTREAM_URL:-https://github.com/basecamp/omarchy.git}" UPSTREAM_URL="${OMARCHY_UPSTREAM_URL:-https://github.com/basecamp/omarchy.git}"
EDGE_DB_URL="${OMARCHY_EDGE_DB_URL:-https://pkgs.omarchy.org/edge/x86_64/omarchy.db.tar.zst}" EDGE_DB_URL="${OMARCHY_EDGE_DB_URL:-https://pkgs.omarchy.org/edge/x86_64/omarchy.db.tar.zst}"
@@ -43,8 +44,8 @@ Options for release:
--commit <sha> (rc) Upstream commit to pin (default: tip of --ref) --commit <sha> (rc) Upstream commit to pin (default: tip of --ref)
--ref <branch> (rc) Upstream branch whose tip to pin (default: $DEFAULT_RC_REF) --ref <branch> (rc) Upstream branch whose tip to pin (default: $DEFAULT_RC_REF)
--yes Skip confirmation prompts --yes Skip confirmation prompts
--host <host> ssh destination of the build host to trigger, overriding --host <host> ssh destination of the repository host to trigger,
\$OMARCHY_BUILD_HOST and .build-host overriding \$OMARCHY_REPO_HOST and .repo-host
--no-push Rewrite and commit locally; skip push and build trigger --no-push Rewrite and commit locally; skip push and build trigger
--pr When releasing from a non-master branch, open a GitHub PR --pr When releasing from a non-master branch, open a GitHub PR
to master with gh after pushing to master with gh after pushing
@@ -314,11 +315,9 @@ regenerate_checksums() {
# --- trigger ----------------------------------------------------------------- # --- trigger -----------------------------------------------------------------
trigger_build_host() { trigger_build_host() {
local host="${BUILD_HOST_OVERRIDE:-}" local host
[[ -z "$host" ]] && host="${OMARCHY_BUILD_HOST:-}" if ! host=$(resolve_repo_host "${REPO_HOST_OVERRIDE:-}"); then
[[ -z "$host" && -f "$BUILD_ROOT/.build-host" ]] && host=$(<"$BUILD_ROOT/.build-host") print_info "No repository host configured (set OMARCHY_REPO_HOST or $BUILD_ROOT/.repo-host)."
if [[ -z "$host" ]]; then
print_info "No build host configured (set OMARCHY_BUILD_HOST or $BUILD_ROOT/.build-host)."
print_info "The 6-hourly auto-release timer will pick this up, or trigger manually:" print_info "The 6-hourly auto-release timer will pick this up, or trigger manually:"
echo " ssh <build-host> 'git -C /root/omarchy-pkgs pull --ff-only && touch /root/.state/.sync-needed-edge && systemctl start omarchy-auto-release-edge.service'" echo " ssh <build-host> 'git -C /root/omarchy-pkgs pull --ff-only && touch /root/.state/.sync-needed-edge && systemctl start omarchy-auto-release-edge.service'"
return 0 return 0
@@ -344,7 +343,7 @@ cmd_release() {
--force) force=true; shift ;; --force) force=true; shift ;;
--commit) commit_arg="$2"; shift 2 ;; --commit) commit_arg="$2"; shift 2 ;;
--ref) ref="$2"; shift 2 ;; --ref) ref="$2"; shift 2 ;;
--host) BUILD_HOST_OVERRIDE="$2"; shift 2 ;; --host) REPO_HOST_OVERRIDE="$2"; shift 2 ;;
--yes) assume_yes=true; shift ;; --yes) assume_yes=true; shift ;;
--dry-run) dry_run=true; shift ;; --dry-run) dry_run=true; shift ;;
-h | --help) show_usage; exit 0 ;; -h | --help) show_usage; exit 0 ;;
+7 -18
View File
@@ -1,9 +1,9 @@
#!/bin/bash #!/bin/bash
# Push locally built packages to the build host and publish them there. # Push locally built packages to the repository host and publish them there.
# #
# Heavy packages are quicker to build on a local machine than on the server, but # Heavy packages are quicker to build on a local machine than on the server, but
# publishing has to happen where the full repository lives: the signing key is on # publishing has to happen where the full repository lives: the signing key is on
# the build host, and `bin/repo sync` can only produce a correct remote from a # the repository host, and `bin/repo sync` can only produce a correct remote from a
# complete local tree. So this uploads the artifacts and runs the publish steps # complete local tree. So this uploads the artifacts and runs the publish steps
# over ssh rather than syncing from here. # over ssh rather than syncing from here.
@@ -12,6 +12,7 @@ set -e
BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..") BUILD_ROOT=$(realpath "${BASH_SOURCE[0]%/*}/..")
source "$BUILD_ROOT/helpers/message-helpers.sh" source "$BUILD_ROOT/helpers/message-helpers.sh"
source "$BUILD_ROOT/helpers/paths.sh" source "$BUILD_ROOT/helpers/paths.sh"
source "$BUILD_ROOT/helpers/host-helpers.sh"
HOST="" HOST=""
REMOTE_ROOT="/root/omarchy-pkgs" REMOTE_ROOT="/root/omarchy-pkgs"
@@ -72,14 +73,14 @@ while [[ $# -gt 0 ]]; do
-h | --help) -h | --help)
echo "Usage: $0 [OPTIONS]" echo "Usage: $0 [OPTIONS]"
echo "" echo ""
echo "Upload packages from build-output/ to the build host, then sign," echo "Upload packages from build-output/ to the repository host, then sign,"
echo "promote, update and sync them there." echo "promote, update and sync them there."
echo "" echo ""
echo "Options:" echo "Options:"
echo " --arch <arch> Target architecture (default: x86_64)" echo " --arch <arch> Target architecture (default: x86_64)"
echo " --mirror <mirror> Mirror to publish to (edge or stable, default: edge)" echo " --mirror <mirror> Mirror to publish to (edge or stable, default: edge)"
echo " --package <names> Only push these packages (space-separated)" echo " --package <names> Only push these packages (space-separated)"
echo " --host <host> ssh destination (default: \$OMARCHY_BUILD_HOST or .build-host)" echo " --host <host> ssh destination (default: \$OMARCHY_REPO_HOST or .repo-host)"
echo " --remote-root <path> Repository path on the host (default: $REMOTE_ROOT)" echo " --remote-root <path> Repository path on the host (default: $REMOTE_ROOT)"
echo " --dry-run Show what would be pushed, transfer nothing" echo " --dry-run Show what would be pushed, transfer nothing"
echo " -y, --yes Do not ask for confirmation" echo " -y, --yes Do not ask for confirmation"
@@ -100,20 +101,8 @@ done
# --- host resolution --------------------------------------------------------- # --- host resolution ---------------------------------------------------------
if [[ -z "$HOST" ]]; then if ! HOST=$(resolve_repo_host "$HOST"); then
HOST="${OMARCHY_BUILD_HOST:-}" print_no_repo_host
[[ -z "$HOST" && -f "$BUILD_ROOT/.build-host" ]] && HOST=$(<"$BUILD_ROOT/.build-host")
fi
if [[ -z "$HOST" ]]; then
print_error "No build host configured"
echo ""
echo "Pass --host, set OMARCHY_BUILD_HOST, or write the destination to:"
echo " $BUILD_ROOT/.build-host"
echo ""
echo "Note that .build-host also arms the automatic build trigger in"
echo "'bin/omarchy-pkgs release'. Use --host or OMARCHY_BUILD_HOST to keep"
echo "this command's host separate from that."
exit 1 exit 1
fi fi
+2 -2
View File
@@ -58,8 +58,8 @@ show_usage() {
echo " list List source package metadata (use --repo for published repo)" echo " list List source package metadata (use --repo for published repo)"
echo " remove Remove a specific package" echo " remove Remove a specific package"
echo " sync Sync repository to remote" echo " sync Sync repository to remote"
echo " push Upload local builds to the build host and publish them there" echo " push Upload local builds to the repository host and publish them there"
echo " deploy Build locally, then push: one command for a local build machine" echo " deploy Build locally, then push: one command from a build machine"
echo "" echo ""
echo "Typical workflows:" echo "Typical workflows:"
echo " $0 release # Complete release workflow" echo " $0 release # Complete release workflow"
+55
View File
@@ -0,0 +1,55 @@
# Resolving the Omarchy repository host
#
# One machine both hosts pkgs.omarchy.org and runs the scheduled builds. The
# commands that reach it are doing repository work — uploading artifacts,
# signing, publishing — so the setting is named for the repository rather than
# for building, which now happens on whatever machine the operator prefers.
#
# OMARCHY_BUILD_HOST and .build-host are the previous names and still work.
# Usage: resolve_repo_host [explicit-host]
# Prints the host, or nothing when none is configured.
resolve_repo_host() {
local explicit="${1:-}"
if [[ -n "$explicit" ]]; then
echo "$explicit"
return 0
fi
if [[ -n "${OMARCHY_REPO_HOST:-}" ]]; then
echo "$OMARCHY_REPO_HOST"
return 0
fi
if [[ -n "${OMARCHY_BUILD_HOST:-}" ]]; then
echo "$OMARCHY_BUILD_HOST"
return 0
fi
local file
for file in "$BUILD_ROOT/.repo-host" "$BUILD_ROOT/.build-host"; do
if [[ -f "$file" ]]; then
# Ignore blank lines and comments so the file can be annotated.
local value
value=$(grep -vE '^\s*(#|$)' "$file" | head -1 | tr -d '[:space:]')
if [[ -n "$value" ]]; then
echo "$value"
return 0
fi
fi
done
return 1
}
# Shared wording so every command explains configuration the same way.
print_no_repo_host() {
print_error "No repository host configured"
echo ""
echo "Pass --host, set OMARCHY_REPO_HOST, or write the destination to:"
echo " $BUILD_ROOT/.repo-host"
echo ""
echo "That file also arms the automatic build trigger in 'bin/omarchy-pkgs"
echo "release'. Use --host or OMARCHY_REPO_HOST to keep them separate."
}