3 Commits
Author SHA1 Message Date
clawbot 464ba8ccda Exit with the shutdown's code and wait for image processing (closes #86)
check / check (push) Successful in 12m43s
fx alone handles SIGINT and SIGTERM; the server's own handler, which
only cancelled a context that fx's stop did not wait for, is gone.
fx's Run exits with the shutdown's code: the one a shutdown request
carries, 0 for a signal, 1 when the app fails to start or stop.
A listen error asks fx to shut down with exit code 1. A Sentry DSN that
cannot be used fails the server's start hook, so fx stops what had
already started. The server's stop hook stops the HTTP server, then
waits for the images still being processed, both within
ShutdownTimeout; images still being processed after that are logged and
fail the stop, so the exit code is 1.

Model: opus-5-5
2026-10-04 01:59:43 +00:00
clawbot 6c38e0aec5 Test shutdown exit codes, Sentry startup failure and the processing wait
These tests fail until the change that follows: WaitForProcessing does
not exist yet, the server has no shutdowner, and a Sentry DSN that
cannot be used exits the process from a goroutine instead of failing
the server's start hook.

A listen error must ask fx to shut down with exit code 1.
WaitForProcessing must wait for an image being processed and report it
when its context ends first.

Model: opus-5-5
2026-10-04 01:59:10 +00:00
clawbot b402eaf88c Run the checks on every script/cibuild and script/docker build (closes #101)
check / check (push) Successful in 12m55s
Both scripts pass a new CHECK_EPOCH, which the Dockerfile's make
fmt-check, make lint and make test steps name in their commands. On an
unchanged tree Docker used to serve those steps from its build cache, so
a run could pass without checking anything. The script/bootstrap steps
stay cached. A plain docker build . still works, as upaas builds the
image that way: it leaves CHECK_EPOCH empty and reuses the check steps
only for an identical build context.

Model: opus-5-5
2026-10-04 03:58:35 +02:00
6 changed files with 39 additions and 16 deletions
+11 -5
View File
@@ -18,9 +18,14 @@ COPY . .
# Tells script/lint it is inside a container, so it runs the linter. # Tells script/lint it is inside a container, so it runs the linter.
ENV container=docker ENV container=docker
# Run formatting check and linter # Run formatting check and linter. script/cibuild and script/docker pass
RUN make fmt-check # a new CHECK_EPOCH on every run, and each check step names it in its
RUN make lint # command, so a new value reruns the step instead of reusing a cached
# success that checked nothing. A plain `docker build .` leaves it empty
# and reuses the check steps only for an identical build context.
ARG CHECK_EPOCH
RUN echo "check epoch: ${CHECK_EPOCH}" && make fmt-check
RUN echo "check epoch: ${CHECK_EPOCH}" && make lint
# Build stage # Build stage
# golang:1.25.4-alpine, 2026-02-25 # golang:1.25.4-alpine, 2026-02-25
@@ -39,8 +44,9 @@ RUN script/bootstrap
# Copy source code # Copy source code
COPY . . COPY . .
# Run tests # Run tests; a new CHECK_EPOCH reruns them, as in the lint stage.
RUN make test ARG CHECK_EPOCH
RUN echo "check epoch: ${CHECK_EPOCH}" && make test
# VERSION is declared here, not earlier: a new value reruns only the # VERSION is declared here, not earlier: a new value reruns only the
# build, not script/bootstrap or the tests. Given none, the version is # build, not script/bootstrap or the tests. Given none, the version is
+3 -2
View File
@@ -353,8 +353,9 @@ 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` - `script/docker` — build the Docker image tagged via `script/projectname`
- `script/docker-smoke` — build the image, start it, wait for it to be healthy - `script/docker-smoke` — build the image, start it, wait for it to be healthy
- `script/cibuild` — CI entrypoint: `docker build .` (the Dockerfile - `script/cibuild` — CI entrypoint: `docker build .` with a new
runs the checks, so a green build implies a green repo) `CHECK_EPOCH` on every run, so the Dockerfile's checks run instead of
coming from the build cache, and a green run implies a green repo
- `script/precommit` — pre-commit checks (`go mod tidy` guard, then - `script/precommit` — pre-commit checks (`go mod tidy` guard, then
`script/check`) `script/check`)
- `script/install-precommit` — install the git pre-commit hook that - `script/install-precommit` — install the git pre-commit hook that
+9
View File
@@ -40,6 +40,15 @@ P2: security: referer blacklist
used fails startup, so the stop hooks of what had already started run, used fails startup, so the stop hooks of what had already started run,
instead of exiting the process from a goroutine; the eviction loop is left to instead of exiting the process from a goroutine; the eviction loop is left to
#102. #102.
- 2026-10-03 every `script/cibuild` and `script/docker` run executes the checks
(closes #101): the `Dockerfile` declares `CHECK_EPOCH` above `make fmt-check`
and `make lint` in the lint stage and above `make test` in the build stage,
and each of those steps names it in its command; both scripts pass a new value
on every run, so Docker runs the checks instead of reusing cached results,
while the `script/bootstrap` steps stay cached; a plain `docker build .` still
works, leaves it empty, and reuses the check steps only for an identical build
context; the `script/cibuild` comment and `README.md` no longer say that any
successful build implies a green repo.
- 2026-09-29 share concurrent misses (closes #65): requests that miss the same - 2026-09-29 share concurrent misses (closes #65): requests that miss the same
variant at once (the same cache key, so quality and fit included) share one variant at once (the same cache key, so quality and fit included) share one
upstream fetch or cached source read and one transcode through upstream fetch or cached source read and one transcode through
+2 -2
View File
@@ -333,8 +333,8 @@ func FormatToMIME(format Format) string {
// WaitForProcessing waits until no image is being processed, or until ctx // WaitForProcessing waits until no image is being processed, or until ctx
// ends, and returns how many images were still being processed then. It // ends, and returns how many images were still being processed then. It
// waits by taking every slot in processingSemaphore as it frees up, so no // waits by taking each slot in processingSemaphore as it frees up until it
// new image starts meanwhile, and gives them all back before it returns. // holds them all, or until ctx ends, then gives back the slots it took.
func (p *ImageProcessor) WaitForProcessing(ctx context.Context) int { func (p *ImageProcessor) WaitForProcessing(ctx context.Context) int {
taken := 0 taken := 0
+7 -4
View File
@@ -1,15 +1,18 @@
#!/bin/sh #!/bin/sh
# script/cibuild: run the CI build. The Dockerfile runs the checks # script/cibuild: run the CI build. The Dockerfile runs the checks
# (make fmt-check, lint, test), so a successful build implies a green # (make fmt-check, lint, test) as build steps. This script passes a new
# repo. Generic: needs no adaptation. The Gitea workflow runs this on # CHECK_EPOCH on every run, so Docker runs those steps instead of
# push. # reusing cached results: a successful run means the checks ran and
# passed on this tree. Generic: needs no adaptation. The Gitea workflow
# runs this on push.
set -eu set -eu
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)" ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
main() { main() {
cd "$ROOT" cd "$ROOT"
docker build . epoch="$(date +%s)$$"
docker build --build-arg CHECK_EPOCH="$epoch" .
} }
main "$@" main "$@"
+7 -3
View File
@@ -1,7 +1,9 @@
#!/bin/sh #!/bin/sh
# script/docker: build the Docker image tagged with the project name. # script/docker: build the Docker image tagged with the project name.
# Identical in all repos; the tag comes from script/projectname. # Identical in all repos; the tag comes from script/projectname. Like
# Generic: needs no adaptation. # script/cibuild, it passes a new CHECK_EPOCH, so the build runs the
# checks instead of reusing cached results. Generic: needs no
# adaptation.
set -eu set -eu
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
@@ -9,7 +11,9 @@ ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
main() { main() {
cd "$ROOT" cd "$ROOT"
docker build -t "$("$SCRIPT_DIR/projectname")" . epoch="$(date +%s)$$"
docker build --build-arg CHECK_EPOCH="$epoch" \
-t "$("$SCRIPT_DIR/projectname")" .
} }
main "$@" main "$@"