fix: A rejected Docker Hub token fails the release it was meant not to #50

Closed
opened 2026-09-05 18:03:27 +00:00 by ahmad · 0 comments
Owner

Context

templates/release.yml's Log in to Docker Hub step (added in #37) is built on an explicit principle, stated in its own comment: a missing token must not stop a release, which is why it uses a hand-rolled docker login rather than docker/login-action — the latter fails a job on an empty password.

It only honours that principle for a token that is absent. A token that is present and rejected — expired, revoked, or rotated — fails the step, and publish with it, under set -euo pipefail.

Driven with a stub docker on an otherwise empty PATH:

neither secret set                exit 0   warns, docker never invoked
only DOCKER_HUB_USER set          exit 0   warns, docker never invoked
both set, login accepted          exit 0   "Authenticated to Docker Hub as …"
both set, login REJECTED          exit 1   step fails, release fails

An expired token is the more likely future state than a missing one: tokens are registered once and then quietly age out, and nobody learns it happened until a release breaks. The failure is strictly avoidable — an anonymous pull is the documented fallback and still works when a credential is stale.

It is latent today because the secrets are not registered anywhere yet (the open half of #37), so every release takes the warn branch. It arrives the moment they are, which is the argument for closing it before the first broken release rather than after.

Found in review of ahmad/portfolio#76, the first repository of #42. The step there is byte-identical to the template, so every copy inherits this — which is why it is fixed here first rather than in any consumer.

Scope

  • In: templates/release.yml treating a failed login the same as a missing one — warn and continue anonymously.
  • Out: registering the secrets (#37); propagating the corrected step to the app repositories (#42), which picks it up once this lands.

Acceptance criteria

  • Given both secrets are set and the login is rejected, when the step runs, then it warns and exits 0 rather than failing the job.
  • Given both secrets are set and the login succeeds, when the step runs, then it reports success and the build proceeds authenticated.
  • Given either secret is absent, when the step runs, then it warns and docker is never invoked, as today.
  • Given the login is rejected, when the warning is emitted, then it states that pulls will be anonymous and subject to the per-IP limit.
### Context `templates/release.yml`'s `Log in to Docker Hub` step (added in #37) is built on an explicit principle, stated in its own comment: a missing token must not stop a release, which is why it uses a hand-rolled `docker login` rather than `docker/login-action` — the latter fails a job on an empty password. It only honours that principle for a token that is **absent**. A token that is **present and rejected** — expired, revoked, or rotated — fails the step, and `publish` with it, under `set -euo pipefail`. Driven with a stub `docker` on an otherwise empty `PATH`: ``` neither secret set exit 0 warns, docker never invoked only DOCKER_HUB_USER set exit 0 warns, docker never invoked both set, login accepted exit 0 "Authenticated to Docker Hub as …" both set, login REJECTED exit 1 step fails, release fails ``` An expired token is the more likely future state than a missing one: tokens are registered once and then quietly age out, and nobody learns it happened until a release breaks. The failure is strictly avoidable — an anonymous pull is the documented fallback and still works when a credential is stale. It is latent today because the secrets are not registered anywhere yet (the open half of #37), so every release takes the warn branch. It arrives the moment they are, which is the argument for closing it before the first broken release rather than after. Found in review of `ahmad/portfolio#76`, the first repository of #42. The step there is byte-identical to the template, so every copy inherits this — which is why it is fixed here first rather than in any consumer. ### Scope - In: `templates/release.yml` treating a failed login the same as a missing one — warn and continue anonymously. - Out: registering the secrets (#37); propagating the corrected step to the app repositories (#42), which picks it up once this lands. ### Acceptance criteria - [ ] Given both secrets are set and the login is rejected, when the step runs, then it warns and exits 0 rather than failing the job. - [ ] Given both secrets are set and the login succeeds, when the step runs, then it reports success and the build proceeds authenticated. - [ ] Given either secret is absent, when the step runs, then it warns and `docker` is never invoked, as today. - [ ] Given the login is rejected, when the warning is emitted, then it states that pulls will be anonymous and subject to the per-IP limit.
ahmad self-assigned this 2026-09-05 18:05:37 +00:00
ahmad closed this issue 2026-09-05 18:32:37 +00:00
Sign in to join this conversation.
No description provided.