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.
ENV container=docker
# Run formatting check and linter
RUN make fmt-check
RUN make lint
# Run formatting check and linter. script/cibuild and script/docker pass
# a new CHECK_EPOCH on every run, and each check step names it in its
# 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
# golang:1.25.4-alpine, 2026-02-25
@@ -39,8 +44,9 @@ RUN script/bootstrap
# Copy source code
COPY . .
# Run tests
RUN make test
# Run tests; a new CHECK_EPOCH reruns them, as in the lint stage.
ARG CHECK_EPOCH
RUN echo "check epoch: ${CHECK_EPOCH}" && make test
# VERSION is declared here, not earlier: a new value reruns only the
# 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/docker` — build the Docker image tagged via `script/projectname`
- `script/docker-smoke` — build the image, start it, wait for it to be healthy
- `script/cibuild` — CI entrypoint: `docker build .` (the Dockerfile
runs the checks, so a green build implies a green repo)
- `script/cibuild` — CI entrypoint: `docker build .` with a new
`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/check`)
- `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,
instead of exiting the process from a goroutine; the eviction loop is left to
#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
variant at once (the same cache key, so quality and fit included) share one
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
// 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
// new image starts meanwhile, and gives them all back before it returns.
// waits by taking each slot in processingSemaphore as it frees up until it
// holds them all, or until ctx ends, then gives back the slots it took.
func (p *ImageProcessor) WaitForProcessing(ctx context.Context) int {
taken := 0
+7 -4
View File
@@ -1,15 +1,18 @@
#!/bin/sh
# script/cibuild: run the CI build. The Dockerfile runs the checks
# (make fmt-check, lint, test), so a successful build implies a green
# repo. Generic: needs no adaptation. The Gitea workflow runs this on
# push.
# (make fmt-check, lint, test) as build steps. This script passes a new
# CHECK_EPOCH on every run, so Docker runs those steps instead of
# 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
ROOT="$(cd "$(dirname "$0")/.." && pwd -P)"
main() {
cd "$ROOT"
docker build .
epoch="$(date +%s)$$"
docker build --build-arg CHECK_EPOCH="$epoch" .
}
main "$@"
+7 -3
View File
@@ -1,7 +1,9 @@
#!/bin/sh
# script/docker: build the Docker image tagged with the project name.
# Identical in all repos; the tag comes from script/projectname.
# Generic: needs no adaptation.
# Identical in all repos; the tag comes from script/projectname. Like
# 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
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd -P)"
@@ -9,7 +11,9 @@ ROOT="$(cd "$SCRIPT_DIR/.." && pwd -P)"
main() {
cd "$ROOT"
docker build -t "$("$SCRIPT_DIR/projectname")" .
epoch="$(date +%s)$$"
docker build --build-arg CHECK_EPOCH="$epoch" \
-t "$("$SCRIPT_DIR/projectname")" .
}
main "$@"