build: standardize browser GitHub releases

This commit is contained in:
mirivlad 2026-07-13 05:02:04 +08:00
parent 057b63a946
commit 4dd87dc8cc
5 changed files with 72 additions and 19 deletions

View File

@ -55,21 +55,29 @@ Firefox signing uses `web-ext` and AMO credentials from an env file. The script
requires `WEB_EXT_API_PROXY`; AMO upload and approval polling run through that requires `WEB_EXT_API_PROXY`; AMO upload and approval polling run through that
proxy. proxy.
Create the signed XPI and publish it, together with `updates.json`, as the Create the signed XPI locally, without publishing it:
current GitHub Release:
```bash ```bash
VERSTAK_BROWSER_ENV=/path/to/.env npm run publish:firefox VERSTAK_BROWSER_ENV=/path/to/.env npm run release:firefox
``` ```
The first invocation publishes tag `v2.0.3` and bootstraps the Publish the signed XPI and `updates.json` as the current GitHub Release:
`releases/latest/download/updates.json` endpoint. Re-running the command
replaces those two release assets for the same tag.
To sign and prepare release files locally without changing GitHub:
```bash ```bash
VERSTAK_BROWSER_ENV=/home/mirivlad/git/verstak/.env npm run release:firefox VERSTAK_BROWSER_ENV=/path/to/.env npm run publish:github
```
The publisher reads the version from `package.json`. It requires an
authenticated GitHub CLI, a clean local `main` equal to `origin/main`, and a
tag pointing at that commit. It creates and pushes the tag if needed, then
creates or updates the GitHub Release. Re-running it for the same tag replaces
the XPI and `updates.json` assets. `npm run publish:firefox` remains as a
compatible alias for the same Firefox publishing flow.
For an explicit version check, pass the current tag after `--`:
```bash
VERSTAK_BROWSER_ENV=/path/to/.env npm run publish:github -- v2.0.3
``` ```
Release output: Release output:

View File

