Extension channels: dev and main each carry their own signed extension #237
@@ -33,16 +33,31 @@ jobs:
|
||||
# Forgejo release exists yet, otherwise downloads the cached signed XPI.
|
||||
# Result is uploaded as an Actions artifact for build-web to consume.
|
||||
#
|
||||
# Why this lives in build.yml (not a separate workflow): the merge-commit's
|
||||
# docker image tagged `:latest` MUST carry the XPI. A separate sign workflow
|
||||
# racing build.yml leaves `:latest` without the XPI for ~5min (until the
|
||||
# commit-back triggers another build). Inline ordering eliminates the race.
|
||||
# Why this lives in build.yml (not a separate workflow): the image a push
|
||||
# publishes MUST carry the XPI. A separate sign workflow racing build.yml
|
||||
# leaves that image without one for ~5min (until the commit-back triggers
|
||||
# another build). Inline ordering eliminates the race.
|
||||
# Cache strategy: Forgejo Release Assets — picked 2026-05-25 over Generic
|
||||
# Packages (cleaner API surface) and commit-back-to-side-branch (no extra
|
||||
# branch to manage). AMO blocks re-signing the same version (returns 409),
|
||||
# so signing is intentionally one-shot per version bump.
|
||||
# so signing is intentionally one-shot per version.
|
||||
#
|
||||
# BOTH branches sign (milestone 271 step 6, 2026-08-27). Not two signatures:
|
||||
# the version is the commit TIME of the newest packaged-extension change, so
|
||||
# dev and main derive the SAME number for the same extension source. A dev
|
||||
# push that changes the extension signs it; the merge to main then finds the
|
||||
# ext-<version> release already there, hits the cache, and bundles the
|
||||
# byte-identical XPI into `:latest` with no second AMO call. One signature
|
||||
# per extension CHANGE, shared by both channels — that is what makes two
|
||||
# channels affordable, and it is why step 4 (derived version) had to land
|
||||
# first. Ungating this while the version was still the hand-set 1.0.11 would
|
||||
# have hit the existing ext-1.0.11 cache and bundled MAIN's stale XPI into
|
||||
# `:dev` — a dev channel confidently serving old code.
|
||||
#
|
||||
# Tags stay excluded: the tag path deliberately skips signing and polls for
|
||||
# the release instead (see build-web's race note, 2026-05-27).
|
||||
sign-extension:
|
||||
if: github.ref == 'refs/heads/main'
|
||||
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev'
|
||||
runs-on: python-ci
|
||||
container:
|
||||
image: git.fabledsword.com/bvandeusen/ci-python:3.14
|
||||
@@ -233,6 +248,11 @@ jobs:
|
||||
# created it so an upload failure below can roll back (don't
|
||||
# leave an empty release tombstone that the next run's
|
||||
# cache-check mistakes for a partial-failure state).
|
||||
#
|
||||
# target_commitish is the signing commit, not a branch name: since
|
||||
# step 6 either branch can create this release, and hard-coding
|
||||
# `main` would tag a dev-signed XPI against a main commit that may
|
||||
# not even contain the extension source it was built from.
|
||||
STATUS=$(curl -s -o release.json -w "%{http_code}" \
|
||||
-H "Authorization: token $TOKEN" \
|
||||
"https://git.fabledsword.com/api/v1/repos/bvandeusen/FabledCurator/releases/tags/ext-$VERSION" || echo 000)
|
||||
@@ -240,7 +260,7 @@ jobs:
|
||||
CREATED_BY_US=false
|
||||
else
|
||||
curl -s -X POST -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
|
||||
-d "{\"tag_name\":\"ext-$VERSION\",\"name\":\"Extension $VERSION (signed XPI cache)\",\"body\":\"Internal cache for the signed XPI consumed by build.yml's build-web job. Not a user-facing FC release.\",\"target_commitish\":\"main\"}" \
|
||||
-d "{\"tag_name\":\"ext-$VERSION\",\"name\":\"Extension $VERSION (signed XPI cache)\",\"body\":\"Internal cache for the signed XPI consumed by build.yml's build-web job. Not a user-facing FC release.\",\"target_commitish\":\"$GITHUB_SHA\"}" \
|
||||
-o release.json \
|
||||
"https://git.fabledsword.com/api/v1/repos/bvandeusen/FabledCurator/releases"
|
||||
CREATED_BY_US=true
|
||||
@@ -283,7 +303,10 @@ jobs:
|
||||
|
||||
build-web:
|
||||
needs: [sign-extension]
|
||||
# sign-extension is main-only; on dev it's skipped, build-web still runs.
|
||||
# sign-extension runs on main and dev, and is skipped on a tag push (which
|
||||
# polls for the release instead). Either is fine to build on; a FAILED sign
|
||||
# is not — this condition lets success and skipped through, so a failure
|
||||
# skips build-web rather than shipping an image without the XPI.
|
||||
if: always() && (needs.sign-extension.result == 'success' || needs.sign-extension.result == 'skipped')
|
||||
runs-on: python-ci
|
||||
container:
|
||||
@@ -297,11 +320,14 @@ jobs:
|
||||
# that exists perfectly well under its real name.
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download signed XPI from Forgejo release asset (main + tags)
|
||||
# Fires on main-push AND on tag-push. Tag-push builds re-package the
|
||||
# same source code as the preceding main-push build but with an
|
||||
# immutable version tag — they need the XPI too, otherwise the
|
||||
# versioned image ships without the signed extension.
|
||||
- name: Download signed XPI from Forgejo release asset
|
||||
# Fires on every trigger shape. dev and main each bundle the XPI their
|
||||
# own sign-extension just published — that is the whole point of the
|
||||
# channel work (milestone 271 step 6): the dev image carries the
|
||||
# extension being developed, rather than requiring a merge to try it.
|
||||
# Tag-push builds re-package the same source as the preceding main-push
|
||||
# build but with an immutable version tag — they need the XPI too,
|
||||
# otherwise the versioned image ships without the signed extension.
|
||||
#
|
||||
# Tag-push vs main-push race (operator-flagged 2026-05-27 after
|
||||
# v26.05.27.0 hit it): a release cut fires BOTH workflows almost
|
||||
@@ -313,7 +339,7 @@ jobs:
|
||||
# for up to 10min total) before giving up. Main-push's signing
|
||||
# eventually wins and tag-push picks the release up on a later
|
||||
# iteration.
|
||||
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/')
|
||||
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' || startsWith(github.ref, 'refs/tags/')
|
||||
env:
|
||||
TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
run: |
|
||||
|
||||
Reference in New Issue
Block a user