Promote v0.1.18 to production

This commit is contained in:
GPU Kitchen delivery
2026-09-29 01:45:50 +00:00
parent 2b476b4e5f
commit cd50796883
3 changed files with 94 additions and 16 deletions
+82 -4
View File
@@ -87,6 +87,15 @@ arch_asset() {
esac esac
} }
# [INS-19] A (re)install has just replaced the binary under a daemon that may be
# running: `systemctl enable --now` is a no-op on an active unit and would leave the
# OLD process in memory, speaking the old protocol to the new controller. Enable, then
# restart — which also starts a daemon that was not running.
start_daemon() {
systemctl enable "$SERVICE_NAME"
systemctl restart "$SERVICE_NAME"
}
install_binary() { # [local-path] install_binary() { # [local-path]
if [ -n "${1:-}" ]; then if [ -n "${1:-}" ]; then
[ -f "$1" ] || die "binary not found: $1" [ -f "$1" ] || die "binary not found: $1"
@@ -630,7 +639,7 @@ cmd_install() {
echo " for automatic admission or administrator approval." echo " for automatic admission or administrator approval."
fi fi
fi fi
systemctl enable --now "$SERVICE_NAME" start_daemon
echo "==> $SERVICE_NAME enabled and started" echo "==> $SERVICE_NAME enabled and started"
echo echo
echo "Done. The worker daemon is running${ENROLL_TOKEN:+ and enrolled}." echo "Done. The worker daemon is running${ENROLL_TOKEN:+ and enrolled}."
@@ -640,7 +649,7 @@ cmd_install() {
fi fi
# ── Controller: start the daemon, then bring up the app container ── # ── Controller: start the daemon, then bring up the app container ──
systemctl enable --now "$SERVICE_NAME" start_daemon
echo "==> $SERVICE_NAME enabled and started" echo "==> $SERVICE_NAME enabled and started"
# The pull is the long part of a first install (a multi-GB image) and workerd # The pull is the long part of a first install (a multi-GB image) and workerd
# runs docker with its output captured, so pulling from inside `apply` is # runs docker with its output captured, so pulling from inside `apply` is
@@ -1110,6 +1119,67 @@ cmd_apply() {
# Worker: the signed-binary self-update is DRIVEN FROM THE CONTROLLER (its Update # Worker: the signed-binary self-update is DRIVEN FROM THE CONTROLLER (its Update
# button → POST /api/nodes/:id/host/update → cmd:host_update → verified swap). # button → POST /api/nodes/:id/host/update → cmd:host_update → verified swap).
# There is no local unverified swap path. # There is no local unverified swap path.
# [INS-03] `gpuk update` moves the WHOLE host to the release the signed channel
# vouches for: the root daemon as well as the app container. Updating only the
# container leaves the co-located worker on the previous protocol, which the new
# controller refuses — and a refused worker cannot receive the UI's Update either.
# The binary is held to the same chain as install.sh's: minisign signature by the
# pinned key, trusted comment naming the build the channel designates for this
# architecture, never older than the daemon already installed. Sets DAEMON_UPDATED.
DAEMON_UPDATED=0
update_daemon() {
_base=$(channel_field "$CHANNEL_DOC" workerBase)
case "$(uname -m)" in
x86_64|amd64) _bkey="workerBuildIdX86_64" ;;
aarch64|arm64) _bkey="workerBuildIdAarch64" ;;
*) die "unsupported architecture: $(uname -m)" ;;
esac
_build=$(channel_field "$CHANNEL_DOC" "$_bkey")
if [ -z "$_base" ] || [ -z "$_build" ]; then
die "the signed release channel names no gpu-kitchen-worker build for $(uname -m) — refusing to leave the daemon on another release (OPS-20)"
fi
_installed=$("$BIN_DEST" --version 2>/dev/null | sed -n 's/^gpu-kitchen-worker //p' | head -1)
if [ "$_installed" = "$_build" ]; then
echo "==> worker daemon already on build $_build"
return 0
fi
case "$_installed" in
[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-*)
# buildId = YYYYMMDDHHMMSS-<commit>: the timestamp orders builds.
[ "${_build%%-*}" -ge "${_installed%%-*}" ] \
|| die "the channel's gpu-kitchen-worker $_build is OLDER than the installed $_installed — refusing a downgrade" ;;
esac
_url="$_base/$(arch_asset)"
echo "==> gpu-kitchen-worker ${_installed:-(unknown build)} → $_build"
command -v curl >/dev/null || die "curl is required to download the daemon"
curl -fL --progress-bar "$_url" -o "$BIN_DEST.new" \
|| { rm -f "$BIN_DEST.new"; die "cannot download $_url"; }
if [ "${GPUK_CHANNEL_INSECURE:-}" = "1" ]; then
echo "WARNING: GPUK_CHANNEL_INSECURE=1 — $_url NOT verified" >&2
else
require_release_key
curl -fsSL "$_url.minisig" -o "$BIN_DEST.new.minisig" \
|| { rm -f "$BIN_DEST.new" "$BIN_DEST.new.minisig"; die "no signature at $_url.minisig — refusing an unsigned daemon binary"; }
_comment=$("$MINISIGN" -V -m "$BIN_DEST.new" -x "$BIN_DEST.new.minisig" -P "$CHANNEL_PUBKEY" 2>/dev/null \
| sed -n 's/^Trusted comment: //p' | head -1)
rm -f "$BIN_DEST.new.minisig"
[ "$_comment" = "gpu-kitchen-worker@$_build" ] \
|| { rm -f "$BIN_DEST.new"; die "$_url is signed for '${_comment:-nothing}', not gpu-kitchen-worker@$_build — refusing it (OPS-20)"; }
echo "==> signature verified (build $_build)"
fi
chmod 0755 "$BIN_DEST.new"
mv "$BIN_DEST.new" "$BIN_DEST"
DAEMON_UPDATED=1
}
# The running daemon still executes the replaced binary until it restarts.
restart_updated_daemon() {
[ "$DAEMON_UPDATED" -eq 1 ] || return 0
systemctl restart "$SERVICE_NAME" \
|| die "the daemon binary was updated but $SERVICE_NAME did not restart — run: systemctl restart $SERVICE_NAME"
echo "==> $SERVICE_NAME restarted on the new build"
}
cmd_update() { cmd_update() {
need_root need_root
_want=""; _check=0 _want=""; _check=0
@@ -1123,8 +1193,12 @@ cmd_update() {
_image=$(manifest_image) _image=$(manifest_image)
if [ -z "$_image" ]; then if [ -z "$_image" ]; then
echo "This is a worker node. Worker self-update is driven from the controller UI" # A worker node: the daemon is the whole install. The controller UI's Update
echo "(the node's Update button), which pushes a minisign-verified binary swap." # button drives the same swap, but only for a worker it still accepts.
[ "$_check" -eq 0 ] || { echo "This is a worker node: 'gpuk update' moves its daemon to the channel's build."; return 0; }
channel_fetch || die "cannot read the release channel at $CHANNEL_URL"
update_daemon
restart_updated_daemon
return 0 return 0
fi fi
@@ -1193,10 +1267,14 @@ cmd_update() {
else else
echo "==> already on $_current — re-pulling and recreating" echo "==> already on $_current — re-pulling and recreating"
fi fi
# The daemon follows the release it is pinned to — only the channel's own one
# carries a designated, signed build.
[ "$_want" != "$_latest" ] || update_daemon
GPUK_MANIFEST_PATH="$MANIFEST" "$BIN_DEST" apply \ GPUK_MANIFEST_PATH="$MANIFEST" "$BIN_DEST" apply \
|| die "the update did not apply — the [worker] lines above say why. A manifest refused for a field || die "the update did not apply — the [worker] lines above say why. A manifest refused for a field
an older release wrote is repaired by re-running the same install command with --reset-manifest: an older release wrote is repaired by re-running the same install command with --reset-manifest:
the file is archived beside itself and rebuilt from this install's settings." the file is archived beside itself and rebuilt from this install's settings."
restart_updated_daemon
} }
# ── uninstall ────────────────────────────────────────────────────────────────── # ── uninstall ──────────────────────────────────────────────────────────────────
+9 -9
View File
@@ -1,14 +1,14 @@
{ {
"version": "v0.1.17", "version": "v0.1.18",
"semver": "0.1.17", "semver": "0.1.18",
"controllerImage": "repo.byterain.io/gpukitchen/gpukitchen-controller", "controllerImage": "repo.byterain.io/gpukitchen/gpukitchen-controller",
"controllerImageEnterprise": "repo.byterain.io/gpukitchen-private/gpukitchen-controller-ee", "controllerImageEnterprise": "repo.byterain.io/gpukitchen-private/gpukitchen-controller-ee",
"controllerImageDigest": "sha256:106ff37f3df93fdccaacef9cf0a8c5a54c8864a3e936c5ab5f0911489b6e6b99", "controllerImageDigest": "sha256:018b2f62519c2b8856022855dadff5cc43b6c23a70d0511e4475bb52fbc89df5",
"controllerImageDigestEnterprise": "sha256:d296b9bd91701f1072d553bac80b814e9a60ec12d2033168a1ecdfa8b0ea47da", "controllerImageDigestEnterprise": "sha256:401e646d750d22102c4b5110418650bea551255b4fe830b99e789ac1a104aa54",
"gpukScriptSha256": "40286416f58d4807c18d62b8dda988ef87714e32c35fe1343e8b4de3fad36dcf", "gpukScriptSha256": "0e7acfa5d01ec83c4436304d166565937c1c682ebf5557b6d488f9a4192ba901",
"workerBuildIdX86_64": "20260928224355-94265bf9a70de6d50abe4cf0bee543cabc99740a", "workerBuildIdX86_64": "20260929011028-3858aae6ec272ae95a02c1860382802fedef55c9",
"workerBuildIdAarch64": "20260928224355-94265bf9a70de6d50abe4cf0bee543cabc99740a", "workerBuildIdAarch64": "20260929011028-3858aae6ec272ae95a02c1860382802fedef55c9",
"workerBase": "https://repo.byterain.io/api/packages/gpukitchen/generic/gpu-kitchen-worker/v0.1.17", "workerBase": "https://repo.byterain.io/api/packages/gpukitchen/generic/gpu-kitchen-worker/v0.1.18",
"gpukScript": "https://repo.byterain.io/api/packages/gpukitchen/generic/gpu-kitchen-channel/v0.1.17/gpuk", "gpukScript": "https://repo.byterain.io/api/packages/gpukitchen/generic/gpu-kitchen-channel/v0.1.18/gpuk",
"releaseNotes": "https://repo.byterain.io/gpukitchen/channel" "releaseNotes": "https://repo.byterain.io/gpukitchen/channel"
} }
+3 -3
View File
@@ -1,4 +1,4 @@
untrusted comment: signature from minisign secret key untrusted comment: signature from minisign secret key
RUQ7BKXJqGX2jaBPnMPv5YyHwVbk6zcwDS7X4JofaAAfbWXjj5agxD8DS53UDyYUo17RWDjxO/QJRrutyKjW8vAxH0UYxzBGBQs= RUQ7BKXJqGX2jYPHJGXskiWTpLMBRffCSFrkWtpw8ijANWROGOzw6yUQoEV/HkogGFDnWfmPsvJTLrU1mYxUsdCy57uw/JCoPwI=
trusted comment: gpu-kitchen channel v0.1.17 trusted comment: gpu-kitchen channel v0.1.18
ZA76R/yyFGS2Os823ISwjzZLnEkLJcpO3GUtx7f4YsDRwkDPxSVyR6z+SO4lxwsrM4i6ksg9MZIDqGfvoGerCQ== OAAL3XLadiHW6lZ8PM3JBjVhSbyWANB0X4ERB1HOg4gzTg08EoiviEB55WCb8r1kNFwGAVZl18oHXejsoUy4Ag==