Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
369f5cea1a |
+2
-5
@@ -34,11 +34,8 @@ COPY . .
|
|||||||
# Run the tests - build fails if any test fails
|
# Run the tests - build fails if any test fails
|
||||||
RUN make test
|
RUN make test
|
||||||
|
|
||||||
# Build the binary. .dockerignore leaves out .git, so `git describe` in
|
# Build the binary
|
||||||
# the Makefile cannot find the version here: script/docker passes it as
|
RUN make build
|
||||||
# --build-arg VERSION, and a build that passes none reports `dev`.
|
|
||||||
ARG VERSION=dev
|
|
||||||
RUN make build VERSION="${VERSION}"
|
|
||||||
|
|
||||||
# Runtime stage
|
# Runtime stage
|
||||||
# alpine 3.21, 2026-02-28
|
# alpine 3.21, 2026-02-28
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
.PHONY: all bootstrap setup build lint fmt fmt-check test check clean hooks docker
|
.PHONY: all bootstrap setup build lint fmt fmt-check test check clean hooks docker
|
||||||
|
|
||||||
BINARY := dnswatcher
|
BINARY := dnswatcher
|
||||||
# `make build VERSION=...` overrides this; the Dockerfile does so, as the
|
|
||||||
# image has no .git to describe.
|
|
||||||
VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
|
VERSION := $(shell git describe --tags --always --dirty 2>/dev/null || echo "dev")
|
||||||
LDFLAGS := -X main.Version=$(VERSION)
|
LDFLAGS := -X main.Version=$(VERSION)
|
||||||
|
|
||||||
|
|||||||
@@ -489,8 +489,7 @@ them. We provide:
|
|||||||
- `script/check` — run test, lint, and fmt-check
|
- `script/check` — run test, lint, and fmt-check
|
||||||
- `script/docker` — build the Docker image tagged via `script/projectname`, with
|
- `script/docker` — build the Docker image tagged via `script/projectname`, with
|
||||||
`--no-cache-filter=lint,builder` so the lint stage and the builder stage,
|
`--no-cache-filter=lint,builder` so the lint stage and the builder stage,
|
||||||
which runs the tests, run on every invocation, and with the version from
|
which runs the tests, run on every invocation
|
||||||
`git describe` passed as `--build-arg VERSION`
|
|
||||||
- `script/cibuild` — CI entrypoint: `docker build` with
|
- `script/cibuild` — CI entrypoint: `docker build` with
|
||||||
`--no-cache-filter=lint,builder`, so the lint stage and the builder stage,
|
`--no-cache-filter=lint,builder`, so the lint stage and the builder stage,
|
||||||
which runs the tests, run on every invocation, because a cached build lints
|
which runs the tests, run on every invocation, because a cached build lints
|
||||||
@@ -512,14 +511,11 @@ make clean # Remove build artifacts
|
|||||||
|
|
||||||
### Build-Time Variables
|
### Build-Time Variables
|
||||||
|
|
||||||
`make build` sets the version with `-ldflags "-X main.Version=..."`, taking
|
Version is injected via `-ldflags`:
|
||||||
it from `git describe --tags --always --dirty`, or from `VERSION` when given
|
|
||||||
on the command line (`make build VERSION=1.2.3`). The version appears in the
|
|
||||||
startup log and in the health check response.
|
|
||||||
|
|
||||||
The Docker image has no `.git`, so the `Dockerfile` takes the version as
|
```sh
|
||||||
`--build-arg VERSION`. `make docker` passes it; a plain `docker build`
|
go build -ldflags "-X main.Version=$(git describe --tags --always)" ./cmd/dnswatcher
|
||||||
passes none, and that image reports `dev`.
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -22,10 +22,6 @@ https://git.eeqj.de/sneak/dnswatcher/issues/104
|
|||||||
|
|
||||||
- 2026-10-01: `/metrics` allows each client address 30 requests a minute,
|
- 2026-10-01: `/metrics` allows each client address 30 requests a minute,
|
||||||
counted before Basic Auth, and answers 429 beyond that (closes #101).
|
counted before Basic Auth, and answers 429 beyond that (closes #101).
|
||||||
- 2026-10-01: the image built by `make docker` reports the `git describe`
|
|
||||||
version, not `dev`, and the startup log now shows it (closes #109).
|
|
||||||
- 2026-10-01: two notify shutdown tests always release the delivery they hold,
|
|
||||||
so a drain that returns early fails them instead of hanging (closes #176).
|
|
||||||
- 2026-10-01: `script/install-precommit` asks git for the repository's git
|
- 2026-10-01: `script/install-precommit` asks git for the repository's git
|
||||||
directory, so `make hooks` also works where `.git` is a file (closes #129).
|
directory, so `make hooks` also works where `.git` is a file (closes #129).
|
||||||
- 2026-10-01: `TODO.md` brought up to date: open issues listed by URL, every
|
- 2026-10-01: `TODO.md` brought up to date: open issues listed by URL, every
|
||||||
@@ -99,6 +95,7 @@ https://git.eeqj.de/sneak/dnswatcher/issues/104
|
|||||||
https://git.eeqj.de/sneak/dnswatcher/issues/107
|
https://git.eeqj.de/sneak/dnswatcher/issues/107
|
||||||
- invalid DNS or TLS interval silently replaced by the default:
|
- invalid DNS or TLS interval silently replaced by the default:
|
||||||
https://git.eeqj.de/sneak/dnswatcher/issues/177
|
https://git.eeqj.de/sneak/dnswatcher/issues/177
|
||||||
|
- images report version `dev`: https://git.eeqj.de/sneak/dnswatcher/issues/109
|
||||||
- trial run of the finished image:
|
- trial run of the finished image:
|
||||||
https://git.eeqj.de/sneak/dnswatcher/issues/149
|
https://git.eeqj.de/sneak/dnswatcher/issues/149
|
||||||
- 1.0 readiness: run it with a real config and read the logs:
|
- 1.0 readiness: run it with a real config and read the logs:
|
||||||
@@ -106,6 +103,8 @@ https://git.eeqj.de/sneak/dnswatcher/issues/104
|
|||||||
- `goimports` in `make fmt-check`, Markdown formatting:
|
- `goimports` in `make fmt-check`, Markdown formatting:
|
||||||
https://git.eeqj.de/sneak/dnswatcher/issues/119
|
https://git.eeqj.de/sneak/dnswatcher/issues/119
|
||||||
- final state save at shutdown: https://git.eeqj.de/sneak/dnswatcher/issues/114
|
- final state save at shutdown: https://git.eeqj.de/sneak/dnswatcher/issues/114
|
||||||
|
- `internal/notify` shutdown tests hang when a drain returns early:
|
||||||
|
https://git.eeqj.de/sneak/dnswatcher/issues/176
|
||||||
- README accuracy sweep: https://git.eeqj.de/sneak/dnswatcher/issues/108
|
- README accuracy sweep: https://git.eeqj.de/sneak/dnswatcher/issues/108
|
||||||
- README sections required by policy:
|
- README sections required by policy:
|
||||||
https://git.eeqj.de/sneak/dnswatcher/issues/173
|
https://git.eeqj.de/sneak/dnswatcher/issues/173
|
||||||
|
|||||||
@@ -63,7 +63,6 @@ func main() {
|
|||||||
return n
|
return n
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
fx.Invoke(func(l *logger.Logger) { l.Identify() }),
|
|
||||||
fx.Invoke(func(*server.Server, *watcher.Watcher) {}),
|
fx.Invoke(func(*server.Server, *watcher.Watcher) {}),
|
||||||
).Run()
|
).Run()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,12 +143,6 @@ func TestDrainWaitsForInFlightDelivery(t *testing.T) {
|
|||||||
srv := blockingNtfyServer(entered, release, &served)
|
srv := blockingNtfyServer(entered, release, &served)
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
|
||||||
// srv.Close waits for the handler, so release it however the
|
|
||||||
// test ends; otherwise a drain that returns early hangs the
|
|
||||||
// package instead of failing this test.
|
|
||||||
releaseHandler := sync.OnceFunc(func() { close(release) })
|
|
||||||
defer releaseHandler()
|
|
||||||
|
|
||||||
topicURL, _ := url.Parse(srv.URL)
|
topicURL, _ := url.Parse(srv.URL)
|
||||||
|
|
||||||
svc := notify.NewTestService(http.DefaultTransport)
|
svc := notify.NewTestService(http.DefaultTransport)
|
||||||
@@ -173,7 +167,9 @@ func TestDrainWaitsForInFlightDelivery(t *testing.T) {
|
|||||||
// delay alone.
|
// delay alone.
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
|
|
||||||
timer := time.AfterFunc(inFlightHold, releaseHandler)
|
timer := time.AfterFunc(inFlightHold, func() {
|
||||||
|
close(release)
|
||||||
|
})
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(
|
ctx, cancel := context.WithTimeout(
|
||||||
@@ -272,7 +268,7 @@ func TestDrainBoundedByContextDeadline(t *testing.T) {
|
|||||||
// all never returns here (the delivery is parked in a backoff
|
// all never returns here (the delivery is parked in a backoff
|
||||||
// that never fires), so an unbounded drain must fail this
|
// that never fires), so an unbounded drain must fail this
|
||||||
// test promptly instead of hanging the package until the test
|
// test promptly instead of hanging the package until the test
|
||||||
// binary's -timeout.
|
// binary's 30s timeout.
|
||||||
returned := make(chan struct{})
|
returned := make(chan struct{})
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
@@ -451,11 +447,6 @@ func TestNewRegistersDrainingStopHook(t *testing.T) {
|
|||||||
srv := blockingNtfyServer(entered, release, &served)
|
srv := blockingNtfyServer(entered, release, &served)
|
||||||
defer srv.Close()
|
defer srv.Close()
|
||||||
|
|
||||||
// As in TestDrainWaitsForInFlightDelivery: release the handler
|
|
||||||
// however the test ends, before srv.Close waits for it.
|
|
||||||
releaseHandler := sync.OnceFunc(func() { close(release) })
|
|
||||||
defer releaseHandler()
|
|
||||||
|
|
||||||
lifecycle := &recordingLifecycle{}
|
lifecycle := &recordingLifecycle{}
|
||||||
svc := newNotifyService(t, lifecycle, srv.URL)
|
svc := newNotifyService(t, lifecycle, srv.URL)
|
||||||
|
|
||||||
@@ -481,7 +472,9 @@ func TestNewRegistersDrainingStopHook(t *testing.T) {
|
|||||||
t.Fatal("delivery never reached the endpoint")
|
t.Fatal("delivery never reached the endpoint")
|
||||||
}
|
}
|
||||||
|
|
||||||
timer := time.AfterFunc(inFlightHold, releaseHandler)
|
timer := time.AfterFunc(inFlightHold, func() {
|
||||||
|
close(release)
|
||||||
|
})
|
||||||
defer timer.Stop()
|
defer timer.Stop()
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(
|
ctx, cancel := context.WithTimeout(
|
||||||
|
|||||||
+1
-9
@@ -12,15 +12,7 @@ ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
|
|||||||
|
|
||||||
main() {
|
main() {
|
||||||
cd "$ROOT"
|
cd "$ROOT"
|
||||||
# Own line: a failing command substitution inside an argument does
|
docker build --no-cache-filter=lint,builder -t "$("$SCRIPT_DIR/projectname")" .
|
||||||
# not trip `set -e`, so the inline form degrades silently to an
|
|
||||||
# empty constant. VERSION is computed here because .dockerignore
|
|
||||||
# excludes .git, so `git describe` in a build stage cannot find it.
|
|
||||||
version="$(git describe --tags --always --dirty 2>/dev/null || true)"
|
|
||||||
[ -n "$version" ] || version="unknown"
|
|
||||||
docker build --no-cache-filter=lint,builder \
|
|
||||||
--build-arg VERSION="$version" \
|
|
||||||
-t "$("$SCRIPT_DIR/projectname")" .
|
|
||||||
}
|
}
|
||||||
|
|
||||||
main "$@"
|
main "$@"
|
||||||
|
|||||||
Reference in New Issue
Block a user