Stamp the build version into the binary (closes #253)
All checks were successful
check / check (push) Successful in 3m12s
All checks were successful
check / check (push) Successful in 3m12s
This commit was merged in pull request #260.
This commit is contained in:
64
README.md
64
README.md
@@ -57,7 +57,8 @@ make fmt-check # Fail if gofmt would change anything (writes nothing)
|
||||
make lint # Run golangci-lint in Docker (Dockerfile.lint)
|
||||
make test # Run tests with race detection
|
||||
make check # test + lint + fmt-check (CI gate)
|
||||
make build # Build binary to bin/webhooker
|
||||
make build # Build binary to bin/webhooker (version-stamped)
|
||||
make version # Print the version this checkout would stamp
|
||||
make run # build, then run ./bin/webhooker
|
||||
make dev # go run ./cmd/webhooker
|
||||
make deps # go mod download + go mod tidy
|
||||
@@ -691,6 +692,9 @@ Upgrade procedure:
|
||||
3. Pull the new image and start it.
|
||||
4. Confirm `database migrations completed` in the logs before putting
|
||||
traffic back on it.
|
||||
5. Confirm the new build is the one running:
|
||||
`curl -s http://host:8080/.well-known/healthcheck` reports the
|
||||
version it was stamped with (see [Version stamping](#version-stamping)).
|
||||
|
||||
**Downgrade is unsupported.** Once a newer binary has migrated the files
|
||||
there is no way to move them back. `AutoMigrate` is additive — it adds
|
||||
@@ -701,6 +705,42 @@ silent divergence, not a startup error. The only supported way back to
|
||||
an older version is restoring the pre-upgrade backup, which discards
|
||||
everything received since that backup was taken.
|
||||
|
||||
### Version stamping
|
||||
|
||||
The binary reports its version at `/.well-known/healthcheck` (the
|
||||
`version` field), in the UI footer, and in the startup log line
|
||||
(`msg=starting`, `version=...`). It is also the Sentry release name,
|
||||
as `webhooker-{version}`. The value is stamped in at build time by the
|
||||
linker; it is not read from a file at runtime, so it identifies the
|
||||
build itself.
|
||||
|
||||
`script/version` produces the value and both build paths use it:
|
||||
|
||||
| Build | What it reports |
|
||||
| --- | --- |
|
||||
| Clean checkout at a tag | exactly that tag, e.g. `v1.0.0` |
|
||||
| Commits past a tag | `v1.0.0-3-g1a2b3c4` — tag, commits since, short SHA |
|
||||
| No tag reachable | the short SHA, e.g. `1a2b3c4` |
|
||||
| Uncommitted changes | the above with a `-dirty` suffix |
|
||||
| No git metadata | `unknown` |
|
||||
|
||||
`unknown` is what a source tarball or a `docker build .` with no
|
||||
`--build-arg VERSION=...` reports. `.dockerignore` excludes `.git/`, so
|
||||
the build context carries no git metadata and the image cannot derive
|
||||
the version itself: `script/docker` (and so `make docker`) resolves it
|
||||
on the host and passes it in as the `VERSION` build arg. A build that
|
||||
reports `unknown` is a build nobody told what it was; it is not a
|
||||
failure, but it cannot be traced back to a commit.
|
||||
|
||||
`make version` prints what the current checkout would stamp, and
|
||||
`make build VERSION=v1.2.3` overrides it. An empty override — from
|
||||
`make build VERSION=` or from `--build-arg VERSION=` — means unset
|
||||
rather than `""`, and resolves the way an absent one does.
|
||||
|
||||
Nothing that varies between two builds of the same commit is stamped —
|
||||
no timestamp, no hostname, no builder identity — so two builds of one
|
||||
commit still produce a byte-identical binary.
|
||||
|
||||
### Backups contain secrets
|
||||
|
||||
Treat a backup with the same care as the credentials inside it. Encrypt
|
||||
@@ -843,9 +883,11 @@ anything.
|
||||
This repository adheres to the
|
||||
[Scripts to Rule Them All](https://github.com/github/scripts-to-rule-them-all)
|
||||
standard: normalized scripts in `script/` are the entrypoints for the
|
||||
development workflow. Ten of the Makefile's sixteen targets are thin
|
||||
shims that call them; `build`, `run`, `dev`, `deps`, `clean` and `css`
|
||||
are inline commands with no script behind them. We provide:
|
||||
development workflow. Ten of the Makefile's seventeen targets are thin
|
||||
shims that call them; `build`, `run`, `dev`, `deps`, `clean`, `css` and
|
||||
`version` are inline commands with no script behind them, though
|
||||
`build` and `version` both take their value from `script/version`. We
|
||||
provide:
|
||||
|
||||
- `script/bootstrap` — install all dependencies (idempotent)
|
||||
- `script/setup` — make a fresh clone ready for development
|
||||
@@ -858,7 +900,11 @@ are inline commands with no script behind them. We provide:
|
||||
- `script/fmt` — format all code (writes)
|
||||
- `script/fmt-check` — check formatting (read-only)
|
||||
- `script/check` — run test, lint, and fmt-check
|
||||
- `script/docker` — build the Docker image tagged via `script/projectname`
|
||||
- `script/version` — output the version to stamp into the binary (see
|
||||
[Version stamping](#version-stamping))
|
||||
- `script/docker` — build the Docker image tagged via
|
||||
`script/projectname`, passing `script/version`'s output in as the
|
||||
`VERSION` build arg
|
||||
- `script/cibuild` — CI entrypoint: `docker build .` (the Dockerfile
|
||||
runs the checks, so a green build implies a green repo)
|
||||
- `script/ci-mark-superseded` — CI helper: mark the commits whose run a
|
||||
@@ -2430,7 +2476,7 @@ webhooker/
|
||||
├── script/ # Scripts to Rule Them All entrypoints
|
||||
├── Dockerfile # Three stages: lint, test+build, Alpine runtime
|
||||
├── Dockerfile.lint # Lint-only image built by script/lint
|
||||
├── Makefile # 10 of 16 targets shim script/; 6 are inline
|
||||
├── Makefile # 10 of 17 targets shim script/; 7 are inline
|
||||
├── go.mod / go.sum
|
||||
└── .golangci.yml # Linter configuration
|
||||
```
|
||||
@@ -2735,7 +2781,11 @@ version is fixed independently of the compiler's:
|
||||
stage passing (it copies a file from it), runs `script/fetch-assets`
|
||||
to download and verify the third-party browser assets, then runs
|
||||
`make test` and `make build`, and finally rebuilds the binary with
|
||||
`CGO_ENABLED=1` and static linking so it runs on musl.
|
||||
`CGO_ENABLED=1` and static linking so it runs on musl. Both builds
|
||||
go through `make build`, the relink adding its `-extldflags` via
|
||||
`GO_LDFLAGS`, so neither can drop the `-X` that stamps the version.
|
||||
The version arrives as the `VERSION` build arg, since the context
|
||||
has no `.git` (see [Version stamping](#version-stamping)).
|
||||
3. **Runtime stage** (`alpine:3.21`) — copies the static binary,
|
||||
creates the `/var/lib/webhooker` directory for all SQLite databases,
|
||||
runs as the non-root `webhooker` user (UID 1000), exposes port 8080,
|
||||
|
||||
Reference in New Issue
Block a user