fix: restore automatic tag versioning

This commit is contained in:
KoalaDev
2026-08-25 14:42:24 +02:00
parent eb925eca5e
commit 5fffeadded
13 changed files with 361 additions and 118 deletions
+35 -47
View File
@@ -4,35 +4,38 @@ This document describes the deployment and release process for KoalaSync.
## Tag-Based Releases
KoalaSync uses a gated release pipeline triggered by immutable Git tags.
KoalaSync uses an automated release pipeline triggered by immutable annotated
Git tags.
> [!IMPORTANT]
> **DO NOT** edit individual version files or tag an unmerged branch. Run
> `npm run prepare:release -- MAJOR.MINOR.PATCH` on a branch, review all generated
> source changes, then run the exact Linux/AMD64 candidate gate before opening
> or updating the pull request:
> `npm run release:gate -- MAJOR.MINOR.PATCH --candidate`.
> Merge only through a pull request with successful CI.
> **DO NOT** edit individual version files before tagging. The workflow extracts
> the exact SemVer version from the tag and updates every release-version source
> atomically. Markdown-only changes do not require browser or release gates.
### How it Works
When an annotated tag matching exact `vMAJOR.MINOR.PATCH` is pushed, the GitHub
Actions workflow performs these ordered gates:
1. Confirms that the tag is annotated, points exactly at current `origin/main`,
and matches every committed version source.
2. Requires successful `verify`, `node20`, and `e2e` checks for that commit.
3. Re-runs release verification, cross-browser E2E, and an unpublished relay
container smoke test.
4. Builds and locally validates Chrome/Firefox archives, checksums, AMO output,
website output, archive parity, and manifests.
5. Creates an attested **draft** GitHub Release.
6. Publishes the multi-architecture relay image, verifies both platforms,
attestation identity, digest, tag source, and a running health check.
7. Makes the GitHub Release public only after every preceding gate succeeds.
The release workflow never writes to `main` and never derives shell code from a
tag. Version changes must pass normal branch protection first.
1. Validates that the tag is an annotated exact `vMAJOR.MINOR.PATCH` tag, points
at current `origin/main`, and has successful `verify`, `node20`, and `e2e`
checks. Invalid tags are rejected before any write.
2. Extracts the validated version and uses the tagged commit timestamp so
repeated preparation is deterministic.
3. Updates and validates all version sources: `extension/manifest.base.json`,
`shared/constants.js`, `package.json`, root metadata in `package-lock.json`,
`website/version.json`, `website/template.html`, `website/llms.txt`, and both
the README badge and release banner.
4. Creates `chore(release): update versions to vX.Y.Z [skip ci]` and pushes it
directly to `main`. A failed push stops every dependent release job.
5. Checks out that exact prepared commit for full verification, cross-browser
E2E, the unpublished relay health smoke, Chrome/Firefox/AMO/checksum/archive
validation, website output, and the relay container build.
6. Creates an attested **draft** GitHub Release after extension checks pass.
7. Publishes the canonical lowercase image `ghcr.io/shik3i/koalasync`, then
verifies both platforms, attestation identity, digest, tag source, and a
running health check.
8. Makes the GitHub Release public only after every preceding job succeeds.
---
@@ -40,35 +43,20 @@ tag. Version changes must pass normal branch protection first.
To release a new version (e.g., `v2.5.1`), follow these steps:
1. Create a release-preparation branch from current `main` and update every
version source atomically:
```bash
git checkout main
git pull origin main
git checkout -b release/v2.5.1
npm run prepare:release -- 2.5.1
git add <reviewed-release-paths>
git commit -m "release: prepare v2.5.1"
npm run release:gate -- 2.5.1 --candidate
```
2. Push the already committed and candidate-gated changes, open a pull request,
and wait for required `verify`, `node20`, and `e2e` checks.
3. After the PR is merged, fast-forward local `main`, wait for `verify`,
`node20`, and `e2e` on the merge commit, then run the final local gate. It
refuses a dirty tree, a non-`main` branch, a commit different from
`origin/main`, missing/failed required checks, version drift, non-AMD64
Linux browser execution, or an unhealthy relay container:
1. Fast-forward local `main`, confirm a clean tree at exact `origin/main`, and
wait for `verify`, `node20`, and `e2e` on that commit:
```bash
git checkout main
git pull --ff-only origin main
npm run release:gate -- 2.5.1
test -z "$(git status --porcelain=v1)"
test "$(git rev-parse HEAD)" = "$(git rev-parse origin/main)"
```
4. Only after that command succeeds, create an **annotated** tag on the exact
checked commit:
2. Create an **annotated** exact SemVer tag on that commit. Do not run
`prepare:release`; the tag workflow owns version updates:
```bash
git tag -a v2.5.1 -m "Release v2.5.1"
```
5. Verify the tag target, then push it once:
3. Verify the tag target, then push it once:
```bash
test "$(git rev-parse v2.5.1^{commit})" = "$(git rev-parse origin/main)"
git push origin v2.5.1
@@ -77,10 +65,10 @@ To release a new version (e.g., `v2.5.1`), follow these steps:
Never reuse or move a published tag. Monitor every release job and verify both
the public GitHub assets and GHCR digest before calling the release complete.
`npm run verify` or a host-only Playwright run is not a substitute for
`release:gate`. The gate pins the official Playwright image to the exact
lockfile version and forces `linux/amd64`, matching GitHub's Ubuntu runner even
when the developer host is macOS or ARM64.
`npm run release:gate -- MAJOR.MINOR.PATCH [--candidate]` remains an optional
Linux/AMD64 parity diagnostic when release code changes. It prepares the target
version only inside an isolated clone. It is not required for Markdown-only
changes and does not replace the tag workflow's own gates.
The relay registry reference is always the canonical lowercase
`ghcr.io/shik3i/koalasync`. Docker repository names reject uppercase characters;