Copies .dockerignore, .gitignore, .prettierignore, check.yml and REPO_POLICIES.md from sneak/prompts at dd4027b. The repo's own entries (dist/, release/, yarn files) are kept after the canonical content. The Dockerfile gets separate lint and test phases. Its last stage depends on both, checks the git describe version and runs make build. script/lint, test, check, cibuild and docker are the canonical models. check-censored moves into the lint phase and test-verify-build into the test phase. fmt and fmt-check fall back to the nvm-installed node. The e2e image builds are uncached. Comments that cited the old test caps now say 60 seconds, and comments that named what runs a script now name the Dockerfile phase or stage. Model: opus-5-5
88 lines
5.3 KiB
Markdown
88 lines
5.3 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`, which runs
|
|
`script/check` and then builds the image uncached, 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`.
|