- Linux app id dev.foxyz.starsync, binary starsync; Windows starsync.exe, company foxyz; server starsync-server; Dart package starsync; archives starsync-<ver>-*. - 1.2.x compatibility: watch_together and watch-together-server launchers (Linux) / copies (Windows) in the archive; the updater accepts both names and relaunches the new binary; update.sh/.bat use whichever server exists. - First start copies (never moves) the old support folder and this app's Hive boxes out of ~/Documents into <support>/hive; a marker makes it run once; AppDirs is a port; settings schema version with ordered migrations. - Launcher entry dev.foxyz.starsync.desktop; the old one removed. - Repository name and URLs unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
149 lines
5.8 KiB
Bash
Executable File
149 lines
5.8 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Package the Linux release bundle into a versioned tar.gz and optionally
|
|
# upload it to Discord.
|
|
# Usage: tool/package_linux.sh [--skip-build] [--noupload|--no-upload]
|
|
# Output: dist/starsync-<version>-linux-x64.tar.gz containing one
|
|
# top-level folder starsync-<version>/ with the executable `starsync`, lib/
|
|
# and data/ as built, plus update.sh (runs starsync-server --upgrade) and
|
|
# starsync-server (the dedicated server, `dart compile exe` of
|
|
# packages/server/bin/server.dart, built every run, also with --skip-build;
|
|
# both binaries are stamped with APP_VERSION from the app's pubspec), and
|
|
# the launchers `watch_together` and `watch-together-server` (the names up
|
|
# to 1.2.x: their updater restarts `watch_together`, VPS units run the old
|
|
# server name). The updater strips that top-level folder — keep the layout
|
|
# in sync with packages/core/test/updater_test.dart.
|
|
# Upload: set DISCORD_WEBHOOK_URL in the environment (never commit it).
|
|
# The tarball must stay under Discord's upload limit (25 MB free tier).
|
|
# The upload posts a Components V2 card (flag 1<<15): version header,
|
|
# short git commit, stat codeblock, and the tarball as a File component.
|
|
# Needs: curl, git, python3 (JSON payload building).
|
|
set -euo pipefail
|
|
|
|
SKIP_BUILD=0
|
|
UPLOAD=1
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--skip-build) SKIP_BUILD=1 ;;
|
|
--noupload|--no-upload) UPLOAD=0 ;;
|
|
*) echo "usage: $0 [--skip-build] [--noupload|--no-upload]" >&2; exit 1 ;;
|
|
esac
|
|
done
|
|
|
|
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
APP="$ROOT/apps/desktop"
|
|
NAME="starsync"
|
|
ARCH="x64"
|
|
|
|
# VERSION in the environment overrides it (tool/dev_release.sh).
|
|
VERSION="${VERSION:-$(sed -n 's/^version: \([0-9.]*\).*/\1/p' "$APP/pubspec.yaml")}"
|
|
if [[ -z "$VERSION" ]]; then echo "error: version not found in $APP/pubspec.yaml" >&2; exit 1; fi
|
|
|
|
# The commit the app shows next to a test build's version (About, the
|
|
# Settings tab's tooltip); -dirty with uncommitted changes.
|
|
COMMIT="$(git -C "$ROOT" rev-parse --short HEAD 2>/dev/null || true)"
|
|
if [[ -n "$COMMIT" && -n "$(git -C "$ROOT" status --porcelain --untracked-files=no 2>/dev/null)" ]]; then
|
|
COMMIT="$COMMIT-dirty"
|
|
fi
|
|
|
|
if [[ "$SKIP_BUILD" != "1" ]]; then
|
|
(cd "$APP" && flutter build linux --release --dart-define=APP_VERSION="$VERSION" --dart-define=GIT_COMMIT="$COMMIT")
|
|
fi
|
|
|
|
BUNDLE="$APP/build/linux/$ARCH/release/bundle"
|
|
[[ -d "$BUNDLE" ]] || { echo "error: bundle missing (build first): $BUNDLE" >&2; exit 1; }
|
|
|
|
STAGE="$APP/build/package-stage"
|
|
DIST="$ROOT/dist"
|
|
FOLDER="$NAME-$VERSION"
|
|
TARBALL="$DIST/$FOLDER-linux-$ARCH.tar.gz"
|
|
rm -rf "$STAGE"
|
|
mkdir -p "$STAGE/$FOLDER" "$DIST"
|
|
cp -r "$BUNDLE/." "$STAGE/$FOLDER/"
|
|
for f in update.sh watch_together watch-together-server; do
|
|
install -m 755 "$APP/lib/src/update/bundle/$f" "$STAGE/$FOLDER/$f"
|
|
done
|
|
# Prefer the dart bundled with the Flutter SDK that builds the app.
|
|
DART="dart"
|
|
if FLUTTER="$(command -v flutter)"; then
|
|
CANDIDATE="$(dirname "$(readlink -f "$FLUTTER")")/dart"
|
|
[[ -x "$CANDIDATE" ]] && DART="$CANDIDATE"
|
|
fi
|
|
(cd "$ROOT/packages/server" && "$DART" pub get >/dev/null &&
|
|
"$DART" compile exe --define=APP_VERSION="$VERSION" bin/server.dart -o "$STAGE/$FOLDER/starsync-server")
|
|
tar -czf "$TARBALL" -C "$STAGE" "$FOLDER"
|
|
rm -rf "$STAGE"
|
|
ls -la "$TARBALL"
|
|
|
|
if [[ "$UPLOAD" == "1" ]]; then
|
|
if [[ -z "${DISCORD_WEBHOOK_URL:-}" ]]; then
|
|
echo "warning: DISCORD_WEBHOOK_URL not set — packaged but not uploaded." >&2
|
|
else
|
|
command -v curl >/dev/null || { echo "error: curl not found" >&2; exit 1; }
|
|
command -v python3 >/dev/null || { echo "error: python3 not found" >&2; exit 1; }
|
|
PAYLOAD="$(mktemp)"
|
|
trap 'rm -f "$PAYLOAD"' EXIT
|
|
export PKG_ROOT="$ROOT" PKG_PAYLOAD="$PAYLOAD" PKG_TARBALL="$TARBALL" \
|
|
PKG_FOLDER="$FOLDER" PKG_VERSION="$VERSION" PKG_ARCH="$ARCH"
|
|
python3 <<'EOF'
|
|
import json, os, subprocess
|
|
|
|
root = os.environ['PKG_ROOT']
|
|
out = os.environ['PKG_PAYLOAD']
|
|
tarball = os.environ['PKG_TARBALL']
|
|
fname = os.path.basename(tarball)
|
|
folder = os.environ['PKG_FOLDER']
|
|
ver = os.environ['PKG_VERSION']
|
|
arch = os.environ['PKG_ARCH']
|
|
size_mb = os.path.getsize(tarball) / 1048576
|
|
|
|
def git(*args):
|
|
try:
|
|
p = subprocess.run(['git', '-C', root, *args],
|
|
capture_output=True, text=True, timeout=10)
|
|
return p.stdout.strip()
|
|
except Exception:
|
|
return ''
|
|
|
|
commit = git('log', '-1', '--format=%h %s') or 'uncommitted build'
|
|
stat = git('show', '--stat', '--oneline', '--format=', 'HEAD')
|
|
stat_lines = [l for l in stat.splitlines() if l.strip()][:14]
|
|
rest = len([l for l in stat.splitlines() if l.strip()]) - len(stat_lines)
|
|
if rest > 0:
|
|
stat_lines.append(f'... +{rest} more files')
|
|
block = '```\n' + '\n'.join(stat_lines) + '\n```'
|
|
|
|
payload = {
|
|
'flags': 1 << 15,
|
|
'attachments': [{
|
|
'id': 0,
|
|
'filename': fname,
|
|
'description': f'{folder} linux {arch} release build',
|
|
}],
|
|
'components': [{
|
|
'type': 17,
|
|
'accent_color': 5793266,
|
|
'components': [
|
|
{'type': 10, 'content':
|
|
f'# 📦 Starsync `{ver}`\n'
|
|
f'-# linux · {arch} · release · {size_mb:.1f} MB'},
|
|
{'type': 10, 'content': f'`{commit[:140]}`'},
|
|
{'type': 10, 'content': block[:1500]},
|
|
{'type': 14, 'divider': True, 'spacing': 1},
|
|
{'type': 13, 'file': {'url': f'attachment://{fname}'}},
|
|
],
|
|
}],
|
|
}
|
|
with open(out, 'w') as f:
|
|
json.dump(payload, f)
|
|
EOF
|
|
# Plain (non-application) webhooks ignore `components` unless the
|
|
# with_components query param is set — without it Discord 500s.
|
|
SEP='?'; [[ "$DISCORD_WEBHOOK_URL" == *\?* ]] && SEP='&'
|
|
curl -fsS \
|
|
-F "payload_json=<$PAYLOAD;type=application/json" \
|
|
-F "files[0]=@$TARBALL;type=application/gzip" \
|
|
"${DISCORD_WEBHOOK_URL}${SEP}with_components=true" > /dev/null
|
|
echo "uploaded $FOLDER-linux-$ARCH.tar.gz"
|
|
fi
|
|
fi
|