Add docs/RELEASE.md, linked from README.md's Release Artifacts section, giving the release procedure as a numbered list: confirm main is green in CI, confirm the one version in package.json and the two manifests matches the intended tag, make package from a clean checkout, verify SHA256SUMS, create the annotated tag vX.Y.Z, then distribute per browser. Each step names who performs it, marks the owner-only ones, and states the check that it worked. Every repo command cited (make setup, make check, make package) exists on next; tagging and verification use standard git and coreutils, and the CRX pack line is README's own. The per-browser distribution step is written as pending the owner's choice on issue 386, with the Firefox and Chrome options named but none presented as settled. Docs only: no code or test changes. Model: opus-4-8
88 lines
5.4 KiB
Markdown
88 lines
5.4 KiB
Markdown
# Releasing AutistMask
|
|
|
|
This is the procedure that turns a green `main` into a tagged, packaged release.
|
|
It gathers into one place what is otherwise spread across the `Makefile` and
|
|
three `README.md` sections, so the person cutting a release does not have to
|
|
reconstruct the order from them.
|
|
|
|
There is one version, declared in three files (`package.json`,
|
|
`manifest/chrome.json`, `manifest/firefox.json`), and `make package` builds and
|
|
packages but publishes nothing. `make build` and `make package` can be run by
|
|
anyone; tagging, signing, packing a CRX and any upload need credentials only the
|
|
owner ([@sneak](https://sneak.berlin)) holds and are marked **owner-only**
|
|
below. Releases are tagged from `main` (see the Workflow section of `TODO.md`),
|
|
so the "release commit" throughout is the `main` commit the milestone PR merged.
|
|
|
|
## Procedure
|
|
|
|
1. **Confirm `main` is green in CI.** The `check` workflow
|
|
(`.gitea/workflows/check.yml`) runs `script/cibuild`, i.e. `docker build .`,
|
|
and the `Dockerfile` runs `make check` as a build step, so a green `check`
|
|
run is a green `make check`. Find the run for the exact release commit on the
|
|
tracker's Actions view. _Check:_ that commit's `check` run succeeded; running
|
|
`make check` on a clean checkout of the commit reproduces it and exits 0.
|
|
|
|
2. **Confirm the version matches the intended tag.** `package.json`,
|
|
`manifest/chrome.json` and `manifest/firefox.json` must all declare the same
|
|
`X.Y.Z`. `make build` fails when they disagree, but nothing checks that they
|
|
equal the tag you mean to create — that is this manual step. _Check:_ all
|
|
three files read the same `X.Y.Z`, and it is the version you intend to tag
|
|
`vX.Y.Z`.
|
|
|
|
3. **Build and package from a clean checkout of that commit.** From a fresh
|
|
clone, or a working tree with no local modifications (`git status` clean),
|
|
checked out at the release commit: run `make setup`, then `make package`.
|
|
`make package` runs `make build` first, so the archives can only be made from
|
|
a `dist/` verified against that build's own receipt as a release (not debug)
|
|
build. It writes three files into `release/`:
|
|
`autistmask-chrome-<version>.zip`, `autistmask-firefox-<version>.xpi`, and
|
|
`SHA256SUMS`. _Check:_ those three files exist and `<version>` in the archive
|
|
names is the version confirmed in step 2. The Firefox `.xpi` is **unsigned**
|
|
(see step 6 and "Installing on Firefox" in `README.md`).
|
|
|
|
4. **Verify `SHA256SUMS`.** The archives are deterministic — sorted entries,
|
|
fixed timestamps, fixed compression — so a second `make package` from another
|
|
clean checkout of the same commit produces byte-identical files. Verify the
|
|
recorded digests against the files with `sha256sum -c SHA256SUMS`, run from
|
|
`release/`. To confirm reproducibility, run `make package` again on a
|
|
separate clean checkout and compare the digests. _Check:_ `sha256sum -c`
|
|
reports `OK` for every file, and an independent build's digests match.
|
|
|
|
5. **Tag the release commit.** _(owner-only)_ Create an annotated tag `vX.Y.Z`
|
|
on the release commit and push it: `git tag -a vX.Y.Z` (with a message), then
|
|
`git push origin vX.Y.Z`. _Check:_ `git tag` lists `vX.Y.Z`, and
|
|
`git rev-parse vX.Y.Z^{commit}` resolves to the release commit.
|
|
|
|
6. **Distribute per browser.** _(owner-only; pending the owner's choice on
|
|
https://git.eeqj.de/sneak/AutistMask/issues/386)_ How 1.0.0 is distributed on
|
|
each browser is not yet decided; it is the open question on that issue, and
|
|
the concrete steps cannot be written until the owner records a choice there.
|
|
These steps need credentials only the owner holds. The options under
|
|
consideration are:
|
|
- **Firefox** — the packaged `.xpi` is unsigned, and release Firefox and ESR
|
|
refuse an unsigned add-on:
|
|
- (a) AMO self-distribution signing (unlisted): submit the `.xpi` to AMO
|
|
with the owner's credentials; AMO returns a signed `.xpi` installable
|
|
on every Firefox, with nothing listed publicly.
|
|
- (b) AMO listed: as (a), plus a public AMO listing and review.
|
|
- (c) Ship the unsigned `.xpi` and state that Firefox support means
|
|
Developer Edition, Nightly, or an Unbranded build with
|
|
`xpinstall.signatures.required` set to `false`.
|
|
- **Chrome** — the repo packs no CRX and publishes nothing; the extension id
|
|
is fixed by the `key` in `manifest/chrome.json`:
|
|
- (a) Chrome Web Store (unlisted): upload the `.zip` with the owner's
|
|
developer account; the store delivers installs and updates.
|
|
- (b) Self-hosted CRX signed with the private key the owner holds
|
|
(`chrome --pack-extension=dist/chrome --pack-extension-key=<path to the .pem>`),
|
|
installable only via enterprise policy on Windows and macOS, so
|
|
realistically Linux-only.
|
|
- (c) "Load unpacked" from `dist/chrome/` only, as today.
|
|
|
|
Once the owner decides, the chosen steps — including which credentials they
|
|
need and who holds them — are written into this section and `README.md`'s
|
|
installation sections are updated to match, which is part of the definition
|
|
of done of https://git.eeqj.de/sneak/AutistMask/issues/386. _Check:_ for a
|
|
store or AMO route, the artifact installs from the store or AMO on a clean
|
|
browser profile; for the CRX or unpacked route, the documented load succeeds
|
|
and Chrome reports the extension id `gipbhkogfopeahplcjhipkgpcimdpkip`.
|