Artifact 2949f1f1bcabdaba998e4a8f42649ccbd360aa42bf68b5d9d2aab77ebc112717:
- File
.github/workflows/test.yml
— part of check-in
[0c30e0d32e]
at
2026-10-24 16:39:16
on branch main
— ci: pin zit interop to 0.7.2 and require the seed-date test
zit 0.7.2 (tag version-0.7.2, check-in 1dcb2d4a29) dates a seed at the repository's latest tag event, as go-libfossil now does. Its horizon draft is the caeef421ee text pinned here (artifact ab18fa7f89).
- ZIT_VERSION is 0.7.2, and ZIT_SHA256 is the checksum of zit-0.7.2-linux-x86_64.tar.gz, checked against the release's SHA256SUMS. - REQUIRE_ZIT_SEED_DATE=1 sits next to REQUIRE_ZIT_BIN, so TestHorizonSeedDateZit cannot skip in CI. - The README, horizons.md, CHANGELOG and test comments now say interop is pinned to zit 0.7.2. (user: [email protected], size: 14384) [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.2" ZIT_SHA256: "9f328fa107723353a5625cc32d834255922e855bba684dbcfe47557b6f13f3df" 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 dates 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: 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