Release hashes services/, migrations/ and config/; when images for that hash already exist it skips CI and the build and only applies the new tags. Tagging a release no longer recompiles the webmail. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
4.6 KiB
Releasing LambdaMail
How a version gets from a commit to a server, and what runs where. The history of what changed is in the CHANGELOG.
The pipeline
Everything runs on Gitea Actions (.gitea/workflows/), on runners hosted on
the Oracle server.
| Workflow | Runs on | Does |
|---|---|---|
ci.yml |
every push and pull request | language lint, Go and TypeScript suites against a real Postgres, webmail tests, a Trivy scan of the repository and of each image, and the whole stack brought up with compose |
release.yml |
a push to main, a v* tag, or by hand |
builds the six images for linux/amd64 and linux/arm64 after ci.yml passes, publishes them, and on a tag creates the release |
Nothing is published unless the full suite passes first.
Images are reused, not rebuilt
The images are built from services/, migrations/ and config/ and nothing
else. release.yml hashes those three trees (the inputs-<hash> tag) and asks
the registry whether images for that hash already exist. If they do, it skips
the CI run and the build and only points the new tags (latest, sha-<commit>,
the version) at the existing manifests, which takes about a minute.
So these never recompile anything: a documentation or workflow change merged
to main, and a version tag pushed on a commit whose images were just
published. A change under the three trees rebuilds everything, as it should.
Images go to the Gitea registry, one package per service:
git.lucasrguerra.dev.br/lucasrguerra/lambdamail/{protocols,auth,storage,webmail,migrations,rspamd}
Tags on every image: latest, sha-<full commit>, and on a version tag also
1.2.3, 1.2 and 1. The packages are public, so a server pulls them without
logging in.
Cutting a release
-
Update CHANGELOG.md and CHANGELOG.pt-BR.md: move what is under Unreleased to a new
## [X.Y.Z] - datesection. -
Set
"version"inservices/{auth,storage,webmail}/package.jsonand their lockfiles to the same number. -
Merge to
mainand wait for theReleaserun of that merge to go green. -
Tag the merge commit and push the tag:
git tag -a v1.2.3 -m "LambdaMail 1.2.3" git push gitea v1.2.3
The tag triggers release.yml once more. Because the commit was already
released from main, the images are reused: it adds the tags 1.2.3, 1.2 and
1 to them without building, and creates the entry under Releases with the
image list and the commit log since the previous tag. Tagging a commit whose
main run has not finished (or never ran) builds it from scratch. A tag with a hyphen (v1.3.0-rc.1) is marked as a pre-release.
Versions follow Semantic Versioning: a change to a migration, a required environment variable, or a published port is at least a minor release, and anything that needs manual steps on upgrade is called out in the changelog.
Deploying a version
Coolify pulls; it does not build. See the Upgrading section of
DEPLOYMENT.md for the two-step deploy (set IMAGE_TAG, then
deploy). In short:
IMAGE_TAG= the release (1.2.3) orsha-<commit>. Neverlatest.- Deploy. Migrations run before the services that need them.
- Check
GET /healthonprotocolsand sign in to the webmail.
To roll back, set IMAGE_TAG back to the previous release and deploy again.
Migrations are not reverted: write them so the previous version still runs
against the new schema.
Runners
Two act_runner instances run on the Oracle server (Ampere ARM, 4 cores), each
with its own Docker-in-Docker daemon, so two jobs never share a network or a
port. The jobs run unprivileged.
linux/arm64images build natively;linux/amd64images build under QEMU emulation, which is slower. Layers are cached in the registry.- The Docker daemon of each runner keeps its layer cache between runs, and the toolcache volume keeps downloaded toolchains.
- The workspace of a job is not visible to the Docker daemon, so workflows copy
files into containers with
docker cpinstead of mounting them with-v. - Windows and macOS jobs cannot run here.
Why some actions are not used
aquasecurity/trivy-actionclones Trivy from the workflow's own server, which is Gitea; Trivy runs from its official image instead.actions/upload-artifactv4+ and theghabuild cache are GitHub services; per-architecture images are told apart by tag, and the cache lives in the registry.- Workflows read
GITHUB_OUTPUTandGITHUB_STEP_SUMMARYunder those names: theGITEA_*equivalents are not set by the runner.