fix: use tea CLI for macOS release upload + test landing.js version

release-mac.sh get_token() could not read tea's OAuth token (stored
encrypted in the keychain, not config.yml), so it fell back to a stale
git-credential token and 401'd on upload. Replace the curl+token upload
with `tea release create` / `tea releases assets create`, which carry
and refresh the OAuth token automatically.

Add a docs-coverage assertion that landing.js platform download links
point at the current version, so the manual version bump cannot drift.
This commit is contained in:
2026-09-06 13:30:16 +08:00
parent bdf2bb543b
commit c461e8177c
2 changed files with 25 additions and 58 deletions
+4
View File
@@ -3,6 +3,7 @@ import { describe, it, expect } from "vitest";
// test free of a `node:fs` dependency so `tsc` (bun run build) stays clean. // test free of a `node:fs` dependency so `tsc` (bun run build) stays clean.
import agents from "../../../AGENTS.md?raw"; import agents from "../../../AGENTS.md?raw";
import readme from "../../../README.md?raw"; import readme from "../../../README.md?raw";
import landing from "../../../www/public/landing.js?raw";
describe("v0.7.15 docs coverage", () => { describe("v0.7.15 docs coverage", () => {
it("AGENTS.md marks inline cell editing complete", () => { it("AGENTS.md marks inline cell editing complete", () => {
@@ -69,4 +70,7 @@ describe("v0.7.15 docs coverage", () => {
expect(readme).toContain("Gridline_0.7.15_aarch64.dmg"); expect(readme).toContain("Gridline_0.7.15_aarch64.dmg");
expect(readme).toContain("Gridline-0.7.15-1.x86_64.rpm"); expect(readme).toContain("Gridline-0.7.15-1.x86_64.rpm");
}); });
it("landing.js platform download links point to v0.7.15", () => {
expect(landing).toContain('const version = "0.7.15"');
});
}); });
+21 -58
View File
@@ -7,13 +7,12 @@
# #
# Usage: # Usage:
# TAG=v0.7.11 ./scripts/release-mac.sh # TAG=v0.7.11 ./scripts/release-mac.sh
# (optionally set GITEA_TOKEN env var to override token lookup)
# #
# The release is keyed by tag. The Linux/Windows job creates it on the first # The release is keyed by tag. The Linux/Windows job creates it on the first
# tag push; this script finds it (creating it only if it somehow doesn't exist) # tag push; this script finds it (creating it only if it somehow doesn't exist)
# and attaches the two DMGs: Gridline_<ver>_aarch64.dmg and Gridline_<ver>_x64.dmg # and attaches the two DMGs: Gridline_<ver>_aarch64.dmg and Gridline_<ver>_x64.dmg
# #
# Token: reads $GITEA_TOKEN, else tries the tea CLI config, else prompts. # Auth: uses the `tea` CLI (OAuth token, auto-refreshed).
set -euo pipefail set -euo pipefail
@@ -28,40 +27,15 @@ if [ -z "$TAG" ]; then
exit 1 exit 1
fi fi
# ---- resolve auth token ---------------------------------------------------- # ---- resolve auth (tea CLI) ------------------------------------------------
get_token() { # The `tea` CLI carries the OAuth token and refreshes it automatically, so the
if [ -n "${GITEA_TOKEN:-}" ]; then # release upload below uses `tea` rather than a raw curl + token. (The git
echo "$GITEA_TOKEN"; return # credential store can hold a stale access token and 401.)
fi if ! command -v tea >/dev/null 2>&1; then
# Try tea's stored credentials if available. echo "error: tea CLI not found (needed to upload release assets)" >&2
if command -v tea >/dev/null 2>&1; then echo " install it: https://gitea.com/gitea/tea" >&2
# tea stores its token in a config under the platform app-support dir.
local cfg
cfg="$(find "$HOME/Library/Application Support" "$HOME/.config" \
-maxdepth 2 -name 'config.yml' -path '*tea*' 2>/dev/null | head -1 || true)"
if [ -n "$cfg" ]; then
local tok
tok="$(sed -n 's/.*token:[" ]*\([^" ]*\).*/\1/p' "$cfg" 2>/dev/null | head -1 || true)"
if [ -n "$tok" ]; then echo "$tok"; return; fi
fi
fi
# Fall back to the git credential store: tea's OAuth login stores an access
# token as the password for every push to this remote, and Gitea accepts it
# for API auth (Authorization: token <access_token>).
local host cred
host="${GITEA_SERVER#*://}"
cred="$(printf 'protocol=https\nhost=%s\n\n' "$host" \
| git credential fill 2>/dev/null | sed -n 's/^password=//p' | head -1 || true)"
if [ -n "$cred" ]; then echo "$cred"; return; fi
# Fail fast — continuing without a token fails only at the upload step,
# after the whole build has run.
echo "error: no Gitea token found" >&2
echo " set GITEA_TOKEN, or run 'tea login' / 'git push' once so the" >&2
echo " credential store has an entry for $host" >&2
exit 1 exit 1
} fi
GITEA_TOKEN="$(get_token)"
# ---- macOS signing + notarization ----------------------------------------- # ---- macOS signing + notarization -----------------------------------------
# Requires a "Developer ID Application" certificate in the login keychain and # Requires a "Developer ID Application" certificate in the login keychain and
@@ -224,32 +198,21 @@ for APP in \
done done
# ---- create/ensure release + upload DMGs ----------------------------------- # ---- create/ensure release + upload DMGs -----------------------------------
API="${GITEA_SERVER}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}" # Use `tea` for release management — it handles OAuth token refresh, unlike a
AUTH="Authorization: token ${GITEA_TOKEN}" # raw curl with a token from the git credential store (which can 401).
cd "${WORKSPACE}"
echo ">> Ensuring release ${TAG} exists..." echo ">> Ensuring release ${TAG} exists..."
REL_ID=$(curl -fsS -H "$AUTH" "${API}/releases/tags/${TAG}" \ if ! tea release list -o json 2>/dev/null | grep -q "\"${TAG}\""; then
| python3 -c "import sys,json;print(json.load(sys.stdin).get('id',''))" 2>/dev/null || true) tea release create --tag "${TAG}" --title "Gridline ${VERSION}" \
if [ -z "$REL_ID" ]; then --note "Gridline ${VERSION} — macOS (built manually)." --draft
BODY="Gridline ${VERSION} — macOS (built manually)." else
REL_ID=$(curl -fsS -X POST -H "$AUTH" -H "Content-Type: application/json" \ echo ">> Release ${TAG} already exists."
-d "{\"tag_name\":\"${TAG}\",\"name\":\"Gridline ${VERSION}\",\"body\":\"${BODY}\",\"draft\":true}" \
"${API}/releases" \
| python3 -c "import sys,json;print(json.load(sys.stdin)['id'])")
fi fi
upload() { echo ">> Uploading macOS DMGs..."
local file="$1" tea releases assets create "${TAG}" \
[ -f "$file" ] || { echo "missing $file" >&2; exit 1; } "${BUNDLE_ARM}/dmg/Gridline_${VERSION}_aarch64.dmg" \
local name "${BUNDLE_INTEL}/dmg/Gridline_${VERSION}_x64.dmg"
name=$(basename "$file")
echo ">> uploading $name"
curl -fsS -X POST -H "$AUTH" -H "Content-Type: application/octet-stream" \
--data-binary "@$file" \
"${API}/releases/${REL_ID}/assets?name=${name}"
}
upload "${BUNDLE_ARM}/dmg/Gridline_${VERSION}_aarch64.dmg"
upload "${BUNDLE_INTEL}/dmg/Gridline_${VERSION}_x64.dmg"
echo "Done. Release: ${GITEA_SERVER}/${REPO_OWNER}/${REPO_NAME}/releases/tag/${TAG}" echo "Done. Release: ${GITEA_SERVER}/${REPO_OWNER}/${REPO_NAME}/releases/tag/${TAG}"