Skip to content

feat: report the running build via GET /api/version - #385

Merged
hokiepokedad2 merged 1 commit into
mainfrom
feat/version-endpoint
Aug 5, 2026
Merged

feat: report the running build via GET /api/version#385
hokiepokedad2 merged 1 commit into
mainfrom
feat/version-endpoint

Conversation

@hokiepokedad2

Copy link
Copy Markdown
Contributor

Answers "what is this instance actually running?" with one request, no shell access to the host.

$ curl -s https://alerts.pgandev.us/api/version
{"version":"beta","revision":"3f8d38aa...","revisionShort":"3f8d38a","buildDate":"2026-08-05T14:22:16Z","environment":"Production"}

Why the OCI labels were not enough

The image already carries org.opencontainers.image.version and .revision. Two problems:

  1. Labels need docker inspect on the host. They cannot answer the question from outside, which is when you usually want it.
  2. A locally-built image has no labels at all. This came up in practice — the dev container ran poracleweb.net:oidc-dev-fixed, built by hand, carrying only the Ubuntu base version. Which commit dev was on turned out to be unrecoverable.

Labels are also invisible from inside the container, so the values are passed as build args and baked into the environment instead.

Change

File Change
VersionController.cs New GET /api/version
Dockerfile BUILD_VERSION / BUILD_REVISION / BUILD_DATE args → env, defaulting to unknown
docker-publish.yml Passes those args from the same metadata that produces the OCI labels

Builds that omit the args report unknown rather than failing, so dotnet run and a plain local docker build keep working unchanged.

Anonymous by design. The point is checking a deployment without credentials. The repository is public, so the commit SHA is already visible on GitHub, and the response exposes no configuration, secret, or host detail beyond the ASP.NET environment name.

Verification

Five unit tests cover the controller: values from configuration, 7-character shortening, the unknown fallback when no build args were supplied, blank/whitespace values treated as unknown (an unset build arg arrives as an empty string, not a missing key), and a revision shorter than seven characters not being truncated.

Unit tests cannot prove the two parts that actually worried me, so both were checked for real:

Build-arg plumbing — built the image with args and confirmed they land in the environment:

BUILD_VERSION=test-1.2.3
BUILD_REVISION=3f8d38aa4724209ec7ebaf4f0a1053d063008734
BUILD_DATE=2026-08-05T15:00:00Z

then built it without args and confirmed all three read unknown.

Routing precedence — ran the container against a throwaway MariaDB and hit the endpoint over HTTP:

GET /api/version   -> 200  {"version":"test-1.2.3","revision":"3f8d38aa...","revisionShort":"3f8d38a",...}
GET /api/nonexistent -> 200  (index.html, SPA fallback)

This mattered: /api/version previously returned index.html, because the SPA catch-all swallowed it. A 200 alone proves nothing here — only the JSON body does.

Full backend suite: 1462 tests pass. Test containers, image and network cleaned up afterwards.

Follow-up

Once merged, CI publishes :beta and the dev watchtower picks it up within ~60s, so curl https://alerts.pgandev.us/api/version becomes the standing answer for dev. Prod reports it from the next release build.

Answers "what is this instance actually running?" without shell access to the
host.

The image already carries version and revision in its OCI labels, but labels are
only readable with `docker inspect` on the host, so they cannot answer the
question from outside -- and a locally-built image carries no labels at all,
which is exactly the case that came up: the dev container's provenance was
simply unrecoverable.

Labels are also invisible from inside the container, so the values are now
passed as Docker build args and baked into the environment. CI supplies them
from the same metadata that produces the labels; any build that omits them
reports "unknown" instead of failing, so `dotnet run` and local `docker build`
keep working.

Anonymous on purpose: the point is checking a deployment without credentials.
The repository is public, so the commit SHA is already visible on GitHub, and
the response exposes no configuration or secret.

Verified end to end, not just by unit test: built the image with build args and
confirmed they land in the environment; built it without and confirmed the
"unknown" fallback; then ran the container against a throwaway MariaDB and
`GET /api/version` returned the injected values as JSON. That last step matters
because `/api/version` previously returned index.html -- the SPA catch-all was
swallowing it -- so routing precedence was the one thing unit tests could not
prove.
@github-actions github-actions Bot added the feat label Aug 5, 2026
@hokiepokedad2
hokiepokedad2 merged commit e358375 into main Aug 5, 2026
7 checks passed
@hokiepokedad2
hokiepokedad2 deleted the feat/version-endpoint branch August 5, 2026 15:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant