ci: Add go 1.26 to the supported version list

Adds Go 1.26 to go_supported so that Gitaly is built and tested against it. The 1.26 images are already published by gitlab-build-images, but our matrix only exercised 1.25.

Doing so surfaced three problems, fixed here.

Go 1.26 test failures

Two failures are caused by changes in Go 1.26 itself. Both fixes are also correct on Go 1.25, so nothing is version-gated.

  1. testhelper.timeoutContext.Err() resolved the cancellation cause with context.Cause(c), passing the wrapper itself. Go 1.26 reordered context.Cause() so that it now starts by calling c.Err(), which turned that into an Err() -> Cause() -> Err() cycle ending in fatal error: stack overflow. Every test using ContextWithSimulatedTimeout() crashed, in internal/limiter and internal/gitaly/service/hook. The cause is now resolved via the embedded context, which is the one created by context.WithCancelCause().

  2. TestGetDuration compared errors with require.Equal(), which compares the wrapped error values structurally. Go 1.26 changed time.ParseDuration() to return a *time.parseDurationError instead of an *errors.errorString, so the comparison failed even though both errors render the same message. The test now compares error messages.

FIPS jobs running out of tmpfs

test:fips: [test-with-praefect, YesPlease, 1.26] failed consistently with No space left on device, which surfaced indirectly as a flood of praefect does not exist and gitaly-hooks does not exist failures.

test:fips overrides TEST_OPTIONS and thereby drops the -p=4 that the Makefile sets, so go test falls back to GOMAXPROCS for -p, which is 32 on the FIPS runners. Each concurrently running package builds its own set of Gitaly binaries into ${TEST_TMP_DIR} via testcfg.BuildBinary(). Those are hard-linked within a test process but not across packages, so every package holds roughly 350MB of a 10GB tmpfs.

The full suite was measured on the FIPS runner with both Go versions, sampling tmpfs usage and the number of concurrent test directories:

Go Cache Peak tmpfs Pkgs
1.25.12 cold 4503 MB 13
1.25.12 warm 6359 MB 29
1.26.5 cold 8453 MB 32
1.26.5 warm 6772 MB 29

Go 1.26 does not use more space per package. Binaries are within 1% of the 1.25 ones, and with a warm cache both versions behave identically. It builds the cold suite faster and overlaps building with running more, so it reaches the fan-out that was always configured, whereas the slower cold build in Go 1.25 held concurrency at about 13 by accident. The FIPS jobs always run with a cold cache, which is why this failed on every run rather than intermittently.

Note that 1.25 was not safe here either, only slower: its warm-cache run already reached 6359MB against the same 10GB limit.

Candidate -p values were then measured with this job's real configuration, including --rerun-fails, and sampled twice a second, because two-second sampling understates the transient peaks during linking by roughly a factor of two:

-p Run Peak tmpfs Min MemAvailable
16 1 8635 MB 3152 MB
16 2 8618 MB 8838 MB
16 3 8497 MB 9446 MB
8 1 7230 MB 13356 MB
8 2 7262 MB 13635 MB

-p=8 is used here. It leaves 2.8GB of the tmpfs unused where 16 leaves 1.4GB, and it keeps a comfortable memory margin: the runners have 31.8GB and no swap, and the tmpfs is RAM backed, so one of the 16 runs dropped to 3.1GB available. It also matches what the non-FIPS runners do implicitly, as they have 8 cores. The cost is about 35 seconds.

Relates to #7356 (closed)

Edited by Mustafa Bayar

Merge request reports

Loading
Loading