4787e8bf12172f44a354bb627245c2b560560a40
5
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
6632231815 |
Move CI, the image and the Node types to 26 together
Three pins and a types package all described Node 22, and moving any one of them alone puts the build somewhere the others are not: @types/node on its own would typecheck against APIs the runtime does not have, and the base image on its own would ship a major CI never exercised. So ci.yml, publish.yml, release.yml, both Dockerfile stages and @types/node move in one change. Worth knowing before this is deployed: 26 is Current, not LTS. node:26- alpine reports lts=none, where 24-alpine is Krypton and the 22-alpine we are leaving is Jod. 26 is due to become Active LTS in October. Nothing here needs 26 over 24 -- the pins are a single number if the LTS line is preferred. engines stays at >=20.19, which is the floor for running ihasmail rather than the version we build it on; the README's recommendation follows CI to 26. Checked on the runtime, not just in CI: the image builds on 26-alpine, starts, and answers /api/health, and the login, SSE and body-carrying POST checks from the node-server upgrade pass against a server on 26.8.1. |
||
|
|
36ad85feef |
Bump the actions group with 7 updates
Bumps the actions group with 7 updates: | Package | From | To | | --- | --- | --- | | [actions/checkout](https://github.com/actions/checkout) | `4` | `7` | | [actions/setup-node](https://github.com/actions/setup-node) | `4` | `7` | | [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) | `3` | `4` | | [docker/login-action](https://github.com/docker/login-action) | `3` | `4` | | [docker/build-push-action](https://github.com/docker/build-push-action) | `6` | `7` | | [actions/upload-artifact](https://github.com/actions/upload-artifact) | `4` | `7` | | [actions/download-artifact](https://github.com/actions/download-artifact) | `4` | `8` | Updates `actions/checkout` from 4 to 7 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v7) Updates `actions/setup-node` from 4 to 7 - [Release notes](https://github.com/actions/setup-node/releases) - [Commits](https://github.com/actions/setup-node/compare/v4...v7) Updates `docker/setup-buildx-action` from 3 to 4 - [Release notes](https://github.com/docker/setup-buildx-action/releases) - [Commits](https://github.com/docker/setup-buildx-action/compare/v3...v4) Updates `docker/login-action` from 3 to 4 - [Release notes](https://github.com/docker/login-action/releases) - [Commits](https://github.com/docker/login-action/compare/v3...v4) Updates `docker/build-push-action` from 6 to 7 - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](https://github.com/docker/build-push-action/compare/v6...v7) Updates `actions/upload-artifact` from 4 to 7 - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v4...v7) Updates `actions/download-artifact` from 4 to 8 - [Release notes](https://github.com/actions/download-artifact/releases) - [Commits](https://github.com/actions/download-artifact/compare/v4...v8) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major dependency-group: actions - dependency-name: actions/setup-node dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major dependency-group: actions - dependency-name: docker/setup-buildx-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major dependency-group: actions - dependency-name: docker/login-action dependency-version: '4' dependency-type: direct:production update-type: version-update:semver-major dependency-group: actions - dependency-name: docker/build-push-action dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major dependency-group: actions - dependency-name: actions/upload-artifact dependency-version: '7' dependency-type: direct:production update-type: version-update:semver-major dependency-group: actions - dependency-name: actions/download-artifact dependency-version: '8' dependency-type: direct:production update-type: version-update:semver-major dependency-group: actions ... Signed-off-by: dependabot[bot] <[email protected]> |
||
|
|
4b2c97df4e |
Prune old images, and keep every release
Two artefacts, opposite answers. Releases stay. They carry no assets -- the image lives in GHCR -- so one costs a tag, a title and generated notes, and with no CHANGELOG in this repository those notes are the only changelog there is. Deleting one destroys history that cannot be reconstructed, and saves nothing. Images accumulate: a multi-architecture build a week, and the by-digest push leaves two untagged per-architecture manifests behind each time on top of the tagged index. Ten tagged versions are kept, which is roughly a quarter of releases and far more than anything anyone rolls back to. The obvious tool for this is a trap. delete-package-versions with `delete-only-untagged-versions` will delete the per-architecture manifests that a multi-arch tag points at, because they are untagged by design, and nothing appears to break: the tag still resolves and pulls simply start failing for one architecture. This action understands manifest lists and leaves a retained index's children alone, `validate` re-checks every multi-arch manifest against the registry afterwards, and `latest` is excluded from consideration entirely. It is pinned to a commit rather than a major tag. It holds `packages: write` and its whole purpose is deletion, so a tag repointed upstream is not a risk worth carrying for the convenience. Kept in its own file and dispatchable, so a dry run can show exactly what would go without rebuilding and re-pushing an image to find out. |
||
|
|
5cb0b2f3ea |
Cut a release once a week, and only when there is something in it
Publishing on release is the right trigger only if releases happen. They had not: main ran 184 commits ahead of the last one, so `:latest` described a build that neither the demo, nor production, nor anyone building from source was running. This is the part that makes the trigger true without anyone having to remember. Mondays at 09:00 UTC. A run with no commits since the last release does nothing at all -- an empty release moves `:latest` to an identical build, spends a version number and mails every watcher about nothing. The decision is written to the run summary either way, so a quiet week reads as a decision rather than as a workflow that failed silently. The awkward part is that a release created with GITHUB_TOKEN raises no `release` event: GitHub refuses to let a token trigger another workflow, to stop a workflow looping on its own output. A scheduled job that cut a release and left publish.yml to notice would tag the commit and never build an image, which is the kind of failure that looks like success. So publish.yml gains a `workflow_call` trigger and this calls it directly. The alternative was a personal access token kept as a secret; this needs no credential. Two smaller decisions. Drafts are excluded when looking for the last release, because an unpublished draft is not a release anybody has and counting from it would hide commits that never shipped. And if the tag a release names has gone, the count falls back to the whole history -- over-counting cuts a release that was due anyway, where under-counting skips one that was not. |
||
|
|
1734ed0439 |
Publish the image the docs have been telling people to pull
README has said `docker run ... ghcr.io/coffey-labs/ihasmail:latest` since the Docker instructions were written, and the docs site repeats it in four places. Nothing ever pushed that image. `docker pull` answers `denied`, because the package does not exist: .github/workflows held ci.yml and nothing else, and there is no reference to ghcr.io, docker/build-push or docker push anywhere in this repo. The instructions have been wrong the whole time. Adds the workflow that makes them true. It fires on a published release, and by hand for a ref -- the same dispatch trigger ci.yml carries, and the only way to build an image for the tags that predate this file. Two architectures on native runners rather than one build under QEMU. Emulated arm64 runs `npm ci` and the Vite build through instruction translation, which takes tens of minutes and sometimes exhausts memory; ubuntu-24.04-arm is free for public repositories and does it at native speed. The cost is pushing by digest and joining the two into one manifest at the end, which is what the third job does. `latest` moves only for a real release. A prerelease that moved it would hand every `:latest` deployment an unfinished build, and a dispatch run has to ask for it deliberately. Also documents the images in README: which tags exist, that the dated tag is the one to pin, and that building it yourself is still fully supported -- `docker compose up --build` is unchanged and the image is a convenience, not a new requirement. Worth knowing before the first run: GHCR creates a new package **private**, even for a public repository, so an anonymous pull will still be refused until the visibility is changed by hand. That is written at the top of the workflow, because it is the failure that looks like success. |