|
| 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 |
0 commit comments