Skip to content

Commit 57173e0

Browse files
committed
[build] Workflow to automate GitHub releases when a version tag is pushed.
1 parent e7e55ea commit 57173e0

4 files changed

Lines changed: 384 additions & 5 deletions

File tree

Lines changed: 250 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,250 @@
1+
# .github/workflows/manage-releases.yml
2+
3+
# Copyright (C) 2005-2026 Giorgio Maone <https://maone.net>
4+
#
5+
# SPDX-License-Identifier: GPL-3.0-or-later
6+
7+
# Triggered by *1984 tags pushed by tools/deploy2tor.sh.
8+
#
9+
# For the current tag:
10+
# - Creates a GitHub Release named after the regular version (no 1984 suffix)
11+
# - Attaches the XPI from dist.torproject.org (always present)
12+
# - Attaches the AMO XPI from secure.informaction.com (if already uploaded)
13+
# - Attaches the Chrome ZIP from secure.informaction.com (if already uploaded)
14+
#
15+
# Additionally, for pre-release tags only:
16+
# - Derives the corresponding stable version (strips trailing .9xx from VER)
17+
# and finds its GitHub release
18+
# - If it is missing the AMO XPI, checks informaction.com and uploads
19+
# it if now available
20+
#
21+
# Required secrets: only the automatic GITHUB_TOKEN.
22+
23+
name: Manage releases
24+
25+
on:
26+
push:
27+
tags:
28+
- '*1984'
29+
30+
jobs:
31+
release:
32+
name: Create / update current release
33+
runs-on: ubuntu-latest
34+
permissions:
35+
contents: write
36+
outputs:
37+
version: ${{ steps.meta.outputs.version }}
38+
prerelease: ${{ steps.meta.outputs.prerelease }}
39+
40+
steps:
41+
- name: Derive version and pre-release flag
42+
id: meta
43+
run: |
44+
TOR_TAG="${GITHUB_REF_NAME}"
45+
echo "tor_tag=${TOR_TAG}" >> "$GITHUB_OUTPUT"
46+
47+
# Strip the Tor suffix to obtain the regular version.
48+
# Stable: 13.6.15.1984 → 13.6.15 (strip .1984)
49+
# Pre: 13.6.15.90101984 → 13.6.15.901 (strip 01984)
50+
# Both cases share "01984" at the tail; stable also has a leading dot.
51+
VER="${TOR_TAG%01984}"
52+
VER="${VER%.1984}"
53+
echo "version=${VER}" >> "$GITHUB_OUTPUT"
54+
55+
# Stable = suffix is exactly ".1984" or ".01984"; anything else is pre.
56+
SUFFIX="${TOR_TAG#"${VER}"}"
57+
if [[ "$SUFFIX" =~ ^\.0?1984$ ]]; then
58+
echo "prerelease=false" >> "$GITHUB_OUTPUT"
59+
else
60+
echo "prerelease=true" >> "$GITHUB_OUTPUT"
61+
fi
62+
63+
- name: Checkout repository
64+
uses: actions/checkout@v4
65+
with:
66+
fetch-depth: 0
67+
68+
- name: Extract changelog from regular tag annotation
69+
id: changelog
70+
env:
71+
VER: ${{ steps.meta.outputs.version }}
72+
run: |
73+
COMMIT=$(git rev-parse HEAD)
74+
75+
# Try VER as-is, then with trailing .0 components stripped
76+
# (handles the 13.5.0.1984 → regular tag "13.5" case).
77+
VER_SHORT="${VER%.0}"
78+
VER_SHORTER="${VER_SHORT%.0}"
79+
80+
REG_TAG=""
81+
for candidate in "$VER" "v$VER" "$VER_SHORT" "v$VER_SHORT" \
82+
"$VER_SHORTER" "v$VER_SHORTER"; do
83+
if git tag --points-at "$COMMIT" | grep -qxF "$candidate"; then
84+
REG_TAG="$candidate"
85+
break
86+
fi
87+
done
88+
89+
if [[ -z "$REG_TAG" ]]; then
90+
echo "No regular tag found on this commit for '$VER'; changelog will be empty." >&2
91+
touch /tmp/changelog.md
92+
else
93+
git tag -l --format='%(contents)' "$REG_TAG" > /tmp/changelog.md
94+
echo "Using annotation from tag '$REG_TAG'."
95+
fi
96+
97+
- name: Download XPI from dist.torproject.org
98+
id: tor_xpi
99+
env:
100+
TOR_TAG: ${{ steps.meta.outputs.tor_tag }}
101+
run: |
102+
FILE="noscript-${TOR_TAG}.xpi"
103+
URL="https://dist.torproject.org/torbrowser/noscript/${FILE}"
104+
echo "Downloading ${URL}"
105+
curl -fsSL --retry 3 -o "$FILE" "$URL"
106+
ls -lh "$FILE"
107+
echo "file=${FILE}" >> "$GITHUB_OUTPUT"
108+
echo "label=${FILE}#auto-updated from torproject.org" >> "$GITHUB_OUTPUT"
109+
110+
- name: Download AMO XPI from informaction.com
111+
id: amo_xpi
112+
env:
113+
VER: ${{ steps.meta.outputs.version }}
114+
PRERELEASE: ${{ steps.meta.outputs.prerelease }}
115+
run: |
116+
FILE="noscript-${VER}.xpi"
117+
if [[ "$PRERELEASE" == "true" ]]; then
118+
SUBPATH="betas"
119+
LABEL_SOURCE="mozilla.org"
120+
else
121+
SUBPATH="releases"
122+
LABEL_SOURCE="informaction.com"
123+
fi
124+
URL="https://secure.informaction.com/download/${SUBPATH}/${FILE}"
125+
echo "Trying ${URL}"
126+
if curl -fsSL --retry 3 -o "$FILE" "$URL" 2>/dev/null; then
127+
ls -lh "$FILE"
128+
echo "found=true" >> "$GITHUB_OUTPUT"
129+
echo "file=${FILE}" >> "$GITHUB_OUTPUT"
130+
echo "label=${FILE}#auto-updated from ${LABEL_SOURCE}" >> "$GITHUB_OUTPUT"
131+
else
132+
echo "AMO XPI not yet available at ${URL}, skipping."
133+
echo "found=false" >> "$GITHUB_OUTPUT"
134+
fi
135+
136+
- name: Download Chrome ZIP from informaction.com
137+
id: chrome_zip
138+
env:
139+
VER: ${{ steps.meta.outputs.version }}
140+
PRERELEASE: ${{ steps.meta.outputs.prerelease }}
141+
run: |
142+
FILE="noscript-${VER}-chrome.zip"
143+
if [[ "$PRERELEASE" == "true" ]]; then
144+
SUBPATH="betas"
145+
else
146+
SUBPATH="releases"
147+
fi
148+
URL="https://secure.informaction.com/download/${SUBPATH}/${FILE}"
149+
echo "Trying ${URL}"
150+
if curl -fsSL --retry 3 -o "$FILE" "$URL" 2>/dev/null; then
151+
ls -lh "$FILE"
152+
echo "found=true" >> "$GITHUB_OUTPUT"
153+
echo "file=${FILE}" >> "$GITHUB_OUTPUT"
154+
else
155+
echo "Chrome ZIP not yet available at ${URL}, skipping."
156+
echo "found=false" >> "$GITHUB_OUTPUT"
157+
fi
158+
159+
- name: Create / update GitHub Release
160+
uses: softprops/action-gh-release@v2
161+
with:
162+
tag_name: ${{ steps.meta.outputs.tor_tag }}
163+
name: ${{ steps.meta.outputs.version }}
164+
prerelease: ${{ steps.meta.outputs.prerelease }}
165+
body_path: /tmp/changelog.md
166+
files: |
167+
${{ steps.tor_xpi.outputs.file }}
168+
${{ steps.amo_xpi.outputs.found == 'true' && steps.amo_xpi.outputs.file || '' }}
169+
${{ steps.chrome_zip.outputs.found == 'true' && steps.chrome_zip.outputs.file || '' }}
170+
171+
# ── Backfill AMO XPI on the corresponding stable release ─────────────────
172+
#
173+
# Only runs for pre-release tags. For a tag like 13.5.2.90101984, VER is
174+
# "13.5.2.901" — the trailing .9xx is stripped to derive the stable base
175+
# version "13.5.2", whose release is then checked and patched if needed.
176+
# Stable tags are excluded because the release job already handles attaching
177+
# the AMO XPI (if available) at creation time.
178+
backfill-stable-amo:
179+
name: Backfill AMO XPI on corresponding stable release
180+
needs: release
181+
if: needs.release.outputs.prerelease == 'true'
182+
runs-on: ubuntu-latest
183+
permissions:
184+
contents: write
185+
186+
steps:
187+
- name: Check and backfill AMO XPI if missing
188+
env:
189+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
190+
VER: ${{ needs.release.outputs.version }}
191+
PRERELEASE: ${{ needs.release.outputs.prerelease }}
192+
run: |
193+
# Derive the stable base version:
194+
# - stable tag (13.5.2.1984) → VER=13.5.2 → STABLE_VER=13.5.2
195+
# - pre tag (13.5.2.90101984) → VER=13.5.2.901 → STABLE_VER=13.5.2
196+
# Strip any trailing .9xx component to reach the stable version.
197+
LAST_COMPONENT="${VER##*.}"
198+
if [[ "$LAST_COMPONENT" =~ ^9[0-9]{2,}$ ]]; then
199+
STABLE_VER="${VER%.*}"
200+
else
201+
STABLE_VER="$VER"
202+
fi
203+
204+
echo "Stable base version to check: ${STABLE_VER}"
205+
206+
# Find the GitHub release whose name matches STABLE_VER.
207+
STABLE_TAG=$(gh release list \
208+
--repo "$GITHUB_REPOSITORY" \
209+
--limit 100 \
210+
--json tagName,name,isPrerelease \
211+
--jq \
212+
--arg sv "$STABLE_VER" \
213+
'[.[] | select(.isPrerelease == false)
214+
| select(.name == $sv)] | first | .tagName' \
215+
2>/dev/null || true)
216+
217+
if [[ -z "$STABLE_TAG" || "$STABLE_TAG" == "null" ]]; then
218+
echo "No stable GitHub release found for version '${STABLE_VER}', nothing to backfill."
219+
exit 0
220+
fi
221+
222+
echo "Stable release tag: ${STABLE_TAG}"
223+
224+
# Check whether it already has the AMO XPI asset.
225+
HAS_AMO=$(gh release view "$STABLE_TAG" \
226+
--repo "$GITHUB_REPOSITORY" \
227+
--json assets \
228+
--jq \
229+
--arg f "noscript-${STABLE_VER}.xpi" \
230+
'.assets[] | select(.name == $f) | .name' \
231+
2>/dev/null || true)
232+
233+
if [[ -n "$HAS_AMO" ]]; then
234+
echo "Release '${STABLE_TAG}' already has the AMO XPI, nothing to do."
235+
exit 0
236+
fi
237+
238+
FILE="noscript-${STABLE_VER}.xpi"
239+
URL="https://secure.informaction.com/download/releases/${FILE}"
240+
echo "AMO XPI missing from '${STABLE_TAG}', checking ${URL} ..."
241+
242+
if curl -fsSL --retry 3 -o "$FILE" "$URL" 2>/dev/null; then
243+
ls -lh "$FILE"
244+
gh release upload "$STABLE_TAG" "$FILE" \
245+
--repo "$GITHUB_REPOSITORY" \
246+
--clobber
247+
echo "Uploaded ${FILE} to release ${STABLE_TAG}."
248+
else
249+
echo "AMO XPI for '${STABLE_VER}' not yet available at ${URL}, skipping."
250+
fi

