initial relay scaffold
This commit is contained in:
Executable
+175
@@ -0,0 +1,175 @@
|
||||
#!/usr/bin/env bash
|
||||
# Interactive version bump.
|
||||
#
|
||||
# Shows the current version, asks for the new version (with a sensible default:
|
||||
# patch-level bump), and asks for release notes. Then:
|
||||
# 1. Creates startos/versions/v<new>.ts
|
||||
# 2. Updates startos/versions/index.ts (adds import, updates `current:`,
|
||||
# pushes old current into `other:`)
|
||||
#
|
||||
# If the file .release-notes-pending.txt exists in the project root, its
|
||||
# contents are shown as the default release notes (just press Enter to accept).
|
||||
# Drop a note in that file before running this script to pre-fill the
|
||||
# prompt. The file is deleted on a successful bump.
|
||||
#
|
||||
# Flags:
|
||||
# --from-deploy Treat the absence of .release-notes-pending.txt as the
|
||||
# signal that no new work needs to ship — exit 0 without
|
||||
# bumping. Lets `make deploy` always include this step
|
||||
# without forcing a redundant bump when the user (or a
|
||||
# prior run) already bumped.
|
||||
#
|
||||
# Run standalone with `make bump`, or as the first step of `make deploy`.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
FROM_DEPLOY=0
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--from-deploy) FROM_DEPLOY=1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
VERSIONS_DIR="$PROJECT_ROOT/startos/versions"
|
||||
INDEX_FILE="$VERSIONS_DIR/index.ts"
|
||||
PENDING_NOTES_FILE="$PROJECT_ROOT/.release-notes-pending.txt"
|
||||
|
||||
# When invoked from `make deploy`, treat a missing pending-notes file as
|
||||
# "nothing new to ship — current version is already fresh, skip the bump."
|
||||
# Standalone `make bump` always prompts.
|
||||
if [ "$FROM_DEPLOY" = "1" ] && [ ! -f "$PENDING_NOTES_FILE" ]; then
|
||||
echo ""
|
||||
echo " (No .release-notes-pending.txt — current version is already bumped. Skipping.)"
|
||||
echo ""
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- Discover current version ---
|
||||
CURRENT_VAR="$(sed -nE "s/.*current:[[:space:]]*(v_[0-9_]+).*/\1/p" "$INDEX_FILE" | head -1)"
|
||||
if [ -z "$CURRENT_VAR" ]; then
|
||||
echo "X Could not find current version in $INDEX_FILE" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CURRENT_DOT="$(echo "$CURRENT_VAR" | sed 's/^v_//; s/_/./g')"
|
||||
IFS='.' read -r MAJOR MINOR PATCH <<< "$CURRENT_DOT"
|
||||
SUGGESTED="$MAJOR.$MINOR.$((PATCH + 1))"
|
||||
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════════"
|
||||
echo " Bumping version"
|
||||
echo "═══════════════════════════════════════════"
|
||||
echo ""
|
||||
echo " Current: $CURRENT_DOT"
|
||||
echo ""
|
||||
|
||||
# --- Prompt for new version ---
|
||||
read -r -p " New version [$SUGGESTED]: " NEW_VERSION
|
||||
NEW_VERSION="${NEW_VERSION:-$SUGGESTED}"
|
||||
|
||||
if ! [[ "$NEW_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "X Invalid version: '$NEW_VERSION' (expected format: x.y.z, e.g. 0.1.10)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NEW_FILE="$VERSIONS_DIR/v${NEW_VERSION}.ts"
|
||||
if [ -f "$NEW_FILE" ]; then
|
||||
echo "X Version file already exists: $NEW_FILE" >&2
|
||||
echo " (If you want to re-run, delete that file first.)" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
NEW_VAR="v_$(echo "$NEW_VERSION" | tr '.' '_')"
|
||||
|
||||
# --- Prompt for release notes ---
|
||||
# If suggested notes are sitting in .release-notes-pending.txt, show them
|
||||
# as the default. Press Enter to accept, or type something different.
|
||||
SUGGESTED_NOTES=""
|
||||
if [ -f "$PENDING_NOTES_FILE" ]; then
|
||||
# Read the file, trim leading/trailing whitespace, collapse interior newlines
|
||||
# into spaces so it fits the one-line release-notes format.
|
||||
SUGGESTED_NOTES="$(tr '\n' ' ' < "$PENDING_NOTES_FILE" | sed -e 's/[[:space:]]\{1,\}/ /g' -e 's/^ //' -e 's/ $//')"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
if [ -n "$SUGGESTED_NOTES" ]; then
|
||||
echo " Suggested release notes (from .release-notes-pending.txt):"
|
||||
echo " $SUGGESTED_NOTES"
|
||||
echo ""
|
||||
read -r -p " Release notes (Enter to accept, or type new): " RELEASE_NOTES
|
||||
RELEASE_NOTES="${RELEASE_NOTES:-$SUGGESTED_NOTES}"
|
||||
else
|
||||
read -r -p " Release notes (one-liner, what changed in $NEW_VERSION?): " RELEASE_NOTES
|
||||
fi
|
||||
|
||||
if [ -z "$RELEASE_NOTES" ]; then
|
||||
echo "X Release notes are required" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Escape for TypeScript single-quoted string: backslash first, then single quote
|
||||
ESCAPED_NOTES="$(printf '%s' "$RELEASE_NOTES" | sed -e 's/\\/\\\\/g' -e "s/'/\\\\'/g")"
|
||||
|
||||
# Clean up partial state if anything below fails
|
||||
cleanup_on_error() {
|
||||
[ -f "$NEW_FILE" ] && rm -f "$NEW_FILE"
|
||||
[ -f "$INDEX_FILE.tmp" ] && rm -f "$INDEX_FILE.tmp"
|
||||
[ -f "$INDEX_FILE.bak" ] && rm -f "$INDEX_FILE.bak"
|
||||
}
|
||||
trap cleanup_on_error ERR
|
||||
|
||||
# --- 1. Create new version file ---
|
||||
cat > "$NEW_FILE" <<EOF
|
||||
import { VersionInfo } from '@start9labs/start-sdk'
|
||||
|
||||
export const $NEW_VAR = VersionInfo.of({
|
||||
version: '$NEW_VERSION:0',
|
||||
releaseNotes: {
|
||||
en_US: '$ESCAPED_NOTES',
|
||||
},
|
||||
migrations: {
|
||||
up: async ({ effects }) => {},
|
||||
down: async ({ effects }) => {},
|
||||
},
|
||||
})
|
||||
EOF
|
||||
|
||||
# --- 2. Update index.ts ---
|
||||
# Insert `import { v_NEW } from './vNEW'` right after the last existing version
|
||||
# import, so the imports stay contiguous.
|
||||
NEW_IMPORT="import { $NEW_VAR } from './v$NEW_VERSION'"
|
||||
|
||||
awk -v new_import="$NEW_IMPORT" '
|
||||
/^import \{ v_[0-9_]+ \} from/ { last_imp = NR }
|
||||
{ lines[NR] = $0 }
|
||||
END {
|
||||
for (i = 1; i <= NR; i++) {
|
||||
print lines[i]
|
||||
if (i == last_imp) print new_import
|
||||
}
|
||||
}
|
||||
' "$INDEX_FILE" > "$INDEX_FILE.tmp"
|
||||
mv "$INDEX_FILE.tmp" "$INDEX_FILE"
|
||||
|
||||
# Point `current:` at the new version, and prepend the old current into `other:`.
|
||||
# Use -i.bak for macOS/BSD + Linux/GNU sed compatibility.
|
||||
sed -i.bak \
|
||||
-e "s/current: $CURRENT_VAR/current: $NEW_VAR/" \
|
||||
-e "s/other: \[/other: [$CURRENT_VAR, /" \
|
||||
"$INDEX_FILE"
|
||||
rm -f "$INDEX_FILE.bak"
|
||||
|
||||
trap - ERR
|
||||
|
||||
# --- Clean up the pending-notes scratch file now that we've consumed it ---
|
||||
if [ -f "$PENDING_NOTES_FILE" ]; then
|
||||
rm -f "$PENDING_NOTES_FILE"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo " ✓ Created startos/versions/v${NEW_VERSION}.ts"
|
||||
echo " ✓ Wired up in startos/versions/index.ts"
|
||||
echo " ✓ Version: $CURRENT_DOT → $NEW_VERSION"
|
||||
echo ""
|
||||
Executable
+109
@@ -0,0 +1,109 @@
|
||||
#!/usr/bin/env bash
|
||||
# One-shot deploy: upload the built .s9pk to FileBrowser, register it with the
|
||||
# Start9 registry, and trigger a re-index so clients see the new version.
|
||||
#
|
||||
# Config is loaded from, in order:
|
||||
# 1. Environment variables
|
||||
# 2. $PROJECT_ROOT/.deploy.env (gitignored; see .deploy.env.example)
|
||||
#
|
||||
# Required config:
|
||||
# FILEBROWSER_URL — e.g. https://immense-voyage.local:51165
|
||||
# FILEBROWSER_USER — your FileBrowser login
|
||||
# FILEBROWSER_PASS — your FileBrowser password
|
||||
# START9_SERVER — your Start9 server, e.g. https://immense-voyage.local:62185
|
||||
#
|
||||
# Optional config (sensible defaults):
|
||||
# FILEBROWSER_PATH — path on FileBrowser to overwrite. Default: /websites/keysat-registry/recap-relay_x86_64.s9pk
|
||||
# REGISTRY_URL — registry JSON-RPC URL. Default: https://registry.keysat.xyz
|
||||
# REGISTRY_PUBLIC_URL — public .s9pk URL registered with start-cli.
|
||||
# Default: https://files.keysat.xyz/recap-relay_x86_64.s9pk
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
ENV_FILE="$PROJECT_ROOT/.deploy.env"
|
||||
|
||||
if [ -f "$ENV_FILE" ]; then
|
||||
# shellcheck disable=SC1090
|
||||
set -a; source "$ENV_FILE"; set +a
|
||||
fi
|
||||
|
||||
# --- Validate config ---
|
||||
: "${FILEBROWSER_URL:?FILEBROWSER_URL is required (see bin/deploy.sh header)}"
|
||||
: "${FILEBROWSER_USER:?FILEBROWSER_USER is required}"
|
||||
: "${FILEBROWSER_PASS:?FILEBROWSER_PASS is required}"
|
||||
: "${START9_SERVER:?START9_SERVER is required (e.g. https://immense-voyage.local:62185)}"
|
||||
|
||||
FILEBROWSER_PATH="${FILEBROWSER_PATH:-/websites/keysat-registry/recap-relay_x86_64.s9pk}"
|
||||
REGISTRY_URL="${REGISTRY_URL:-https://registry.keysat.xyz}"
|
||||
REGISTRY_PUBLIC_URL="${REGISTRY_PUBLIC_URL:-https://files.keysat.xyz/recap-relay_x86_64.s9pk}"
|
||||
|
||||
S9PK_FILE="$PROJECT_ROOT/recap-relay_x86_64.s9pk"
|
||||
|
||||
if [ ! -f "$S9PK_FILE" ]; then
|
||||
echo "X $S9PK_FILE not found. Run 'make x86' first." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Discover current version from startos/versions ---
|
||||
CURRENT_VAR="$(sed -nE "s/.*current:[[:space:]]*(v_[0-9_]+).*/\1/p" "$PROJECT_ROOT/startos/versions/index.ts" | head -1)"
|
||||
if [ -n "$CURRENT_VAR" ]; then
|
||||
VERSION_DOT="$(echo "$CURRENT_VAR" | sed 's/^v_//; s/_/./g')"
|
||||
VERSION_FILE="$PROJECT_ROOT/startos/versions/v${VERSION_DOT}.ts"
|
||||
CURRENT_VERSION="$(sed -nE "s/.*version:[[:space:]]*'([^']+)'.*/\1/p" "$VERSION_FILE" | head -1)"
|
||||
else
|
||||
CURRENT_VERSION="unknown"
|
||||
fi
|
||||
|
||||
echo "==> Deploying recap-relay $CURRENT_VERSION"
|
||||
echo " source : $S9PK_FILE"
|
||||
echo " upload : $FILEBROWSER_URL$FILEBROWSER_PATH"
|
||||
echo " public : $REGISTRY_PUBLIC_URL"
|
||||
echo " start9 : $START9_SERVER"
|
||||
echo ""
|
||||
|
||||
# FileBrowser is typically on a *.local address with a self-signed cert, so
|
||||
# curl needs -k (--insecure) to connect. Override with FILEBROWSER_CURL_OPTS if
|
||||
# you've set up trust for the Start9 root CA.
|
||||
FB_CURL_OPTS="${FILEBROWSER_CURL_OPTS:--k}"
|
||||
|
||||
# --- 1. Authenticate with FileBrowser ---
|
||||
echo "[1/4] Authenticating with FileBrowser..."
|
||||
LOGIN_BODY="$(printf '{"username":"%s","password":"%s"}' \
|
||||
"$(printf '%s' "$FILEBROWSER_USER" | sed 's/[\\"]/\\&/g')" \
|
||||
"$(printf '%s' "$FILEBROWSER_PASS" | sed 's/[\\"]/\\&/g')")"
|
||||
|
||||
TOKEN="$(curl $FB_CURL_OPTS -fsS -X POST "$FILEBROWSER_URL/api/login" \
|
||||
-H "Content-Type: application/json" \
|
||||
--data-raw "$LOGIN_BODY")" || {
|
||||
echo "X FileBrowser login failed (check URL, username, password)" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
if [ -z "$TOKEN" ]; then
|
||||
echo "X FileBrowser login returned an empty token" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- 2. Upload .s9pk (override existing) ---
|
||||
echo "[2/4] Uploading $(basename "$S9PK_FILE") ($(du -h "$S9PK_FILE" | cut -f1))..."
|
||||
curl $FB_CURL_OPTS -fsS -X POST "$FILEBROWSER_URL/api/resources${FILEBROWSER_PATH}?override=true" \
|
||||
-H "X-Auth: $TOKEN" \
|
||||
-H "Content-Type: application/octet-stream" \
|
||||
--data-binary "@$S9PK_FILE" \
|
||||
-o /dev/null
|
||||
|
||||
# --- 3. Register with Start9 registry (adds manifest + pointer to public URL) ---
|
||||
echo "[3/4] Registering package with registry..."
|
||||
start-cli -r "$START9_SERVER" registry package add "$S9PK_FILE" --url "$REGISTRY_PUBLIC_URL"
|
||||
|
||||
# --- 4. Trigger registry re-index so clients see the new version ---
|
||||
echo "[4/4] Re-indexing registry..."
|
||||
curl -fsS -X POST "$REGISTRY_URL/rpc/v0" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"jsonrpc":"2.0","method":"index","id":1}' \
|
||||
-o /dev/null
|
||||
|
||||
echo ""
|
||||
echo "==> Done. recap-relay $CURRENT_VERSION is live."
|
||||
Reference in New Issue
Block a user