Files
ozan a81a450e7e feat: monorepo consolidation — merge CLI, bot, admin, team-tool, website, docs, runner, proxy
Merged into tinqs/studio:
- cmd/tinqs-cli/    — tinqs-cli (Go binary, from bot/cli)
- cmd/tea/          — Gitea CLI tool (from tinqs/cli-tea)
- services/bot/     — Bot service (from tinqs-ltd/bot on git.arikigame.com)
- services/admin/   — Admin panel (from tinqs/admin)
- services/team-tool/ — Team Tool (from tinqs/team-tool)
- services/proxy/   — tinqs-proxy (from bot/proxy)
- web/landing/      — tinqs.com website (from tinqs/website)
- web/docs/         — Platform docs (from tinqs/docs)
- web/blog/         — Blog (placeholder)
- runner/           — Ephemeral CI runner (from tinqs/runner)

All source repos will be deleted after verification.
2026-05-22 04:55:50 +00:00

107 lines
3.6 KiB
Bash
Executable File

#!/bin/bash
set -euo pipefail
# generate-appcast.sh — Produce appcast.xml for Sparkle 2.x auto-update.
#
# Usage:
# ./scripts/generate-appcast.sh <signed-app.zip> <version> <edsa-private-key-path> [output-path]
#
# Arguments:
# signed-app.zip Path to the codesigned, zipped .app bundle
# version Semantic version string (e.g. 1.2.0)
# edsa-private-key-path Path to EdDSA private key file (from sparkle/bin/generate_keys)
# output-path Optional output file (default: stdout)
#
# Requirements:
# - Sparkle's sign_update tool on PATH or at ./sparkle/bin/sign_update
#
# Outputs an appcast.xml with one <item> containing EdDSA signature, download URL,
# and file size — ready to upload to S3.
readonly S3_BASE="https://tinqs-cli-releases.s3.eu-west-1.amazonaws.com/releases/darwin"
ZIP_PATH="${1:?Usage: $0 <signed-app.zip> <version> <edsa-private-key-path> [output-path]}"
VERSION="${2:?Usage: $0 <signed-app.zip> <version> <edsa-private-key-path> [output-path]}"
PRIVATE_KEY_PATH="${3:?Usage: $0 <signed-app.zip> <version> <edsa-private-key-path> [output-path]}"
OUTPUT_PATH="${4:-}"
# Validate inputs
if [ ! -f "$ZIP_PATH" ]; then
echo "Error: ZIP file not found: $ZIP_PATH" >&2
exit 1
fi
if [ ! -f "$PRIVATE_KEY_PATH" ]; then
echo "Error: EdDSA private key not found: $PRIVATE_KEY_PATH" >&2
exit 1
fi
# Locate sign_update tool
SIGN_UPDATE=""
if command -v sign_update >/dev/null 2>&1; then
SIGN_UPDATE="sign_update"
elif [ -x "./sparkle/bin/sign_update" ]; then
SIGN_UPDATE="./sparkle/bin/sign_update"
elif [ -x "/usr/local/bin/sign_update" ]; then
SIGN_UPDATE="/usr/local/bin/sign_update"
else
echo "Error: Sparkle sign_update tool not found on PATH or at ./sparkle/bin/sign_update" >&2
exit 1
fi
# Generate EdDSA signature for the zip
SIGNATURE=$("$SIGN_UPDATE" "$ZIP_PATH" --ed-key-file "$PRIVATE_KEY_PATH" 2>/dev/null)
if [ -z "$SIGNATURE" ]; then
echo "Error: sign_update produced empty signature" >&2
exit 1
fi
# Extract the edSignature value (sign_update outputs: sparkle:edSignature="..." length="...")
ED_SIGNATURE=$(echo "$SIGNATURE" | sed -n 's/.*sparkle:edSignature="\([^"]*\)".*/\1/p')
if [ -z "$ED_SIGNATURE" ]; then
# Some versions output just the signature string
ED_SIGNATURE="$SIGNATURE"
fi
# File size in bytes
FILE_SIZE=$(stat -f%z "$ZIP_PATH" 2>/dev/null || stat -c%s "$ZIP_PATH" 2>/dev/null)
# Publication date in RFC 2822 format
PUB_DATE=$(date -R 2>/dev/null || date "+%a, %d %b %Y %H:%M:%S %z")
# Download URL
DOWNLOAD_URL="${S3_BASE}/TinqsTeamTool-${VERSION}.zip"
# Generate appcast XML
APPCAST=$(cat <<XMLEOF
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>Tinqs Team Tool Updates</title>
<link>${S3_BASE}/appcast.xml</link>
<description>Updates for Tinqs Team Tool macOS</description>
<language>en</language>
<item>
<title>Version ${VERSION}</title>
<pubDate>${PUB_DATE}</pubDate>
<sparkle:version>${VERSION}</sparkle:version>
<sparkle:shortVersionString>${VERSION}</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>14.0</sparkle:minimumSystemVersion>
<enclosure
url="${DOWNLOAD_URL}"
sparkle:edSignature="${ED_SIGNATURE}"
length="${FILE_SIZE}"
type="application/octet-stream" />
</item>
</channel>
</rss>
XMLEOF
)
if [ -n "$OUTPUT_PATH" ]; then
echo "$APPCAST" > "$OUTPUT_PATH"
echo "Appcast written to: $OUTPUT_PATH" >&2
else
echo "$APPCAST"
fi