docker-dev rig image stamps a bare 1.0.0 informational version (no git SHA): .dockerignore excludes .git #893

Closed
opened 2026-11-12 22:07:49 -05:00 by dohertj2 · 1 comment
Owner

Found while fixing ScadaBridge#134 (2026-11-12). Same gap here.

Symptom: the docker-dev rig image stamps AssemblyInformationalVersion as a bare 1.0.0, with no +<git sha>. Checked on the current local image: docker run --rm --entrypoint sh otopcua-host:dev -c "grep -ao '1\.0\.0[+0-9a-f-]*' OtOpcUa.Host.dll" prints 1.0.0. So service.version (Telemetry 0.3.0 defaults it from the informational version) and anything else that identifies the build on the rig can't tell which commit is running. Builds for the wonder boxes are published from a checkout, so they keep the SHA and aren't affected.

Cause: docker-dev/Dockerfile runs dotnet publish inside the image after COPY . ., but the repo-root .dockerignore excludes .git/. SourceLink has no repository to read, so SourceRevisionId stays empty.

Fix (the one ScadaBridge took, 7e34d7c2): keep .git/ excluded. Add ARG SOURCE_REVISION= to the build stage, and pass ${SOURCE_REVISION:+-p:SourceRevisionId=${SOURCE_REVISION}} on the publish. Then have docker-dev/deploy.sh supply git rev-parse HEAD, with -dirty added if git status --porcelain --untracked-files=no is non-empty. Here the images are built by compose build: (host and migrator), so wire it in as build.args: SOURCE_REVISION: ${SOURCE_REVISION:-} in docker-compose.yml, with deploy.sh exporting the value. If the arg is empty, the build still succeeds as 1.0.0. One note: the build stage has COPY . . before restore, so the ARG position doesn't affect restore caching.

Found while fixing ScadaBridge#134 (2026-11-12). Same gap here. **Symptom:** the docker-dev rig image stamps `AssemblyInformationalVersion` as a bare `1.0.0`, with no `+<git sha>`. Checked on the current local image: `docker run --rm --entrypoint sh otopcua-host:dev -c "grep -ao '1\.0\.0[+0-9a-f-]*' OtOpcUa.Host.dll"` prints `1.0.0`. So `service.version` (Telemetry 0.3.0 defaults it from the informational version) and anything else that identifies the build on the rig can't tell which commit is running. Builds for the wonder boxes are published from a checkout, so they keep the SHA and aren't affected. **Cause:** `docker-dev/Dockerfile` runs `dotnet publish` inside the image after `COPY . .`, but the repo-root `.dockerignore` excludes `.git/`. SourceLink has no repository to read, so `SourceRevisionId` stays empty. **Fix (the one ScadaBridge took, `7e34d7c2`):** keep `.git/` excluded. Add `ARG SOURCE_REVISION=` to the build stage, and pass `${SOURCE_REVISION:+-p:SourceRevisionId=${SOURCE_REVISION}}` on the publish. Then have `docker-dev/deploy.sh` supply `git rev-parse HEAD`, with `-dirty` added if `git status --porcelain --untracked-files=no` is non-empty. Here the images are built by compose `build:` (`host` and `migrator`), so wire it in as `build.args: SOURCE_REVISION: ${SOURCE_REVISION:-}` in `docker-compose.yml`, with deploy.sh exporting the value. If the arg is empty, the build still succeeds as `1.0.0`. One note: the build stage has `COPY . .` before restore, so the ARG position doesn't affect restore caching.
dohertj2 added the priority:p3type:bugtype:infra labels 2026-11-12 22:08:10 -05:00
Author
Owner

