Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
build(site): add a reproducible 1helm.com deploy
The site has been deployed by hand: git archive a commit into
/opt/1helm-site/releases/<sha>, repoint current, restart the unit. That is
fragile for something that gates a release - install.ps1 and install.sh are
served from here, and install.sh resolves /api/releases/linux/latest to find
the Linux archive, so publishing a release without deploying the site leaves
Windows with no installer and Linux unable to resolve a version.

Refuses any commit that is not an ancestor of origin/main, so the live
surface always traces back to reviewed source. Verifies the archive actually
contains install.sh, install.ps1 and the keepalive payload before going
live, and rolls back to the previous release if the new one fails to answer
its health endpoint.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
  • Loading branch information
gitcommit90 and claude committed Aug 2, 2026
commit a68130cbd4b0f952619517d16753e9b481e0433f
85 changes: 85 additions & 0 deletions scripts/deploy-site.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/usr/bin/env bash
# Deploy 1helm.com from an exact Git commit.
#
# The site is a release-directory deployment on this host: each release is an
# immutable `git archive` of one commit under /opt/1helm-site/releases/<sha>,
# `current` points at the live one, and 1helm-site.service runs
# `node site/server.mjs` from there behind 1helm-site-cloudflared.service.
#
# This exists because the site gates a release. install.ps1 and install.sh are
# served from here, and install.sh resolves /api/releases/linux/latest to find
# the archive - so a release published without deploying the site leaves Windows
# with no installer and Linux unable to resolve a version.
#
# scripts/deploy-site.sh <commit-ish>
#
# Rolls back to the previous release automatically if the new one fails to
# answer, so a bad deploy cannot leave 1helm.com down.
set -euo pipefail

SITE_ROOT=/opt/1helm-site
RELEASES="$SITE_ROOT/releases"
CURRENT="$SITE_ROOT/current"
UNIT=1helm-site.service
PORT=8130

[[ "${EUID}" -eq 0 ]] || { echo "Run with sudo." >&2; exit 1; }
COMMITISH="${1:-}"
[[ -n "$COMMITISH" ]] || { echo "usage: $0 <commit-ish>" >&2; exit 1; }

REPO="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$REPO"

SHA="$(git rev-parse --verify "$COMMITISH^{commit}")"
# A deployed site must be reproducible from a pushed commit, otherwise the live
# surface cannot be traced back to reviewed source.
git merge-base --is-ancestor "$SHA" origin/main 2>/dev/null \
|| { echo "Refusing to deploy $SHA: it is not an ancestor of origin/main." >&2; exit 1; }

TARGET="$RELEASES/$SHA"
PREVIOUS="$(readlink -f "$CURRENT" 2>/dev/null || true)"

echo "repo : $REPO"
echo "commit : $SHA"
echo "previous : ${PREVIOUS:-<none>}"

if [[ -d "$TARGET" ]]; then
echo "release directory already exists; reusing it"
else
install -d -m 0755 "$TARGET"
git archive --format=tar "$SHA" | tar -x -C "$TARGET"
# The site serves the product's own public assets from ../public, so a bare
# archive of site/ alone would 404 icons and schemas.
[[ -d "$TARGET/site" && -f "$TARGET/site/server.mjs" ]] \
|| { echo "archive is missing site/server.mjs" >&2; rm -rf -- "$TARGET"; exit 1; }
for required in site/public/install.sh site/public/install.ps1 site/public/keepalive/keepalive-install.ps1; do
[[ -e "$TARGET/$required" ]] || { echo "archive is missing $required" >&2; rm -rf -- "$TARGET"; exit 1; }
done
fi
Comment on lines +46 to +58

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Validate a reused release directory before promoting it.

The required-asset checks at lines 53-57 only run in the else branch. If an earlier run was interrupted during git archive | tar -x, $TARGET exists but is incomplete. Line 47 then reuses it, and line 61 promotes that partial tree to current. The installers in this same PR guard against exactly this case (install.sh line 306-309, update-host.sh line 282-285).

Move the validation out of the conditional so both the fresh and the reused path are proven.

🐛 Proposed fix: validate on both paths
 if [[ -d "$TARGET" ]]; then
   echo "release directory already exists; reusing it"
 else
   install -d -m 0755 "$TARGET"
   git archive --format=tar "$SHA" | tar -x -C "$TARGET"
-  # The site serves the product's own public assets from ../public, so a bare
-  # archive of site/ alone would 404 icons and schemas.
-  [[ -d "$TARGET/site" && -f "$TARGET/site/server.mjs" ]] \
-    || { echo "archive is missing site/server.mjs" >&2; rm -rf -- "$TARGET"; exit 1; }
-  for required in site/public/install.sh site/public/install.ps1 site/public/keepalive/keepalive-install.ps1; do
-    [[ -e "$TARGET/$required" ]] || { echo "archive is missing $required" >&2; rm -rf -- "$TARGET"; exit 1; }
-  done
 fi