@ -10,6 +10,7 @@
"sign:firefox": "./scripts/sign-firefox-xpi.sh", "sign:firefox": "./scripts/sign-firefox-xpi.sh",
"release:firefox": "./scripts/release-firefox-xpi.sh", "release:firefox": "./scripts/release-firefox-xpi.sh",
"publish:firefox": "./scripts/publish-firefox-github-release.sh", "publish:firefox": "./scripts/publish-firefox-github-release.sh",
"publish:github": "./scripts/publish-github-release.sh",
"release:package": "./scripts/package-release.sh" "release:package": "./scripts/package-release.sh"
}, },
"devDependencies": { "devDependencies": {

View File

@ -7,13 +7,29 @@ cd "$ROOT_DIR"
REPOSITORY="mirivlad/verstak-browser-extension" REPOSITORY="mirivlad/verstak-browser-extension"
SOURCE_DIR="${VERSTAK_FIREFOX_SOURCE_DIR:-dist/firefox}" SOURCE_DIR="${VERSTAK_FIREFOX_SOURCE_DIR:-dist/firefox}"
RELEASE_DIR="${VERSTAK_FIREFOX_RELEASE_DIR:-release/firefox}" RELEASE_DIR="${VERSTAK_FIREFOX_RELEASE_DIR:-release/firefox}"
GIT_BIN="${GIT_BIN:-git}"
GH_BIN="${GH_BIN:-gh}"
if ! command -v gh >/dev/null; then if ! command -v "$GH_BIN" >/dev/null; then
echo "ERROR: gh CLI is required to publish a GitHub Release" >&2 echo "ERROR: gh CLI is required to publish a GitHub Release" >&2
exit 1 exit 1
fi fi
if [[ "$("$GIT_BIN" branch --show-current)" != "main" ]]; then
echo "ERROR: GitHub releases must be published from main" >&2
exit 1
fi
if [[ -n "$("$GIT_BIN" status --porcelain)" ]]; then
echo "ERROR: working tree must be clean before publishing a release" >&2
exit 1
fi
gh auth status "$GH_BIN" auth status
"$GIT_BIN" fetch origin main --tags
HEAD="$("$GIT_BIN" rev-parse HEAD)"
if [[ "$HEAD" != "$("$GIT_BIN" rev-parse origin/main)" ]]; then
echo "ERROR: local main must match origin/main before publishing a release" >&2
exit 1
fi
./scripts/release-firefox-xpi.sh ./scripts/release-firefox-xpi.sh
VERSION="$(node -e "console.log(require('./${SOURCE_DIR}/manifest.json').version)")" VERSION="$(node -e "console.log(require('./${SOURCE_DIR}/manifest.json').version)")"
@ -28,16 +44,26 @@ for artifact in "$XPI" "$UPDATES"; do
fi fi
done done
if gh release view "$TAG" --repo "$REPOSITORY" >/dev/null 2>&1; then if "$GIT_BIN" rev-parse -q --verify "refs/tags/$TAG" >/dev/null; then
gh release upload "$TAG" "$XPI" "$UPDATES" --repo "$REPOSITORY" --clobber if [[ "$("$GIT_BIN" rev-parse "${TAG}^{commit}")" != "$HEAD" ]]; then
echo "ERROR: existing tag $TAG does not point at HEAD" >&2
exit 1
fi
else else
gh release create "$TAG" "$XPI" "$UPDATES" \ "$GIT_BIN" tag -a "$TAG" -m "Release $TAG"
"$GIT_BIN" push origin "refs/tags/$TAG"
fi
if "$GH_BIN" release view "$TAG" --repo "$REPOSITORY" >/dev/null 2>&1; then
"$GH_BIN" release upload "$TAG" "$XPI" "$UPDATES" --repo "$REPOSITORY" --clobber
else
"$GH_BIN" release create "$TAG" "$XPI" "$UPDATES" \
--repo "$REPOSITORY" \ --repo "$REPOSITORY" \
--title "Verstak Browser Extension $VERSION" \ --title "Verstak Browser Extension $VERSION" \
--generate-notes \ --generate-notes \
--latest \ --latest \
--target "$(git rev-parse HEAD)" --verify-tag
fi fi
echo "GitHub release:" echo "GitHub release:"
gh release view "$TAG" --repo "$REPOSITORY" --json url --jq .url "$GH_BIN" release view "$TAG" --repo "$REPOSITORY" --json url --jq .url

View File

@ -0,0 +1,12 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
VERSION="$(node -p "require('$ROOT/package.json').version")"
if [[ $# -gt 1 || ( $# -eq 1 && "$1" != "v$VERSION" && "$1" != "$VERSION" ) ]]; then
echo "usage: $0 [v$VERSION]" >&2
exit 2
fi
exec "$ROOT/scripts/publish-firefox-github-release.sh"

View File

@ -35,10 +35,16 @@ assert.equal(
); );
const publisher = fs.readFileSync('scripts/publish-firefox-github-release.sh', 'utf8'); const publisher = fs.readFileSync('scripts/publish-firefox-github-release.sh', 'utf8');
assert.match(publisher, /gh auth status/); assert.match(publisher, /auth status/);
assert.match(publisher, /gh release create/); assert.match(publisher, /branch --show-current/);
assert.match(publisher, /gh release upload/); assert.match(publisher, /tag -a/);
assert.match(publisher, /push origin/);
assert.match(publisher, /release create/);
assert.match(publisher, /release upload/);
assert.match(publisher, /--clobber/); assert.match(publisher, /--clobber/);
assert.match(publisher, /--latest/); assert.match(publisher, /--latest/);
const genericPublisher = fs.readFileSync('scripts/publish-github-release.sh', 'utf8');
assert.match(genericPublisher, /publish-firefox-github-release\.sh/);
console.log('Firefox GitHub release metadata tests passed'); console.log('Firefox GitHub release metadata tests passed');