Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 3m27s
The advertised curl URL referenced raw/branch/main, but main has never been created (creating it is rejected by a branch-protection rule that matches the name even with no branch behind it), so the one-command install 404'd. dev is currently the repo's only branch and serves the script fine now that the repo is public — verified 200, with all three v0.1.0 release assets resolving and the AppImage downloading in full. Flagged in the header to move back to main once that branch exists, so the public install command stops tracking day-to-day work. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SreJkbxB4gx8pPsu8QbLPi
114 lines
5.3 KiB
Bash
Executable File
114 lines
5.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Publish the built desktop bundles as assets on a Fabled-Git (Forgejo) Release.
|
|
#
|
|
# WHY: CI Actions artifacts are ephemeral, per-run, and auth-gated — useless as a
|
|
# distribution/fetch target. The install script (install.sh) and the in-app
|
|
# updater both need a STABLE, versioned URL. A Release attached to the pushed
|
|
# `v*` tag is that target: `/releases/latest` always points at the newest one,
|
|
# and each asset has a permanent browser_download_url.
|
|
#
|
|
# WHEN: CI-only, and ONLY on a `v*` tag build (the workflow gates this step with
|
|
# `if: startsWith(github.ref, 'refs/tags/v')`). Cutting the tag is the operator's
|
|
# action (rule 2) — this script never creates a tag, it only publishes a Release
|
|
# for a tag that already exists.
|
|
#
|
|
# The build + de-bundle steps run first; this consumes their output:
|
|
# desktop/src-tauri/target/release/bundle/appimage/*.AppImage (de-bundled)
|
|
# desktop/src-tauri/target/release/bundle/deb/*.deb
|
|
# desktop/src-tauri/target/release/bundle/arch/*.pkg.tar.* (prebuilt pacman)
|
|
#
|
|
# Instance-agnostic: server + repo come from the runner's github.* context
|
|
# (Forgejo populates them for compatibility), so nothing is hardcoded to one host.
|
|
#
|
|
# Idempotent: re-running for the same tag reuses the existing Release and
|
|
# replaces same-named assets, so a re-run (or workflow_dispatch retry) is safe.
|
|
set -euo pipefail
|
|
|
|
: "${GITHUB_TOKEN:?GITHUB_TOKEN is required (runner-injected; needs contents:write)}"
|
|
: "${GITHUB_SERVER_URL:?GITHUB_SERVER_URL is required}"
|
|
: "${GITHUB_REPOSITORY:?GITHUB_REPOSITORY is required (owner/repo)}"
|
|
: "${GITHUB_REF_NAME:?GITHUB_REF_NAME is required (the tag, e.g. v0.1.0)}"
|
|
|
|
API="$GITHUB_SERVER_URL/api/v1/repos/$GITHUB_REPOSITORY"
|
|
TAG="$GITHUB_REF_NAME"
|
|
AUTH=(-H "Authorization: token $GITHUB_TOKEN")
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
BUNDLE_ROOT="$REPO_ROOT/desktop/src-tauri/target/release/bundle"
|
|
|
|
# --- collect the assets to upload -------------------------------------------
|
|
shopt -s nullglob
|
|
ASSETS=(
|
|
"$BUNDLE_ROOT"/appimage/*.AppImage
|
|
"$BUNDLE_ROOT"/deb/*.deb
|
|
"$BUNDLE_ROOT"/arch/*.pkg.tar.*
|
|
)
|
|
if [ ${#ASSETS[@]} -eq 0 ]; then
|
|
echo "ERROR: no bundles under $BUNDLE_ROOT — did the tauri build run?" >&2
|
|
exit 1
|
|
fi
|
|
echo "==> Publishing release $TAG with ${#ASSETS[@]} asset(s):"
|
|
for a in "${ASSETS[@]}"; do echo " $(basename "$a") ($(du -h "$a" | cut -f1))"; done
|
|
|
|
# curl wrapper that returns the response body on stdout and fails the script on
|
|
# an HTTP >=400 that we didn't explicitly allow (via ALLOW_CODES).
|
|
api() {
|
|
local method="$1" url="$2"; shift 2
|
|
local out code
|
|
out="$(curl -sS -X "$method" "${AUTH[@]}" -w $'\n%{http_code}' "$url" "$@")"
|
|
code="${out##*$'\n'}"
|
|
out="${out%$'\n'*}"
|
|
if [ "$code" -ge 400 ] && [[ " ${ALLOW_CODES:-} " != *" $code "* ]]; then
|
|
echo "ERROR: $method $url -> HTTP $code" >&2
|
|
echo "$out" >&2
|
|
return 1
|
|
fi
|
|
printf '%s' "$out"
|
|
}
|
|
|
|
# First integer value of a "id": <n> pair — the release id is the first "id" in
|
|
# the release object. Avoids a jq dependency (not guaranteed in the CI image).
|
|
first_id() { grep -oE '"id"[[:space:]]*:[[:space:]]*[0-9]+' | head -1 | grep -oE '[0-9]+'; }
|
|
|
|
# --- create (or reuse) the release for the tag ------------------------------
|
|
echo "==> Creating release for $TAG"
|
|
BODY=$(cat <<JSON
|
|
{"tag_name":"$TAG","name":"ThoughtSync $TAG","draft":false,"prerelease":false,
|
|
"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\`\`\`"}
|
|
JSON
|
|
)
|
|
# 409 = a release for this tag already exists (re-run) — fall through to lookup.
|
|
release="$(ALLOW_CODES=409 api POST "$API/releases" -H "Content-Type: application/json" -d "$BODY")"
|
|
RELEASE_ID="$(printf '%s' "$release" | first_id || true)"
|
|
|
|
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)"
|
|
fi
|
|
[ -n "${RELEASE_ID:-}" ] || { echo "ERROR: could not resolve release id" >&2; exit 1; }
|
|
echo " release id = $RELEASE_ID"
|
|
|
|
# Existing assets (name -> id), so a re-run replaces rather than duplicates.
|
|
existing="$(api GET "$API/releases/$RELEASE_ID/assets")"
|
|
|
|
# --- upload each asset ------------------------------------------------------
|
|
for asset in "${ASSETS[@]}"; do
|
|
name="$(basename "$asset")"
|
|
# If an asset with this name already exists, delete it first (Forgejo rejects
|
|
# a duplicate name). Match the "id" that precedes this asset's "name".
|
|
old_id="$(printf '%s' "$existing" \
|
|
| grep -oE "\"id\"[[:space:]]*:[[:space:]]*[0-9]+[^}]*\"name\"[[:space:]]*:[[:space:]]*\"$name\"" \
|
|
| first_id || true)"
|
|
if [ -n "${old_id:-}" ]; then
|
|
echo "==> Replacing existing asset $name (id $old_id)"
|
|
api DELETE "$API/releases/$RELEASE_ID/assets/$old_id" >/dev/null
|
|
fi
|
|
echo "==> Uploading $name"
|
|
api POST "$API/releases/$RELEASE_ID/assets?name=$name" -F "attachment=@$asset" >/dev/null
|
|
done
|
|
|
|
echo "==> Done. Release $TAG published with $(printf '%s\n' "${ASSETS[@]##*/}" | tr '\n' ' ')"
|