Implement runtime version injection and footer display #112
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Implements the Web Application Versioning and Build Standard: version string injection via ldflags at build time, displayed in the UI footer.
Changes
main.go
var Version = "dev"for ldflags injectionversiontemplate functionDockerfile
ARG VERSION=dev-ldflags "-X 'main.Version=${VERSION}'"GitHub Actions
docker-build-dev.yml: Computedev/${BRANCH}@${SHA12}and pass as build-argrelease-docker-ghcr.yml: Passgithub.ref_name(release tag) as VERSIONtemplates/index.html
Example
Screenshot
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
metadata.google.internal/tmp/server /tmp/server -slog -stringintconv l/linux_amd64/vet /tmp/go-build3575277288/b357/vet.cfg /go-build mpile ux-amd64/pkg/tool/linux_amd64/vet user.name rg/toolchain@v0.-unsafeptr=false m ux-amd64/pkg/too/tmp/go-build3575277288/b177/vet.cfg conf�� 0.1-go1.25.6.linux-amd64/src/os/-p andler.go ux-amd64/pkg/tool/linux_amd64/vet(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
Web Application Versioning and Build Standard
Each web application MUST expose a single runtime version string that:
• Defaults to dev when not explicitly set at build time
• For production releases, equals the release tag, for example v1.2.3
• For development builds, MAY be set to dev/{BRANCH}@{SHA12} (SHA truncated to 12 chars), for example dev/main@1a2b3c4d5e6f
That version MUST be displayed in the web UI footer on every rendered page as:
Version: {VERSION}
⸻
2.1 Location and name
• Each repository MUST define the following in main.go at the repo root (package main):
var Version = "dev"
2.2 Meaning
• Version == "dev" means a generic dev build (unknown branch and commit), acceptable fallback.
• Any other value is considered authoritative and MUST be displayed verbatim.
⸻
3.1 Docker build argument
All web app Docker builds MUST accept a build argument named:
• VERSION (string)
Rules:
• Default value MUST be dev if not provided.
• VERSION MUST be injected into the Go binary as main.Version.
3.2 Go build injection
The Go build step in Docker MUST set main.Version via ldflags:
• -ldflags "-X 'main.Version=${VERSION}'"
The repo MUST NOT rely on git state at runtime (no git inside runtime image and no reading .git).
⸻
For the standard multi-stage Dockerfile pattern:
4.1 Builder stage
• MUST define ARG VERSION=dev in the builder stage.
• MUST build with ldflags injection to set main.Version.
• MUST keep CGO disabled (as you already do).
Example requirement-level change (exact syntax can vary, but behavior must match):
• Add ARG VERSION=dev
• Modify the build command to:
go build -mod=readonly -o server -ldflags "-X 'main.Version=${VERSION}'" .
4.2 Runtime stage
• No changes required beyond copying the resulting binary.
• The runtime image MUST NOT require git or source code.
⸻
5.1 Shared conventions
All workflows that build Docker images for these web apps MUST:
• Compute a VERSION string
• Pass it to Docker build as build-arg VERSION
• Not require repo-specific naming inside the Dockerfile
5.2 Development build workflow requirements
Without changing trigger behavior, the dev workflow MUST be compatible with future branch builds by deriving version from:
• Branch: github.ref_name
• Commit: github.sha truncated to 12 characters
Rules:
• The workflow MUST compute:
• SHA12 = first 12 characters of github.sha
• BRANCH = github.ref_name
• VERSION = dev/${BRANCH}@${SHA12}
• If BRANCH is empty or unavailable, the workflow MUST fall back to VERSION=dev.
• The workflow MUST pass VERSION into docker/build-push-action via build-args.
Notes:
• Do not implement feature branch tagging or retention cleanup in these requirements.
• This only defines the version string injection interface so that adding branch builds later does not require application changes.
5.3 Release workflow requirements
For the release workflow:
• The workflow MUST set VERSION to the release tag value.
• Use github.ref_name as the canonical tag string.
• The workflow MUST pass VERSION into docker/build-push-action via build-args.
This is independent from the Docker image tags produced by docker/metadata-action. The injected binary version MUST equal the release tag (for example v1.2.3), even if the image is also tagged with v1, v1.2, or a sha tag.
⸻
6.1 Footer content
All HTML pages rendered by the server MUST include the existing footer content unchanged, plus an additional second line below it that displays:
Version: {VERSION}
Constraints:
• The added line MUST visually match the existing application style (font size, color, spacing).
• It MUST be in the footer region and appear on every page using the shared layout.
6.2 Template integration requirements
Implementations MAY differ internally, but MUST meet one of the following standard patterns:
Pattern A (preferred for consistency): global template function
• The template system MUST expose a function available to the base layout, for example version, that returns the application version string.
• Footer renders Version: {{ version }} (exact template syntax depends on engine).
• This avoids passing version through every handler.
Pattern B: layout data field
• The base layout template data model MUST include a Version field populated from main.Version.
• Footer renders Version: {{ .Version }}.
• Handlers MUST populate the field consistently for all pages.
Either pattern is acceptable, but each repo MUST use exactly one chosen pattern consistently within that repo.
6.3 Source of truth
• The footer MUST display the exact value of main.Version at runtime.
• No additional parsing or normalization is required. Display verbatim.
⸻
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.