fix(docker-dev): stamp the git commit into rig image versions via a SOURCE_REVISION build arg (#893)
v2-ci / unit-tests (push) Has been cancelled
v2-ci / unit-tests (push) Has been cancelled
.dockerignore keeps .git/ out of the build context, so the in-image publish had no repository and AssemblyInformationalVersion (Telemetry service.version) was a bare 1.0.0. The Dockerfile now takes ARG SOURCE_REVISION and passes it to dotnet publish as SourceRevisionId; docker-compose.yml forwards it as a build arg for the host and migrator images; the new docker-dev/compose.sh wrapper exports git rev-parse HEAD (suffixed -dirty for an uncommitted tree; an explicit value wins) and runs docker compose with the base file. Without the arg the build still succeeds as 1.0.0. The ARG sits after restore so a new commit does not bust the restore layer. Mirrors ScadaBridge 7e34d7c2 (ScadaBridge#134). Claude-Session: https://claude.ai/code/session_01GT67ACmpMR7b9LGRPLijMi
This commit is contained in:
@@ -12,8 +12,16 @@ FROM --platform=linux/amd64 mcr.microsoft.com/dotnet/sdk:10.0 AS build
|
||||
WORKDIR /src
|
||||
COPY . .
|
||||
RUN dotnet restore ZB.MOM.WW.OtOpcUa.slnx
|
||||
# Commit stamp (#893). .dockerignore keeps .git/ out of the build context, so SourceLink has no
|
||||
# repository to read and the informational version would be a bare "1.0.0". The compose `build.args`
|
||||
# (fed by docker-dev/compose.sh from the host's `git rev-parse HEAD`, plus "-dirty" for an uncommitted
|
||||
# tree) hand it to the SDK as SourceRevisionId, which yields "1.0.0+<sha>" in
|
||||
# AssemblyInformationalVersion (and so Telemetry's service.version). Left empty, the build still
|
||||
# succeeds as "1.0.0". Declared after restore so a new commit does not bust the restore layer.
|
||||
ARG SOURCE_REVISION=
|
||||
RUN dotnet publish src/Server/ZB.MOM.WW.OtOpcUa.Host/ZB.MOM.WW.OtOpcUa.Host.csproj \
|
||||
-c Release -o /app --no-restore
|
||||
-c Release -o /app --no-restore \
|
||||
${SOURCE_REVISION:+-p:SourceRevisionId=${SOURCE_REVISION}}
|
||||
|
||||
FROM mcr.microsoft.com/dotnet/aspnet:10.0 AS runtime
|
||||
WORKDIR /app
|
||||
|
||||
@@ -87,7 +87,7 @@ The DriverHost actor doesn't spawn drivers from raw DriverInstance rows on its o
|
||||
|
||||
```bash
|
||||
# from the repo root
|
||||
docker compose -f docker-dev/docker-compose.yml up -d --build
|
||||
docker-dev/compose.sh up -d --build
|
||||
|
||||
# the one-shot migrator + cluster-seed bootstrap the DB; watch the seed finish:
|
||||
docker compose -f docker-dev/docker-compose.yml logs -f cluster-seed # ^C once it prints "[cluster-seed] done."
|
||||
@@ -96,6 +96,8 @@ open http://localhost:9200 # Admin UI (Traefik → central-1 or
|
||||
open http://localhost:8089 # Traefik dashboard
|
||||
```
|
||||
|
||||
`docker-dev/compose.sh` is `docker compose -f docker-dev/docker-compose.yml "$@"` with `SOURCE_REVISION` exported from `git rev-parse HEAD` (suffixed `-dirty` for an uncommitted tree; an explicit `SOURCE_REVISION=...` wins). `.git/` stays out of the build context (`.dockerignore`), so that build arg is the only way the in-image publish learns the commit: with it the Host stamps `1.0.0+<sha>` as its informational version (Telemetry's `service.version`); a plain `docker compose ... --build` still works and stamps a bare `1.0.0` (#893). Check a built image with `docker run --rm --entrypoint sh otopcua-host:dev -c "grep -ao '1\.0\.0[+0-9a-f-]*' OtOpcUa.Host.dll"`.
|
||||
|
||||
The first build takes a few minutes (.NET SDK image + restore + publish). **No manual schema step is needed** — on a fresh SQL volume the one-shot `migrator` service applies the EF migrations (the host nodes deliberately don't auto-migrate, since production owns schema changes), then `cluster-seed` populates the cluster/namespace/driver rows. `cluster-seed` and the host nodes wait for the migrator via `service_completed_successfully`, so nothing races an in-progress migration. A plain `docker compose ... up -d` on an existing volume is a fast no-op for both — the named SQL volume keeps the schema + rows across restarts; only `down -v` wipes them, after which the next `up` re-migrates + re-seeds automatically.
|
||||
|
||||
## Auth (dev only)
|
||||
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# docker compose wrapper for the docker-dev rig that stamps the git commit into the images (#893).
|
||||
#
|
||||
# .dockerignore keeps .git/ out of the build context, so the in-image `dotnet publish` cannot read the
|
||||
# commit itself and AssemblyInformationalVersion would be a bare "1.0.0". This exports SOURCE_REVISION
|
||||
# (git rev-parse HEAD, suffixed "-dirty" for an uncommitted tree) for the compose `build.args`, which
|
||||
# the Dockerfile hands to the SDK as SourceRevisionId -> "1.0.0+<sha>". An explicit SOURCE_REVISION in
|
||||
# the environment wins; outside a git checkout it stays empty and the images stamp a bare "1.0.0".
|
||||
#
|
||||
# Usage (any docker compose arguments; the base compose file is always passed first):
|
||||
# docker-dev/compose.sh up -d --build
|
||||
# docker-dev/compose.sh -f docker-dev/docker-compose.questdb.yml up -d --build central-1 central-2
|
||||
# docker-dev/compose.sh build central-1
|
||||
#
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
||||
|
||||
SOURCE_REVISION="${SOURCE_REVISION:-}"
|
||||
if [ -z "$SOURCE_REVISION" ] && git -C "$REPO_ROOT" rev-parse --git-dir >/dev/null 2>&1; then
|
||||
SOURCE_REVISION="$(git -C "$REPO_ROOT" rev-parse HEAD)"
|
||||
if [ -n "$(git -C "$REPO_ROOT" status --porcelain --untracked-files=no)" ]; then
|
||||
SOURCE_REVISION="${SOURCE_REVISION}-dirty"
|
||||
fi
|
||||
fi
|
||||
export SOURCE_REVISION
|
||||
echo "Source revision: ${SOURCE_REVISION:-<none>}" >&2
|
||||
|
||||
exec docker compose -f "$SCRIPT_DIR/docker-compose.yml" "$@"
|
||||
@@ -113,7 +113,9 @@
|
||||
# exercises.
|
||||
#
|
||||
# Usage:
|
||||
# docker compose -f docker-dev/docker-compose.yml up -d --build
|
||||
# docker-dev/compose.sh up -d --build # = docker compose -f docker-dev/docker-compose.yml ..., plus
|
||||
# # SOURCE_REVISION=<git sha> so the images stamp the commit (#893)
|
||||
# docker compose -f docker-dev/docker-compose.yml up -d --build # also works; images stamp a bare 1.0.0
|
||||
# open http://localhost:9200 # central Blazor admin UI
|
||||
# open http://localhost:8089 # Traefik dashboard (8080 is the sister scadalink stack)
|
||||
#
|
||||
@@ -250,6 +252,9 @@ services:
|
||||
context: ..
|
||||
dockerfile: docker-dev/Dockerfile
|
||||
target: migrator
|
||||
args:
|
||||
# Commit stamp for the image's informational version (#893); docker-dev/compose.sh exports it.
|
||||
SOURCE_REVISION: ${SOURCE_REVISION:-}
|
||||
image: otopcua-migrator:dev
|
||||
depends_on:
|
||||
sql:
|
||||
@@ -291,6 +296,9 @@ services:
|
||||
context: ..
|
||||
dockerfile: docker-dev/Dockerfile
|
||||
target: runtime
|
||||
args:
|
||||
# Commit stamp for the image's informational version (#893); docker-dev/compose.sh exports it.
|
||||
SOURCE_REVISION: ${SOURCE_REVISION:-}
|
||||
image: otopcua-host:dev
|
||||
# Per-node memory bounds. The full single-mesh stack (6 host nodes) OOM-killed
|
||||
# central-1 on a loaded host. Each host node measured ~357 MiB idle-solo and
|
||||
|
||||
Reference in New Issue
Block a user