Fixed in 6147e8dc on master (mirrors ScadaBridge 7e34d7c2).

  • docker-dev/Dockerfile: ARG SOURCE_REVISION= after restore; publish adds ${SOURCE_REVISION:+-p:SourceRevisionId=${SOURCE_REVISION}}. .git/ stays in .dockerignore.
  • docker-dev/docker-compose.yml: build.args: SOURCE_REVISION: ${SOURCE_REVISION:-} on migrator and the host anchor (runtime).
  • New docker-dev/compose.sh: exports git rev-parse HEAD (-dirty if git status --porcelain --untracked-files=no is non-empty; an explicit SOURCE_REVISION wins) and runs docker compose -f docker-dev/docker-compose.yml "$@". docker-dev/deploy.sh here is the deploy-POST script, not a build script, so the wrapper is new. README bring-up now uses docker-dev/compose.sh up -d --build.

Evidence (worktree builds, isolated tags so otopcua-host:dev was not touched):

$ docker build -f docker-dev/Dockerfile --target runtime --build-arg SOURCE_REVISION=00a5be26... -t otopcua-host:wt893-pos .
$ docker run --rm --entrypoint sh otopcua-host:wt893-pos -c "grep -ao '1\.0\.0[+0-9a-f-]*' OtOpcUa.Host.dll | sort -u"
1.0.0
1.0.0+00a5be261cc29022c2b88c6cebc0a2148c77156f

$ docker build -f docker-dev/Dockerfile --target runtime -t otopcua-host:wt893-neg .     # no arg
$ docker run --rm --entrypoint sh otopcua-host:wt893-neg -c "grep -ao '1\.0\.0[+0-9a-f-]*' OtOpcUa.Host.dll | sort -u"
1.0.0

(The bare 1.0.0 in the positive output is the AssemblyVersion/FileVersion strings; the informational version carries the +sha.)

Wrapper → compose: docker-dev/compose.sh config printed Source revision: 00a5be26...-dirty and resolved SOURCE_REVISION into all 7 build sections (migrator + 6 host nodes); a plain docker compose ... config resolves it to "".

Fixed in `6147e8dc` on `master` (mirrors ScadaBridge `7e34d7c2`). - `docker-dev/Dockerfile`: `ARG SOURCE_REVISION=` after restore; publish adds `${SOURCE_REVISION:+-p:SourceRevisionId=${SOURCE_REVISION}}`. `.git/` stays in `.dockerignore`. - `docker-dev/docker-compose.yml`: `build.args: SOURCE_REVISION: ${SOURCE_REVISION:-}` on `migrator` and the host anchor (`runtime`). - New `docker-dev/compose.sh`: exports `git rev-parse HEAD` (`-dirty` if `git status --porcelain --untracked-files=no` is non-empty; an explicit `SOURCE_REVISION` wins) and runs `docker compose -f docker-dev/docker-compose.yml "$@"`. `docker-dev/deploy.sh` here is the deploy-POST script, not a build script, so the wrapper is new. README bring-up now uses `docker-dev/compose.sh up -d --build`. Evidence (worktree builds, isolated tags so `otopcua-host:dev` was not touched): ``` $ docker build -f docker-dev/Dockerfile --target runtime --build-arg SOURCE_REVISION=00a5be26... -t otopcua-host:wt893-pos . $ docker run --rm --entrypoint sh otopcua-host:wt893-pos -c "grep -ao '1\.0\.0[+0-9a-f-]*' OtOpcUa.Host.dll | sort -u" 1.0.0 1.0.0+00a5be261cc29022c2b88c6cebc0a2148c77156f $ docker build -f docker-dev/Dockerfile --target runtime -t otopcua-host:wt893-neg . # no arg $ docker run --rm --entrypoint sh otopcua-host:wt893-neg -c "grep -ao '1\.0\.0[+0-9a-f-]*' OtOpcUa.Host.dll | sort -u" 1.0.0 ``` (The bare `1.0.0` in the positive output is the AssemblyVersion/FileVersion strings; the informational version carries the `+sha`.) Wrapper → compose: `docker-dev/compose.sh config` printed `Source revision: 00a5be26...-dirty` and resolved `SOURCE_REVISION` into all 7 build sections (migrator + 6 host nodes); a plain `docker compose ... config` resolves it to `""`.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dohertj2/lmxopcua#893