build.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#
55
# SPDX-License-Identifier: GPL-3.0-or-later
66

7-
BASE="$PWD"
7+
BASE="$(git rev-parse --show-toplevel)"
88
SRC="$BASE/src"
99
BUILD="$BASE/build"
1010
MANIFEST_IN="$SRC/manifest.json"

tools/backfill-tor-tags.sh

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#! /usr/bin/env bash
2+
# backfill-tor-tags.sh
3+
#
4+
5+
# Copyright (C) 2005-2026 Giorgio Maone <https://maone.net>
6+
#
7+
# SPDX-License-Identifier: GPL-3.0-or-later
8+
9+
#!/usr/bin/env bash
10+
# backfill-tor-tags.sh
11+
#
12+
# For every XPI on dist.torproject.org/torbrowser/noscript/ that does NOT
13+
# already have a corresponding *1984 git tag in this repo, find the commit
14+
# that matches the regular version tag and push a new *1984 tag to origin.
15+
#
16+
# Run from the root of the noscript git repo.
17+
# Usage: bash tools/backfill-tor-tags.sh [--dry-run]
18+
19+
set -euo pipefail
20+
21+
DRY_RUN=0
22+
[[ "${1:-}" == "--dry-run" ]] && DRY_RUN=1
23+
24+
BASE="$(git rev-parse --show-toplevel)"
25+
TOR_INDEX_URL="https://dist.torproject.org/torbrowser/noscript/"
26+
27+
echo "Fetching Tor dist index..."
28+
INDEX=$(curl -fsSL "$TOR_INDEX_URL")
29+
30+
TOR_TAGS=$(echo "$INDEX" \
31+
| grep -oP '(?<=noscript-)[\d.]+1984(?=\.xpi)' \
32+
| sort -V \
33+
| uniq)
34+
35+
if [[ -z "$TOR_TAGS" ]]; then
36+
echo "ERROR: No *1984 XPI versions found in index. Check URL or page format." >&2
37+
exit 1
38+
fi
39+
40+
echo "Found $(echo "$TOR_TAGS" | wc -l) Tor XPI version(s) on dist.torproject.org."
41+
42+
git -C "$BASE" fetch --tags --quiet origin 2>/dev/null || true
43+
EXISTING_TAGS=$(git -C "$BASE" tag -l)
44+
45+
skipped=0; tagged=0; missing_regular=0; already=0
46+
47+
for TOR_TAG in $TOR_TAGS; do
48+
49+
if echo "$EXISTING_TAGS" | grep -qxF "$TOR_TAG"; then
50+
echo "SKIP (already tagged): $TOR_TAG"
51+
(( already++ )) || true
52+
continue
53+
fi
54+
55+
# Derive the regular version from the Tor tag.
56+
# The Tor suffix is always "0?1984" where the boundary with the regular
57+
# version is:
58+
# - a dot for stable releases: 13.6.15.1984 → 13.6.15
59+
# 13.5.902.1984 → 13.5.902
60+
# - a literal 0 for pre-releases: 13.6.15.90101984 → 13.6.15.901
61+
# 13.5.1.90201984 → 13.5.1.902
62+
# Pre-release tags end in 0…1984 (e.g. 90101984); stable tags end in .1984.
63+
# Two suffix strips cover both; each is a no-op on the other case.
64+
VER="${TOR_TAG%01984}"
65+
VER="${VER%.1984}"
66+
67+
if [[ "$VER" == "$TOR_TAG" ]]; then
68+
echo "SKIP (unexpected format, could not derive regular version): $TOR_TAG" >&2
69+
(( skipped++ )) || true
70+
continue
71+
fi
72+
73+
# The regular tag may omit trailing .0 components (e.g. tor "13.5.0.1984"
74+
# → VER "13.5.0" but regular tag is just "13.5"), so also try with those stripped.
75+
VER_SHORT="${VER%.0}" # strip one trailing .0; repeat for pathological cases
76+
VER_SHORTER="${VER_SHORT%.0}"
77+
78+
REG_TAG=""
79+
for candidate in "$VER" "v$VER" "$VER_SHORT" "v$VER_SHORT" "$VER_SHORTER" "v$VER_SHORTER"; do
80+
if echo "$EXISTING_TAGS" | grep -qxF "$candidate"; then
81+
REG_TAG="$candidate"
82+
break
83+
fi
84+
done
85+
86+
if [[ -z "$REG_TAG" ]]; then
87+
echo "SKIP (no regular tag for '$VER'): $TOR_TAG"
88+
(( missing_regular++ )) || true
89+
continue
90+
fi
91+
92+
COMMIT=$(git -C "$BASE" rev-list -n1 "$REG_TAG" 2>/dev/null || true)
93+
if [[ -z "$COMMIT" ]]; then
94+
echo "SKIP (cannot resolve commit for tag '$REG_TAG'): $TOR_TAG" >&2
95+
(( skipped++ )) || true
96+
continue
97+
fi
98+
99+
echo "TAGGING $TOR_TAG$COMMIT (regular tag: $REG_TAG)"
100+
101+
if [[ $DRY_RUN -eq 1 ]]; then
102+
echo " [dry-run] git tag '$TOR_TAG' '$COMMIT'"
103+
echo " [dry-run] git push origin '$TOR_TAG'"
104+
else
105+
git -C "$BASE" tag "$TOR_TAG" "$COMMIT"
106+
git -C "$BASE" push origin "$TOR_TAG"
107+
echo " ✓ pushed $TOR_TAG"
108+
fi
109+
110+
(( tagged++ )) || true
111+
112+
done
113+
114+
echo ""
115+
echo "Done."
116+
echo " Already had tag : $already"
117+
echo " Newly tagged : $tagged"
118+
echo " No regular tag : $missing_regular"
119+
echo " Skipped (other) : $skipped"
120+
121+
if [[ $missing_regular -gt 0 ]]; then
122+
echo "$missing_regular Tor version(s) had no matching regular git tag (likely pre-repo history)."
123+
fi

0 commit comments

Comments
 (0)