chore(release): v0.4.0 #54

Merged
alex merged 1 commit from release-prep/rolling into main 2026-08-06 16:03:41 +02:00

Added

  • release: attach a compiled purser-linux-amd64 binary to each Forgejo release (#16)

    A new attach-release-asset job runs after the cut and uploads the binary to the draft release before the operator publishes it. The binary is built with the same -ldflags "-X …/version.Tag=${TAG}" injection used by the Docker image, so the login page and the Docker-deployed binary report the same tag. The job is a no-op on non-cut runs (update / noop mode) and on dry runs.

The dashboard can now choose a certificate's expiry at issue time, up to
PURSER_MAX_CERT_LIFETIME. Leaving the box empty gives PURSER_CERT_LIFETIME
as before, and the control is hidden entirely until the ceiling is raised above
the default — so nothing changes for a deployment that does not opt in.

A request above the ceiling is refused before anything is signed, with the
limit named. A request shorter than PURSER_DOWNLOAD_WINDOW is refused too: no
minTLSCertDuration is set on the provisioner, so the CA would sign a
certificate that can expire before it finishes being installed.

  • docs: document dashboard password rotation with hashpw (#44)

    Operators now have a runbook for replacing the mounted bcrypt hash without putting the password in argv or adding a change-password form to Purser.

Changed

None.

Fixed

  • version: add tests for the Tag → VCS revision → dev fallback chain (#29)

    internal/version had no test file; purser#7 carried a negative-control AC for the dev/unknown fallback that was never met. Six tests now cover the three arms (Tag set, VCS revision present, neither) including an arm for the empty-revision guard (vcs.revision key present, value empty → must fall through to "dev") and a mutation-verified negative control asserting the chain never returns an empty or invented string. Each arm uses an injectable readBuildInfo hook so tests exercise the full chain regardless of whether VCS info is available in the CI container.

  • release: address Lookout review 4976 on attach-release-asset job

Removed

None.

Deprecated

None.

Upgrade

None.

### Added - **release**: attach a compiled `purser-linux-amd64` binary to each Forgejo release (#16) A new `attach-release-asset` job runs after the cut and uploads the binary to the draft release before the operator publishes it. The binary is built with the same `-ldflags "-X …/version.Tag=${TAG}"` injection used by the Docker image, so the login page and the Docker-deployed binary report the same tag. The job is a no-op on non-cut runs (update / noop mode) and on dry runs. The dashboard can now choose a certificate's expiry at issue time, up to `PURSER_MAX_CERT_LIFETIME`. Leaving the box empty gives `PURSER_CERT_LIFETIME` as before, and the control is hidden entirely until the ceiling is raised above the default — so nothing changes for a deployment that does not opt in. A request above the ceiling is **refused before anything is signed**, with the limit named. A request shorter than `PURSER_DOWNLOAD_WINDOW` is refused too: no `minTLSCertDuration` is set on the provisioner, so the CA would sign a certificate that can expire before it finishes being installed. - **docs**: document dashboard password rotation with `hashpw` (#44) Operators now have a runbook for replacing the mounted bcrypt hash without putting the password in argv or adding a change-password form to Purser. ### Changed None. ### Fixed - **version**: add tests for the Tag → VCS revision → dev fallback chain (#29) `internal/version` had no test file; `purser#7` carried a negative-control AC for the dev/unknown fallback that was never met. Six tests now cover the three arms (`Tag` set, VCS revision present, neither) including an arm for the empty-revision guard (`vcs.revision` key present, value empty → must fall through to `"dev"`) and a mutation-verified negative control asserting the chain never returns an empty or invented string. Each arm uses an injectable `readBuildInfo` hook so tests exercise the full chain regardless of whether VCS info is available in the CI container. - **release**: address Lookout review 4976 on attach-release-asset job ### Removed None. ### Deprecated None. ### Upgrade None.
Generated by release-toolkit rt prep.

Tracker: frankenbit/release-toolkit#1
forgejo-actions changed title from chore(release): v0.3.1 to chore(release): v0.4.0 2026-08-06 15:04:31 +02:00
forgejo-actions force-pushed release-prep/rolling from c141484472 to 47d04a17a2 2026-08-06 15:04:33 +02:00 Compare
forgejo-actions force-pushed release-prep/rolling from 47d04a17a2 to 8ae3c7393c 2026-08-06 15:14:37 +02:00 Compare
Owner

⚠️ This PR has NO CI. Not "nothing failing" — nothing ran.

Posting here rather than only on #41, because this page is where the decision gets made and the page looks fine.

statuses on head            0
runs of ANY workflow        0
go-ci · manifest-check · fragment-check · changelog-body-check    all absent

Zero is not green. There is no red, no failed job, and no tell — the PR simply never received a pull_request event, because it was pushed by forgejo-actions from release-prep/rolling. A PR that ran every check and got one warning would look worse than this one.

The control, measured in the same window

PR #55  human branch, real CHANGELOG.md edit   changelog-body-check SUCCESS ×2, + manifest-check, + go-ci
PR #54  bot push,     same file matched         nothing at all

Same repo, same afternoon, same paths: ['CHANGELOG.md'] filter matched. One variable: who pushed. And the surface is demonstrably live — manifest-check fired on #48 at 15:11, go-ci and release.yml on main at 15:13.

So this is not "the changelog gate is broken." The gate is wired and fires — that was proven separately. It is that prep PRs receive no PR CI at all on this instance, which is exactly what #41 exists for, now measured rather than hypothesised.

Why it matters on this PR specifically

This is a v0.4.0 cut, which is a different weight from a docs PR with no CI. The last cut that went through this same hole — #25 — merged with two 36-word sentences that the density check would have caught, and it cost a morning to unwind.

Whoever merges this: the changelog body has not been checked by anything. If it is going to be merged, the body wants a human read first — or run the check by hand against it.

Mechanism is stated as hypothesis, not measurement: Forgejo's anti-recursion safeguard suppresses workflow triggers for pushes made with the Actions token. That fits every observation here; what is measured is the absence and its control, not the cause.

Discriminator by Surveyor — separating "ran and skipped" from "never ran" — against the arm-0 control.

## ⚠️ This PR has NO CI. Not "nothing failing" — nothing ran. Posting here rather than only on #41, because this page is where the decision gets made and the page looks fine. ``` statuses on head 0 runs of ANY workflow 0 go-ci · manifest-check · fragment-check · changelog-body-check all absent ``` **Zero is not green.** There is no red, no failed job, and no tell — the PR simply never received a `pull_request` event, because it was pushed by `forgejo-actions` from `release-prep/rolling`. A PR that ran every check and got one warning would look *worse* than this one. ### The control, measured in the same window ``` PR #55 human branch, real CHANGELOG.md edit changelog-body-check SUCCESS ×2, + manifest-check, + go-ci PR #54 bot push, same file matched nothing at all ``` Same repo, same afternoon, same `paths: ['CHANGELOG.md']` filter matched. **One variable: who pushed.** And the surface is demonstrably live — `manifest-check` fired on #48 at 15:11, `go-ci` and `release.yml` on `main` at 15:13. So this is not *"the changelog gate is broken."* The gate is wired and fires — that was proven separately. It is that **prep PRs receive no PR CI at all on this instance**, which is exactly what #41 exists for, now measured rather than hypothesised. ### Why it matters on this PR specifically **This is a v0.4.0 cut, which is a different weight from a docs PR with no CI.** The last cut that went through this same hole — #25 — merged with two 36-word sentences that the density check would have caught, and it cost a morning to unwind. **Whoever merges this: the changelog body has not been checked by anything.** If it is going to be merged, the body wants a human read first — or run the check by hand against it. Mechanism is stated as hypothesis, not measurement: Forgejo's anti-recursion safeguard suppresses workflow triggers for pushes made with the Actions token. That fits every observation here; what is *measured* is the absence and its control, not the cause. *Discriminator by Surveyor — separating "ran and skipped" from "never ran" — against the arm-0 control.*
forgejo-actions force-pushed release-prep/rolling from 8ae3c7393c to 447bcf272f
Some checks failed
go-ci / lint + build + test (push) Successful in 51s
release / decide + act (push) Failing after 5s
release / release (push) Failing after 0s
release / attach-release-asset (push) Has been skipped
2026-08-06 15:25:43 +02:00
Compare
alex merged commit 447bcf272f into main 2026-08-06 16:03:41 +02:00
alex deleted branch release-prep/rolling 2026-08-06 16:03:41 +02:00
Sign in to join this conversation.
No description provided.