[Bug] latest points at main, not at a release #561

Open
opened 2026-07-31 11:00:26 +02:00 by simon · 1 comment
Owner

Description

Two related problems, both about knowing which version an instance runs.

latest points at main, not at a release. Every push to main publishes latest plus the commit sha, while the tag pipeline uses auto_tag, which produces 1, 1.3 and 1.3.0 but never latest. So latest only ever means "current main", and no released version ever carries it. That inverts what operators expect: latest is the implicit default (docker pull <image> resolves to :latest), so the least experienced operators receive our least stable build. Together with an auto-updater such as Watchtower it becomes unattended deployment of unreleased code, which is how #559 reached a production instance. There is currently no tag at all that means "newest stable release", so someone who simply wants to stay current has no correct choice unless they happen to know they should pin 1.3.

Our own CD needs a stable pointer to the tip of main. Today it would have to use latest, which is exactly the tag that should stop meaning that. We need a tag that is explicitly the moving tip of main, so continuous deployment can follow it without competing with the meaning of latest.

Nothing reports the running version. mix.exs still declares 0.1.0 while the changelog is at 1.3.0, the image carries no version metadata, and the UI shows nothing. When an operator reports a problem we have to ask what they run, and they have no place to look it up.

Proposed tagging scheme

Tag Points at Mutability Audience
main tip of main, published on every push moving our CD, and anyone deliberately testing unreleased code
<sha> one specific commit immutable what CD should actually deploy and roll back to
1.3.0 one release immutable operators pinning exactly
1.3, 1 newest patch resp. minor of that line moving operators who want automatic patch updates
latest newest release moving the default any operator gets without thinking

main is the conventional name for a moving pointer at a branch tip: it is self-documenting, matches the branch it is built from, and generalises if we ever add release branches. edge is the other established convention (Alpine, some Docker images) and would be an acceptable alternative, but it says less about where the build comes from. nightly would be wrong, since it implies a schedule rather than every push, and dev is ambiguous between "development build" and "development environment".

Worth stating in the deployment docs, because it is the part that is easy to get wrong: a moving tag makes the deployed digest ambiguous, so push-based CD should deploy the immutable sha it just built rather than main. main exists for pull-based updaters and for manual testing, not as the preferred deployment target.

Note on changing the meaning of latest

This flips an existing tag. Anyone tracking latest today runs main and will move to a release afterwards, which can be an older commit than what they currently run. It needs an entry in the changelog and a line in the release notes; it must not be rolled out silently.

Version reporting

Make the version in mix.exs the real one, or derive it at build time from the git tag, so that Application.spec(:mv, :vsn) is meaningful. Pass the commit sha into the image and set the usual OCI labels (org.opencontainers.image.version, org.opencontainers.image.revision). Then surface it read-only in /settings (GlobalSettingsLive) as its own section below the existing ones, showing the version and, when available, the short commit sha.

Which side owns the version is an open question worth deciding before implementation: mix.exs as the source of truth with the git tag required to match, or the git tag as the source with the version injected at build time. The second prevents the two from drifting, which is what already happened here.

Acceptance criteria

  • latest in the registry points at the newest released version
  • main is published on every push to main and always points at the tip of that branch
  • the immutable commit-sha tag is still published and documented as the recommended deployment target for push-based CD
  • released versions keep their 1.3.0, 1.3 and 1 tags
  • the deployment docs name the recommended tag per audience and warn that automatic updates across versions are unsafe while migrations are one-way
  • Application.spec(:mv, :vsn) returns the real version, and the image carries org.opencontainers.image.version and org.opencontainers.image.revision
  • an admin can read the running version, and the commit sha when available, in the settings page
  • the changed meaning of latest is announced in CHANGELOG.md

External or internal Dependencies

  • Needs verification whether the Drone docker plugin accepts auto_tag together with an explicit tags entry; if it does not, the tag pipeline needs a second publish step instead.
  • Out of scope: anything about how migrations run, and a CI stage that exercises an upgrade against a database with existing rows. The latter is its own issue, and #559 showed we need it.
## Description Two related problems, both about knowing which version an instance runs. **`latest` points at main, not at a release.** Every push to `main` publishes `latest` plus the commit sha, while the tag pipeline uses `auto_tag`, which produces `1`, `1.3` and `1.3.0` but never `latest`. So `latest` only ever means "current main", and no released version ever carries it. That inverts what operators expect: `latest` is the implicit default (`docker pull <image>` resolves to `:latest`), so the least experienced operators receive our least stable build. Together with an auto-updater such as Watchtower it becomes unattended deployment of unreleased code, which is how #559 reached a production instance. There is currently no tag at all that means "newest stable release", so someone who simply wants to stay current has no correct choice unless they happen to know they should pin `1.3`. **Our own CD needs a stable pointer to the tip of main.** Today it would have to use `latest`, which is exactly the tag that should stop meaning that. We need a tag that is explicitly the moving tip of `main`, so continuous deployment can follow it without competing with the meaning of `latest`. **Nothing reports the running version.** `mix.exs` still declares `0.1.0` while the changelog is at `1.3.0`, the image carries no version metadata, and the UI shows nothing. When an operator reports a problem we have to ask what they run, and they have no place to look it up. ### Proposed tagging scheme | Tag | Points at | Mutability | Audience | | --- | --- | --- | --- | | `main` | tip of `main`, published on every push | moving | our CD, and anyone deliberately testing unreleased code | | `<sha>` | one specific commit | immutable | what CD should actually deploy and roll back to | | `1.3.0` | one release | immutable | operators pinning exactly | | `1.3`, `1` | newest patch resp. minor of that line | moving | operators who want automatic patch updates | | `latest` | newest release | moving | the default any operator gets without thinking | `main` is the conventional name for a moving pointer at a branch tip: it is self-documenting, matches the branch it is built from, and generalises if we ever add release branches. `edge` is the other established convention (Alpine, some Docker images) and would be an acceptable alternative, but it says less about where the build comes from. `nightly` would be wrong, since it implies a schedule rather than every push, and `dev` is ambiguous between "development build" and "development environment". Worth stating in the deployment docs, because it is the part that is easy to get wrong: a moving tag makes the deployed digest ambiguous, so push-based CD should deploy the immutable sha it just built rather than `main`. `main` exists for pull-based updaters and for manual testing, not as the preferred deployment target. ### Note on changing the meaning of `latest` This flips an existing tag. Anyone tracking `latest` today runs main and will move to a release afterwards, which can be an older commit than what they currently run. It needs an entry in the changelog and a line in the release notes; it must not be rolled out silently. ### Version reporting Make the version in `mix.exs` the real one, or derive it at build time from the git tag, so that `Application.spec(:mv, :vsn)` is meaningful. Pass the commit sha into the image and set the usual OCI labels (`org.opencontainers.image.version`, `org.opencontainers.image.revision`). Then surface it read-only in `/settings` (`GlobalSettingsLive`) as its own section below the existing ones, showing the version and, when available, the short commit sha. Which side owns the version is an open question worth deciding before implementation: `mix.exs` as the source of truth with the git tag required to match, or the git tag as the source with the version injected at build time. The second prevents the two from drifting, which is what already happened here. ## Acceptance criteria - [ ] `latest` in the registry points at the newest released version - [ ] `main` is published on every push to `main` and always points at the tip of that branch - [ ] the immutable commit-sha tag is still published and documented as the recommended deployment target for push-based CD - [ ] released versions keep their `1.3.0`, `1.3` and `1` tags - [ ] the deployment docs name the recommended tag per audience and warn that automatic updates across versions are unsafe while migrations are one-way - [ ] `Application.spec(:mv, :vsn)` returns the real version, and the image carries `org.opencontainers.image.version` and `org.opencontainers.image.revision` - [ ] an admin can read the running version, and the commit sha when available, in the settings page - [ ] the changed meaning of `latest` is announced in `CHANGELOG.md` ## External or internal Dependencies - Needs verification whether the Drone docker plugin accepts `auto_tag` together with an explicit `tags` entry; if it does not, the tag pipeline needs a second publish step instead. - Out of scope: anything about how migrations run, and a CI stage that exercises an upgrade against a database with existing rows. The latter is its own issue, and #559 showed we need it.
Author
Owner

we could also evaluate publishing packages for pull requests so we could easily test them on our staging instance. security-aware of course.

and a release script should also consider updating the version in the publiccode.yml

we could also evaluate publishing packages for pull requests so we could easily test them on our staging instance. security-aware of course. and a release script should also consider updating the version in the publiccode.yml
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
local-it/mitgliederverwaltung#561
No description provided.