4d82591052
gates / gates (push) Successful in 7s
R-115's whole point is that publishing cannot be forgotten because it rides the release script. On the first real release through it (v0.121.0, R-86) it died at exactly that leg: scripts/release-agent.sh: line 101: .../scripts/publish-agent.sh: Permission denied publish-agent.sh has been mode 0644 since it was created on 2026-06-28 — every earlier caller ran it as `bash scripts/publish-agent.sh`, so nothing ever noticed, and release-agent.sh (written the same day it was needed) called it directly. Two fixes, both small and both wanted: restore the executable bit, and invoke it through `bash` so the release no longer depends on a file mode — the kind of thing a checkout, an archive or a copy loses again. The v0.121.0 tag created by the failed run is withdrawn and recreated on this commit; nothing was published under it (verified 404 on the package endpoint), so one version name still means one binary.
92 lines
4.7 KiB
Bash
Executable File
92 lines
4.7 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# publish-agent.sh — build (optional) + publish the felhom-agent binary to Gitea as a generic package.
|
|
#
|
|
# Part of the BUNDLE slice: the host-bootstrap script fetches the agent binary from Gitea
|
|
# (/api/packages/admin/generic/felhom-agent/<ver>/felhom-agent) and verifies its sha256 against the
|
|
# hub-vouched artifact manifest before installing it. This script PUTs that binary and prints the
|
|
# version + sha256 the operator records in the hub (Configs → "Day-0 artifacts").
|
|
#
|
|
# The binary is PINNED to a version (never :latest). The published path encodes the version.
|
|
#
|
|
# Usage:
|
|
# GITEA_USER=admin GITEA_TOKEN=<token> ./publish-agent.sh <version> [binary-path]
|
|
#
|
|
# <version> bare semver, e.g. 0.43.0 (MUST match the binary's `--version`)
|
|
# [binary-path] path to a prebuilt felhom-agent binary. If omitted, the script builds one with
|
|
# `go build -ldflags "-X main.version=<version>"` from the repo (needs a Go toolchain).
|
|
#
|
|
# Env:
|
|
# GITEA_USER / GITEA_TOKEN Gitea credentials with package write (the build-server's admin creds).
|
|
# Falls back to REGISTRY_USER / REGISTRY_TOKEN if those are unset.
|
|
# GITEA_BASE Gitea base URL (default https://gitea.dooplex.hu)
|
|
# GITEA_OWNER package owner (default admin)
|
|
#
|
|
# Output (stdout, machine-greppable):
|
|
# AGENT_VERSION=<version>
|
|
# AGENT_SHA256=<sha256>
|
|
set -euo pipefail
|
|
|
|
GITEA_BASE="${GITEA_BASE:-https://gitea.dooplex.hu}"
|
|
GITEA_OWNER="${GITEA_OWNER:-admin}"
|
|
GITEA_USER="${GITEA_USER:-${REGISTRY_USER:-}}"
|
|
GITEA_TOKEN="${GITEA_TOKEN:-${REGISTRY_TOKEN:-}}"
|
|
|
|
die() { echo "[publish-agent] ERROR: $*" >&2; exit 1; }
|
|
log() { echo "[publish-agent] $*" >&2; }
|
|
|
|
VERSION="${1:-}"
|
|
BIN="${2:-}"
|
|
[[ -n "$VERSION" ]] || die "version required (usage: GITEA_USER=.. GITEA_TOKEN=.. $0 <version> [binary-path])"
|
|
[[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || die "version must be bare semver X.Y.Z (got '$VERSION')"
|
|
[[ -n "$GITEA_USER" && -n "$GITEA_TOKEN" ]] || die "GITEA_USER + GITEA_TOKEN (or REGISTRY_USER/REGISTRY_TOKEN) required"
|
|
|
|
# Resolve repo root from this script's location (scripts/ lives at the repo root).
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
|
|
# Build the binary if no prebuilt path was given.
|
|
CLEANUP_BIN=""
|
|
if [[ -z "$BIN" ]]; then
|
|
command -v go >/dev/null || die "no binary-path given and no 'go' toolchain to build one"
|
|
BIN="$(mktemp -t felhom-agent.XXXXXX)"
|
|
CLEANUP_BIN="$BIN"
|
|
log "building felhom-agent $VERSION from $REPO_ROOT …"
|
|
( cd "$REPO_ROOT" && CGO_ENABLED=0 go build -ldflags "-X main.version=${VERSION}" -o "$BIN" ./cmd/felhom-agent )
|
|
fi
|
|
[[ -f "$BIN" ]] || die "binary not found: $BIN"
|
|
trap '[[ -n "$CLEANUP_BIN" ]] && rm -f "$CLEANUP_BIN"' EXIT
|
|
|
|
# Sanity: the binary's self-reported version MUST match the publish version (catch a stale rebuild).
|
|
BIN_VER="$("$BIN" --version 2>/dev/null | awk '{print $2}' || true)"
|
|
if [[ -n "$BIN_VER" && "$BIN_VER" != "$VERSION" ]]; then
|
|
die "binary --version is '$BIN_VER' but publishing as '$VERSION' — rebuild with the right ldflags"
|
|
fi
|
|
|
|
SHA256="$(sha256sum "$BIN" | awk '{print $1}')"
|
|
[[ -n "$SHA256" ]] || die "failed to compute sha256"
|
|
|
|
URL="${GITEA_BASE}/api/packages/${GITEA_OWNER}/generic/felhom-agent/${VERSION}/felhom-agent"
|
|
log "publishing $BIN ($(wc -c < "$BIN") bytes, sha256 ${SHA256:0:16}…) → $URL"
|
|
|
|
# Generic packages reject re-upload of an existing version+file with 409/400. Delete-then-put makes
|
|
# re-publishing a version idempotent (so a rebuild of the same version overwrites cleanly).
|
|
code="$(curl -fsS -o /dev/null -w '%{http_code}' -u "${GITEA_USER}:${GITEA_TOKEN}" -X DELETE "$URL" 2>/dev/null || true)"
|
|
log "pre-delete existing artifact: HTTP ${code} (404/204 expected)"
|
|
|
|
code="$(curl -sS -o /dev/null -w '%{http_code}' -u "${GITEA_USER}:${GITEA_TOKEN}" -X PUT --upload-file "$BIN" "$URL")"
|
|
[[ "$code" == "201" || "$code" == "200" ]] || die "upload failed: HTTP $code"
|
|
log "upload OK (HTTP $code)"
|
|
|
|
# GET round-trip: re-fetch and confirm the stored bytes hash to the same sha256 (proves fetchable +
|
|
# intact end-to-end, the same path the host-install script will take).
|
|
TMP_GET="$(mktemp -t felhom-agent-get.XXXXXX)"
|
|
trap '[[ -n "$CLEANUP_BIN" ]] && rm -f "$CLEANUP_BIN"; rm -f "$TMP_GET"' EXIT
|
|
curl -fsS -u "${GITEA_USER}:${GITEA_TOKEN}" -o "$TMP_GET" "$URL" || die "round-trip GET failed"
|
|
GOT_SHA="$(sha256sum "$TMP_GET" | awk '{print $1}')"
|
|
[[ "$GOT_SHA" == "$SHA256" ]] || die "round-trip sha256 mismatch (put $SHA256, got $GOT_SHA)"
|
|
log "round-trip GET verified (sha256 matches)"
|
|
|
|
echo "AGENT_VERSION=${VERSION}"
|
|
echo "AGENT_SHA256=${SHA256}"
|
|
log "DONE. Record in the hub operator UI (Configs → Day-0 artifacts): agent ${VERSION} / ${SHA256}"
|