+# The site serves the product's own public assets from ../public, so a bare
+# archive of site/ alone would 404 icons and schemas. A directory retained from
+# an interrupted earlier run can also be incomplete, so check both paths.
+[[ -d "$TARGET/site" && -f "$TARGET/site/server.mjs" ]] \
+  || { echo "archive is missing site/server.mjs" >&2; rm -rf -- "$TARGET"; exit 1; }
+for required in site/public/install.sh site/public/install.ps1 site/public/uninstall.ps1 \
+                site/public/keepalive/keepalive-install.ps1; do
+  [[ -e "$TARGET/$required" ]] || { echo "archive is missing $required" >&2; rm -rf -- "$TARGET"; exit 1; }
+done
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if [[ -d "$TARGET" ]]; then
echo "release directory already exists; reusing it"
else
install -d -m 0755 "$TARGET"
git archive --format=tar "$SHA" | tar -x -C "$TARGET"
# The site serves the product's own public assets from ../public, so a bare
# archive of site/ alone would 404 icons and schemas.
[[ -d "$TARGET/site" && -f "$TARGET/site/server.mjs" ]] \
|| { echo "archive is missing site/server.mjs" >&2; rm -rf -- "$TARGET"; exit 1; }
for required in site/public/install.sh site/public/install.ps1 site/public/keepalive/keepalive-install.ps1; do
[[ -e "$TARGET/$required" ]] || { echo "archive is missing $required" >&2; rm -rf -- "$TARGET"; exit 1; }
done
fi
if [[ -d "$TARGET" ]]; then
echo "release directory already exists; reusing it"
else
install -d -m 0755 "$TARGET"
git archive --format=tar "$SHA" | tar -x -C "$TARGET"
fi
# The site serves the product's own public assets from ../public, so a bare
# archive of site/ alone would 404 icons and schemas. A directory retained from
# an interrupted earlier run can also be incomplete, so check both paths.
[[ -d "$TARGET/site" && -f "$TARGET/site/server.mjs" ]] \
|| { echo "archive is missing site/server.mjs" >&2; rm -rf -- "$TARGET"; exit 1; }
for required in site/public/install.sh site/public/install.ps1 site/public/uninstall.ps1 \
site/public/keepalive/keepalive-install.ps1; do
[[ -e "$TARGET/$required" ]] || { echo "archive is missing $required" >&2; rm -rf -- "$TARGET"; exit 1; }
done
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/deploy-site.sh` around lines 46 - 58, Move the required release
validation from the `else` branch to after the `if [[ -d "$TARGET" ]]`
conditional in `scripts/deploy-site.sh`, so reused and newly extracted
directories both pass the `site/server.mjs` and required-assets checks before
promotion. Preserve the existing cleanup and failure behavior for incomplete
targets.


ln -sfn "$TARGET" "$SITE_ROOT/.current-next"
mv -Tf "$SITE_ROOT/.current-next" "$CURRENT"
systemctl restart "$UNIT"

healthy=0
for _ in $(seq 1 60); do
if curl -fsS "http://127.0.0.1:$PORT/health" >/dev/null 2>&1; then healthy=1; break; fi
sleep 0.5
done

if [[ "$healthy" -ne 1 ]]; then
echo "New release did not answer on :$PORT - rolling back." >&2
if [[ -n "$PREVIOUS" && -d "$PREVIOUS" ]]; then
ln -sfn "$PREVIOUS" "$SITE_ROOT/.current-next"
mv -Tf "$SITE_ROOT/.current-next" "$CURRENT"
systemctl restart "$UNIT"
echo "Rolled back to $PREVIOUS." >&2
fi
systemctl status "$UNIT" --no-pager -l >&2 || true
exit 1
fi

echo "deployed : $SHA"
for path in /health /install.sh /install.ps1 /keepalive/keepalive-install.ps1 /api/releases/linux/latest; do
printf ' %-38s %s\n' "$path" "$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1:$PORT$path")"
done
Comment on lines +83 to +85

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Add /uninstall.ps1 to the post-deploy smoke list.

site/server.mjs line 447 serves /uninstall.ps1, and test/site.mjs treats a 404 there as stranding every Windows installation. The smoke list omits it, so a deploy that breaks that route passes silently.

🔎 Proposed fix
-for path in /health /install.sh /install.ps1 /keepalive/keepalive-install.ps1 /api/releases/linux/latest; do
+for path in /health /install.sh /install.ps1 /uninstall.ps1 /keepalive/keepalive-install.ps1 /api/releases/linux/latest; do
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
for path in /health /install.sh /install.ps1 /keepalive/keepalive-install.ps1 /api/releases/linux/latest; do
printf ' %-38s %s\n' "$path" "$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1:$PORT$path")"
done
for path in /health /install.sh /install.ps1 /uninstall.ps1 /keepalive/keepalive-install.ps1 /api/releases/linux/latest; do
printf ' %-38s %s\n' "$path" "$(curl -s -o /dev/null -w '%{http_code}' "http://127.0.0.1:$PORT$path")"
done
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/deploy-site.sh` around lines 83 - 85, Extend the post-deploy
smoke-test loop in the visible path list to include /uninstall.ps1, ensuring it
is checked alongside the existing installation and health endpoints.