M12 — the Android client, end to end #2
@@ -15,11 +15,18 @@ Easiest — the one-command installer picks this package automatically on any
|
||||
pacman system:
|
||||
|
||||
```sh
|
||||
curl -fsSL https://git.fabledsword.com/bvandeusen/thoughtsync/raw/branch/main/desktop/packaging/install.sh | sh
|
||||
curl -fsSL https://git.fabledsword.com/bvandeusen/thoughtsync/raw/branch/dev/desktop/packaging/install.sh | sh
|
||||
```
|
||||
|
||||
That installs the newest tagged release. To follow the rolling development
|
||||
channel instead, pass the flag through the pipe:
|
||||
|
||||
```sh
|
||||
curl -fsSL https://git.fabledsword.com/bvandeusen/thoughtsync/raw/branch/dev/desktop/packaging/install.sh | sh -s -- --channel dev
|
||||
```
|
||||
|
||||
Or grab the `.pkg.tar.*` from the
|
||||
[latest release](https://git.fabledsword.com/bvandeusen/thoughtsync/releases/latest)
|
||||
[releases page](https://git.fabledsword.com/bvandeusen/thoughtsync/releases)
|
||||
and install it directly:
|
||||
|
||||
```sh
|
||||
|
||||
+106
-17
@@ -4,12 +4,18 @@
|
||||
#
|
||||
# curl -fsSL https://git.fabledsword.com/bvandeusen/thoughtsync/raw/branch/dev/desktop/packaging/install.sh | sh
|
||||
#
|
||||
# Points at `dev` because that is currently the repo's only branch — `main` does
|
||||
# not exist yet, so a main URL 404s. Move this to `main` once that branch is
|
||||
# created, so the public install command stops tracking day-to-day work.
|
||||
# Two channels, the SAME two the app's own updater offers (src-tauri/src/update.rs):
|
||||
# stable (default) — the newest tagged v* release.
|
||||
# dev — the rolling build from every green push to `dev`.
|
||||
# Pick one with `--channel dev` or `TS_CHANNEL=dev`. Through a pipe the options go
|
||||
# after a `--`: curl -fsSL <url> | sh -s -- --channel dev
|
||||
#
|
||||
# Fetches the LATEST published release for this machine's architecture and
|
||||
# installs it, ending with a working app + menu entry. Native-first:
|
||||
# Served from `dev` rather than `main`: `main` exists but trails day-to-day work by
|
||||
# a long way, so the copy there would install an older script. Move the documented
|
||||
# URL to `main` after a dev→main merge lands, not before.
|
||||
#
|
||||
# Fetches the LATEST published release on the chosen channel for this machine's
|
||||
# architecture and installs it, ending with a working app + menu entry. Native-first:
|
||||
# * Arch/CachyOS (pacman) -> the native .pkg.tar.zst (system libs; needs sudo).
|
||||
# * Debian/Ubuntu (dpkg+apt) -> the native .deb (system libs; needs sudo).
|
||||
# * everything else (Fedora/openSUSE/…) -> the de-bundled AppImage,
|
||||
@@ -29,6 +35,38 @@ say() { printf '==> %s\n' "$1"; }
|
||||
die() { printf 'error: %s\n' "$1" >&2; exit 1; }
|
||||
have() { command -v "$1" >/dev/null 2>&1; }
|
||||
|
||||
usage() {
|
||||
cat <<'USAGE'
|
||||
ThoughtSync desktop installer.
|
||||
|
||||
install.sh [--channel stable|dev]
|
||||
|
||||
--channel stable newest tagged release (default)
|
||||
--channel dev rolling build from the latest green push to `dev`
|
||||
-h, --help this text
|
||||
|
||||
The channel can also come from TS_CHANNEL. Through a pipe, pass options after
|
||||
`--`: curl -fsSL <url> | sh -s -- --channel dev
|
||||
USAGE
|
||||
}
|
||||
|
||||
# --- channel ----------------------------------------------------------------
|
||||
channel="${TS_CHANNEL:-stable}"
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--channel)
|
||||
[ $# -ge 2 ] || die "--channel needs a value (stable or dev)."
|
||||
channel="$2"; shift 2 ;;
|
||||
--channel=*) channel="${1#*=}"; shift ;;
|
||||
-h | --help) usage; exit 0 ;;
|
||||
*) die "unknown option: $1 (try --help)" ;;
|
||||
esac
|
||||
done
|
||||
case "$channel" in
|
||||
stable | dev) : ;;
|
||||
*) die "unknown channel '$channel' — expected stable or dev." ;;
|
||||
esac
|
||||
|
||||
have curl || die "curl is required."
|
||||
|
||||
# --- architecture gate ------------------------------------------------------
|
||||
@@ -41,20 +79,51 @@ case "$arch" in
|
||||
*) die "ThoughtSync ships x86_64 Linux builds only right now (this machine: $arch)." ;;
|
||||
esac
|
||||
|
||||
# --- resolve the latest release ---------------------------------------------
|
||||
say "Finding the latest ThoughtSync release…"
|
||||
json="$(curl -fsSL "$API/releases/latest" 2>/dev/null)" || die \
|
||||
"no published release found at $INSTANCE/$REPO/releases — the maintainer publishes one by pushing a v* tag."
|
||||
# --- resolve the release for this channel -----------------------------------
|
||||
say "Finding the latest ThoughtSync build on the $channel channel…"
|
||||
|
||||
# Pull asset URLs straight out of the release JSON (no jq): the only
|
||||
# .AppImage/.deb URLs present are the asset download links.
|
||||
appimage_url="$(printf '%s' "$json" | grep -oE 'https?://[^"]+\.AppImage' | head -1 || true)"
|
||||
deb_url="$(printf '%s' "$json" | grep -oE 'https?://[^"]+\.deb' | head -1 || true)"
|
||||
pkg_url="$(printf '%s' "$json" | grep -oE 'https?://[^"]+\.pkg\.tar\.[a-z]+' | head -1 || true)"
|
||||
if [ "$channel" = "dev" ]; then
|
||||
# A release whose tag never moves and whose assets are pruned to the current
|
||||
# build — so the tag alone always names the newest dev build.
|
||||
json="$(curl -fsSL "$API/releases/tags/dev" 2>/dev/null)" ||
|
||||
die "the dev channel has nothing published yet."
|
||||
else
|
||||
# Ask the stable channel's own manifest which version is current, then install
|
||||
# THAT release. This is the same file the in-app updater reads, so the installer
|
||||
# and the updater can never disagree about what `stable` means.
|
||||
#
|
||||
# Not `/releases/latest`: that returns the newest non-prerelease release by date,
|
||||
# and the `stable` pointer release (manifest only, no bundles — see
|
||||
# write-manifest.sh) is itself a non-prerelease created moments after the
|
||||
# versioned one. It would win, and it carries nothing installable.
|
||||
manifest="$(curl -fsSL "$INSTANCE/$REPO/releases/download/stable/latest.json" 2>/dev/null || true)"
|
||||
stable_version="$(printf '%s' "$manifest" |
|
||||
grep -oE '"version"[[:space:]]*:[[:space:]]*"[^"]+"' | head -1 |
|
||||
sed -E 's/.*"([^"]+)"$/\1/')"
|
||||
if [ -n "$stable_version" ]; then
|
||||
json="$(curl -fsSL "$API/releases/tags/v$stable_version" 2>/dev/null)" ||
|
||||
die "the stable channel names $stable_version, but there is no v$stable_version release to install."
|
||||
else
|
||||
# No stable pointer yet — the channel predates the updater. Fall back to the
|
||||
# newest non-prerelease release, which is what stable meant before there was
|
||||
# a manifest to ask.
|
||||
json="$(curl -fsSL "$API/releases/latest" 2>/dev/null)" ||
|
||||
die "no stable release published yet — try --channel dev, or ask the maintainer to tag one."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Pull asset URLs straight out of the release JSON (no jq). Anchored on the closing
|
||||
# quote so a `…AppImage.sig` URL can't be truncated into a match of its own.
|
||||
asset_url() {
|
||||
printf '%s' "$json" | grep -oE "https?://[^\"]+$1\"" | head -1 | tr -d '"'
|
||||
}
|
||||
appimage_url="$(asset_url '\.AppImage')"
|
||||
deb_url="$(asset_url '\.deb')"
|
||||
pkg_url="$(asset_url '\.pkg\.tar\.[a-z]+')"
|
||||
version="$(printf '%s' "$json" | grep -oE '"tag_name":"[^"]+"' | head -1 | sed -E 's/.*:"([^"]+)".*/\1/')"
|
||||
[ -n "$appimage_url" ] || [ -n "$deb_url" ] || [ -n "$pkg_url" ] ||
|
||||
die "the latest release has no installable Linux asset."
|
||||
say "Latest release: ${version:-unknown}"
|
||||
die "the $channel release (${version:-unknown}) has no installable Linux asset."
|
||||
say "Installing ${version:-unknown} from the $channel channel"
|
||||
|
||||
tmp="$(mktemp -d)"
|
||||
trap 'rm -rf "$tmp"' EXIT INT TERM
|
||||
@@ -69,6 +138,18 @@ need_root() {
|
||||
say "Installing (you may be prompted for your password)…"
|
||||
}
|
||||
|
||||
# Both native paths are package-manager-owned, so the app cannot replace itself
|
||||
# in place (update.rs refuses, by design). Say so at the end of those paths rather
|
||||
# than letting someone discover it from a greyed-out button.
|
||||
native_update_note() {
|
||||
printf ' A package-manager install can'\''t update itself in-app.\n'
|
||||
if [ "$channel" = "dev" ]; then
|
||||
printf ' Re-run this script with --channel dev to move to a newer dev build.\n'
|
||||
else
|
||||
printf ' Re-run this script to move to a newer release.\n'
|
||||
fi
|
||||
}
|
||||
|
||||
# --- native pacman path (Arch/CachyOS/Manjaro) ------------------------------
|
||||
# Preferred over the AppImage on Arch: pacman pulls webkit2gtk-4.1 itself and the
|
||||
# app then runs against the host graphics stack, which is what keeps the
|
||||
@@ -83,6 +164,7 @@ if have pacman && [ -n "$pkg_url" ]; then
|
||||
need_root
|
||||
$sudo pacman -U --noconfirm "$pkg_file"
|
||||
say "Done. Launch ThoughtSync from your application menu, or run thoughtsync."
|
||||
native_update_note
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -97,6 +179,7 @@ if have dpkg && have apt-get && [ -n "$deb_url" ]; then
|
||||
$sudo apt-get install -y "$tmp/thoughtsync.deb" ||
|
||||
{ $sudo dpkg -i "$tmp/thoughtsync.deb" || true; $sudo apt-get -f install -y; }
|
||||
say "Done. Launch ThoughtSync from your application menu."
|
||||
native_update_note
|
||||
exit 0
|
||||
fi
|
||||
|
||||
@@ -105,7 +188,7 @@ fi
|
||||
# own self-integration uses (src/integration.rs) — so the running app sees
|
||||
# itself already installed and never makes a second copy or menu entry.
|
||||
say "Installing the de-bundled AppImage (user-local, no sudo)"
|
||||
[ -n "$appimage_url" ] || die "no AppImage asset on the latest release."
|
||||
[ -n "$appimage_url" ] || die "the $channel release (${version:-unknown}) has no AppImage asset."
|
||||
|
||||
apps_dir="$HOME/Applications"
|
||||
dest="$apps_dir/ThoughtSync.AppImage"
|
||||
@@ -153,3 +236,9 @@ ln -sf "$dest" "$HOME/.local/bin/thoughtsync"
|
||||
say "Installed to $dest"
|
||||
printf ' Launch it from your application menu, or run \033[1mthoughtsync\033[0m'
|
||||
printf ' (if ~/.local/bin is on your PATH).\n'
|
||||
# The AppImage CAN update itself, but the app's own channel is a separate,
|
||||
# stable-by-default setting — installing from dev here does not move it.
|
||||
if [ "$channel" = "dev" ]; then
|
||||
printf ' You installed from the \033[1mdev\033[0m channel — set the app to match in\n'
|
||||
printf ' Sync → App updates → Development, or in-app updates will follow stable.\n'
|
||||
fi
|
||||
|
||||
@@ -94,10 +94,22 @@ api() {
|
||||
first_id() { grep -oE '"id"[[:space:]]*:[[:space:]]*[0-9]+' | head -1 | grep -oE '[0-9]+'; }
|
||||
|
||||
# --- create (or reuse) the release for the tag ------------------------------
|
||||
# The install command printed on a release has to install THAT release's channel.
|
||||
# install.sh defaults to stable, so the rolling dev release must opt in explicitly
|
||||
# — otherwise someone following the instructions here lands on a tagged build and
|
||||
# wonders why the version they were sent isn't what they got.
|
||||
if [ "$TAG" = "dev" ]; then
|
||||
INSTALL_TAIL='sh -s -- --channel dev'
|
||||
CHANNEL_NOTE='\n\nThis is the rolling **dev** channel: republished on every green push to \`dev\`, and pruned to the current build.'
|
||||
else
|
||||
INSTALL_TAIL='sh'
|
||||
CHANNEL_NOTE=''
|
||||
fi
|
||||
|
||||
echo "==> Creating release for $TAG"
|
||||
BODY=$(cat <<JSON
|
||||
{"tag_name":"$TAG","name":"ThoughtSync $TAG","draft":false,"prerelease":$RELEASE_PRERELEASE,
|
||||
"body":"ThoughtSync desktop $TAG.\n\n- **Debian / Ubuntu** — native \`.deb\`\n- **Arch / CachyOS** — native \`.pkg.tar.*\`\n- **everything else** — \`.AppImage\` (de-bundled graphics: renders on any GPU/Wayland setup)\n\nInstall / update — picks the right one for your system:\n\`\`\`\ncurl -fsSL $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/raw/branch/dev/desktop/packaging/install.sh | sh\n\`\`\`"}
|
||||
"body":"ThoughtSync desktop $TAG.\n\n- **Debian / Ubuntu** — native \`.deb\`\n- **Arch / CachyOS** — native \`.pkg.tar.*\`\n- **everything else** — \`.AppImage\` (de-bundled graphics: renders on any GPU/Wayland setup)\n\nInstall / update — picks the right one for your system:\n\`\`\`\ncurl -fsSL $GITHUB_SERVER_URL/$GITHUB_REPOSITORY/raw/branch/dev/desktop/packaging/install.sh | $INSTALL_TAIL\n\`\`\`$CHANNEL_NOTE"}
|
||||
JSON
|
||||
)
|
||||
# 409 = a release for this tag already exists (re-run) — fall through to lookup.
|
||||
@@ -108,6 +120,11 @@ if [ -z "${RELEASE_ID:-}" ]; then
|
||||
echo " release exists; fetching it by tag"
|
||||
release="$(api GET "$API/releases/tags/$TAG")"
|
||||
RELEASE_ID="$(printf '%s' "$release" | first_id)"
|
||||
# And refresh its description. A fixed-tag release (dev, and any re-run) keeps
|
||||
# whatever text the FIRST build wrote — including the install command. A stale
|
||||
# one sends people to the wrong channel, silently.
|
||||
echo " refreshing its description"
|
||||
api PATCH "$API/releases/$RELEASE_ID" -H "Content-Type: application/json" -d "$BODY" >/dev/null
|
||||
fi
|
||||
[ -n "${RELEASE_ID:-}" ] || { echo "ERROR: could not resolve release id" >&2; exit 1; }
|
||||
echo " release id = $RELEASE_ID"
|
||||
|
||||
Reference in New Issue
Block a user