Artifact e9d3647e777c162914edcd68f822ab8b26439aa5af6ab52950c69e574accc99d:
- File
.github/workflows/test.yml
— part of check-in
[b2dcbb7130]
at
2026-10-25 23:02:28
on branch main
— ci: check gofmt; format the tree
Sixteen files had drifted from gofmt: struct and comment alignment, one-line if bodies in auth_test.go, trailing blank lines, and a blank comment line gofmt now puts before an indented block in two delta.go doc comments. The test job now fails on any tracked .go file gofmt would change, and lists it. (user: [email protected], size: 14646) [annotate] [blame] [check-ins using] [more...]
name: Tests on: push: branches: [main] pull_request: env: # The canonical fossil the real-fossil-gated tests compare against. Local # development validates against this exact version, so CI must too -- # otherwise the two are checking our output against different reference # implementations. Bump deliberately, here, in one place. # # The distro package is unusable for this: it is unpinned, currently lags # several releases behind, and tracks different upstream check-ins over time # under the same version string, so two runs at nominally the same version # can behave differently. The official upstream release tarball is a fixed # build, and FOSSIL_SHA256 pins it to that exact artifact -- a re-upload # upstream then fails the checksum loudly instead of silently changing what # we test against. FOSSIL_VERSION: "2.28" FOSSIL_SHA256: "c9d2bf9d150dff1076eae1b0b822ed3cde892e1273f78b040c4f8ace1b59dd40" # zit, the Zig fossil, pinned the same way: the release tarball from zit's # own server, checked against the release's SHA256SUMS. The interop and # horizon-seed tests compare bytes with it, so a missing zit must fail the # run, not skip it. ZIT_VERSION: "0.7.3" ZIT_SHA256: "ee88d811170283bb8e348ef35eda8eb1b499473e4a2f74d995271212e02cf4b7" jobs: test: name: Test (modernc) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version-file: go.mod - name: Install pinned Fossil run: | curl -fsSL --retry 3 --retry-delay 2 --retry-all-errors \ -o /tmp/fossil.tar.gz \ "https://fossil-scm.org/home/uv/fossil-linux-x64-${FOSSIL_VERSION}.tar.gz" echo "${FOSSIL_SHA256} /tmp/fossil.tar.gz" | sha256sum -c - sudo tar -xzf /tmp/fossil.tar.gz -C /usr/local/bin fossil rm -f /tmp/fossil.tar.gz - name: Verify Fossil version # A silent upstream change has to surface as an explicit failure here, # not as mysterious behavioural drift in the real-fossil-gated tests. run: | reported=$(fossil version | sed -n 's/.*fossil version \([0-9][0-9.]*\).*/\1/p') if [ "$reported" != "${FOSSIL_VERSION}" ]; then echo "expected fossil ${FOSSIL_VERSION}, got: $(fossil version)" >&2 exit 1 fi fossil version - name: Install pinned zit run: | curl -fsSL --retry 3 --retry-delay 2 --retry-all-errors \ -o /tmp/zit.tar.gz \ "https://fossil.craftdesign.group/zit/uv/releases/${ZIT_VERSION}/zit-${ZIT_VERSION}-linux-x86_64.tar.gz" echo "${ZIT_SHA256} /tmp/zit.tar.gz" | sha256sum -c - sudo tar -xzf /tmp/zit.tar.gz -C /usr/local/bin --strip-components=1 "zit-${ZIT_VERSION}/zit" rm -f /tmp/zit.tar.gz zit version - name: Warm Fossil global config # Fossil keeps a per-user global config database outside any repository # and creates it lazily on first use. `go test` runs packages # concurrently, several of them shell out to fossil, and nothing sets # HOME, so on a fresh runner two test processes can race to create it: # one wins and the others die with "table global_config already exists". # Creating it once here, single-threaded, means no test process is ever # the one to create it. `fossil version` does not open that database, so # the step above does not incidentally cover this; `fossil all list` # does, and prints nothing. # # The first call's exit status is ignored deliberately -- it exists to # create the database, not to assert anything, so an unrelated non-zero # must not red the job. The second call is what carries the weight: it # must succeed on its own, which proves the database is both present and # usable. Checking that a file exists would not -- a truncated or # partially-written database passes an existence check while concurrent # invocations still die on the missing schema, which is exactly the # "looks like protection while the race stays live" failure this guards # against. Re-running the command also keeps the check independent of # where fossil resolved the database to (~/.fossil, ~/.config/fossil.db, # $XDG_CONFIG_HOME, or $FOSSIL_HOME). run: | fossil all list >/dev/null 2>&1 || true fossil all list >/dev/null - name: Build all packages # Build every package, not just the cmd/libfossil dependency closure. # The `go test $(go list ./...)` step below silently drops any package # that fails to compile (go list omits it from stdout instead of # failing), so a broken import can vanish from the test run undetected. # Building `./...` first makes that a loud, fail-fast build error. run: GOWORK=off go build ./... - name: Unit tests # REQUIRE_FOSSIL_BIN turns "fossil is missing" into a failure rather # than an invisible skip. Verifying a real fossil reads what we write # is the one thing our own tests cannot substitute for. env: REQUIRE_FOSSIL_BIN: "1" REQUIRE_ZIT_BIN: "1" # zit 0.7.2 and later date a seed at the repository's latest tag event, so # the seed byte-identity test over a cancelled tag must not skip. REQUIRE_ZIT_SEED_DATE: "1" run: GOWORK=off go test $(GOWORK=off go list ./... | grep -v '/dst') -count=1 -timeout=300s - name: DST run: GOWORK=off go test ./dst/... -count=1 -timeout=300s - name: Driver tests (modernc) run: cd db/driver/modernc && GOWORK=off go test ./... -count=1 - name: Format run: | unformatted=$(gofmt -l $(git ls-files '*.go')) if [ -n "$unformatted" ]; then echo "$unformatted" echo "run gofmt -w on the files above" >&2 exit 1 fi - name: Vet run: GOWORK=off go vet ./... test-ncruces: name: Test (ncruces) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version-file: go.mod - name: Install pinned Fossil run: | curl -fsSL --retry 3 --retry-delay 2 --retry-all-errors \ -o /tmp/fossil.tar.gz \ "https://fossil-scm.org/home/uv/fossil-linux-x64-${FOSSIL_VERSION}.tar.gz" echo "${FOSSIL_SHA256} /tmp/fossil.tar.gz" | sha256sum -c - sudo tar -xzf /tmp/fossil.tar.gz -C /usr/local/bin fossil rm -f /tmp/fossil.tar.gz - name: Verify Fossil version # A silent upstream change has to surface as an explicit failure here, # not as mysterious behavioural drift in the real-fossil-gated tests. run: | reported=$(fossil version | sed -n 's/.*fossil version \([0-9][0-9.]*\).*/\1/p') if [ "$reported" != "${FOSSIL_VERSION}" ]; then echo "expected fossil ${FOSSIL_VERSION}, got: $(fossil version)" >&2 exit 1 fi fossil version - name: Warm Fossil global config # Same single-threaded warm-up as the modernc leg -- see the comment # there for why `fossil version` does not cover this, and why the first # call's exit status is ignored but the second call's is not. run: | fossil all list >/dev/null 2>&1 || true fossil all list >/dev/null - name: Build all packages (ncruces) # Same fail-fast guard as the modernc leg, under the test_ncruces tag so # the ncruces driver's compile surface is covered too. run: GOWORK=off go build -tags test_ncruces ./... - name: Unit tests (ncruces) env: REQUIRE_FOSSIL_BIN: "1" run: GOWORK=off go test -tags test_ncruces $(GOWORK=off go list ./... | grep -v '/dst') -count=1 -timeout=300s - name: DST (ncruces) run: GOWORK=off go test -tags test_ncruces ./dst/... -count=1 -timeout=300s - name: Driver tests (ncruces) run: cd db/driver/ncruces && GOWORK=off go test ./... -count=1 build-wasm: name: Build (js/wasm) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version-file: go.mod - name: Build main module for js/wasm # Browser support is the reason the ncruces driver is in this repo at # all, but until this job nothing was ever compiled for js/wasm. # # What a build gate catches is a dependency with no js/wasm build at # all -- most realistically the wrong SQLite driver reaching a shared # package, since modernc.org/libc is linux/darwin-only and would fail # here while both linux legs above stay green. It does not catch every # WASM problem: much of the stdlib (os/exec included) compiles for js # behind stubs and only fails when called, so runtime-behaviour gaps # need tests under a browser harness, which is a separate question. # # test_ncruces is the same tag the ncruces leg builds under. It switches # both internal/testdriver and cmd/libfossil from modernc to ncruces, # which is the driver that can actually target WASM. Without the tag, # both packages would pull modernc into this build. # # The package set comes from `go list`, not a hand-written list, so a # newly added package is inside the gate by default rather than # silently outside it. `-e` stops go list from aborting on the package # excluded below -- without it that unresolvable import would # discard the entire list. Packages that already declare `//go:build # !js` in source (internal/stash, internal/undo) are dropped by go list # itself under GOOS=js; that exclusion lives in the code, not here. # # The only exclusion is examples/embed-repo-api: its main package # imports the modernc driver directly, and modernc.org/libc ships no # js/wasm build. cmd/libfossil is deliberately built here with the # test_ncruces binding, so this gate compiles the tagged CLI for WASM. # examples/embed-repo-api stays fully covered by the linux legs above. env: GOWORK: "off" GOOS: js GOARCH: wasm run: | set -o pipefail pkgs=$(go list -e -tags test_ncruces ./... \ | grep -v -e '/examples/embed-repo-api$') echo "building $(echo "$pkgs" | wc -l) packages for js/wasm:" echo "$pkgs" echo "$pkgs" | xargs go build -tags test_ncruces - name: Build ncruces driver for js/wasm # A separate module, so the step above never reaches it -- and it is # the driver the browser build actually runs on. Its js-only source # (ncruces_js.go) is compiled by no other job in this workflow. env: GOWORK: "off" GOOS: js GOARCH: wasm run: cd db/driver/ncruces && go build ./... build-tinygo: name: Build (tinygo) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version-file: go.mod - name: Install TinyGo # The release's own .deb, pinned: TinyGo releases change what compiles # and how large the output is, so the gate moves only on purpose. run: | curl -sSfL -o tinygo.deb https://github.com/tinygo-org/tinygo/releases/download/v0.43.0/tinygo_0.43.0_amd64.deb sudo dpkg -i tinygo.deb tinygo version - name: Build examples/tinygo for wasm # The whole public API, sync and signing included, must keep compiling # under TinyGo: applications ship it to browsers and edge runtimes that # way. A standard-library feature TinyGo lacks fails here, not in an # embedder's build. env: GOWORK: "off" run: | tinygo build -target=wasm -no-debug -opt=z -stack-size=1MB -o libfossil.wasm ./examples/tinygo/ echo "raw $(wc -c < libfossil.wasm) bytes, gzip -9 $(gzip -9c libfossil.wasm | wc -c) bytes" test-otel: name: Test (observer/otel) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version-file: go.mod - name: OTel sub-module tests run: cd observer/otel && GOWORK=off go test ./... -count=1 test-docs: name: Test (docs/site) runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version-file: go.mod - name: Install Hugo (extended) # docs/site pulls the hextra theme via Hugo Modules, which need both the # Go toolchain (setup-go above) and the Hugo binary. Pin the version so a # future Hugo release can't silently change build behaviour under us. env: HUGO_VERSION: "0.162.1" run: | curl -fsSL "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.tar.gz" \ | sudo tar -xz -C /usr/local/bin hugo - name: Generated docs are current # The landing page's hero figure and conformance table, the CLI # reference and llms*.txt are generated from the code (a real engine # run, TestCoverage, the libfossil binary's --help, the content tree) # and committed. Regenerate them into a scratch dir and fail if any # differs, so the site cannot drift from the code it describes. The # llms check also validates llms.txt's shape and the packages its # header names. Fix with `make docs-gen`. env: GOWORK: "off" run: | ./scripts/check-llms-txt.sh ./scripts/check-docs-generated.sh - name: Build docs site # docs/site is the one module with no Go source of its own: its go.mod # exists only to import the hextra theme as a Hugo Module, so `go build # ./...` there matches no packages and gates nothing. A real Hugo build # is the equivalent compile gate — it resolves the module import, # compiles templates, and renders content, failing loud on a broken # import or template the way the Go build steps do for the other modules. run: cd docs/site && GOWORK=off hugo --gc --minify