feat: buildvars registry + extension hooks + FIPS-awareness + test-infra resilience#9691
feat: buildvars registry + extension hooks + FIPS-awareness + test-infra resilience#9691
Conversation
Replace hardcoded binary/image literals with lookups through a typed registry populated at build time. Introduces buildvars package, renames cmd/buildvarprint -> cmd/buildvars, aligns Go identifier ExtraBuildTags -> PrivateBuildTags. Migrates hardcoded call sites in contrib/jepsen, testutil/exec, dgraphtest/dgraph, and systest scripts.
…o build -o Allow BIN path override via environment. Expand jemalloc detection to handle both install prefixes. Switch dgraph and t Makefiles to 'go build -o' for explicit output paths.
Namespace-aware restore depends on Linux-only kernel features. Guard the test file with //go:build linux so Darwin CI does not fail.
Add untagged package-level FIPSEnabled var so non-FIPS builds can still reference x.FIPSEnabled. Add FIPSBinary() returning whether the dgraph binary under test is a FIPS build (via DGRAPH_FIPS_BINARY env var). Enables FIPS-aware test skips without tag-guarded symbols.
…hooks Relocate environment-assembly and plugin-build logic behind extension hooks so downstream forks can layer FIPS-aware variants without patching upstream helpers. Hooks default to the existing behavior.
…File Extract compose-file selection and cluster image-resolution behind hooks so downstream forks can insert FIPS- and registry-aware variants without forking the files. Rename the local 'copy' helper to 'copyFile' to avoid shadowing the standard library name.
FIPS crypto policies require secret keys of at least 14 bytes. Widen shared test secrets in HMAC, JWT, and MinIO fixtures, and align the env files used by docker-compose test harnesses. Replace x.FIPSEnabled truthiness with x.FIPSBinary() calls at test skip sites so non-FIPS compilations can still reference FIPS awareness without tag-guarded symbols.
…ience Pull compose environment assembly and compose-file argument selection behind hooks so downstream forks can supply FIPS- and registry-aware variants without touching upstream t/t.go. Resilience improvements bundled in the same file: - 3 up-attempts with 2s delay between in startCluster for docker volume-init races (300ms was insufficient) - 5s grace after resumeDefault's health-check wait for alpha->zero connection pool re-establishment Discovered during CI stabilization; universally beneficial.
This comment has been minimized.
This comment has been minimized.
…registry-and-hooks-clean # Conflicts: # dgraph/Makefile
archive.ubuntu.com publishes index updates non-atomically; CI builds intermittently fail with 'File has unexpected size... Mirror sync in progress?' when the runner fetches Packages.gz mid-publish. Retry the install once after a 15-second pause and a fresh apt list, which is sufficient to ride out the transient. While here, drop a duplicate 'htop' line in the package list (was listed twice). Same retry pattern is used in the Chainguard go-fips image's apk calls; this makes contrib/Dockerfile equivalently resilient.
| // private/downstream code paths), not access control. The name is | ||
| // retained for compatibility with the established PRIVATE_BUILD_TAGS | ||
| // environment variable that Makefile and CI have long used. | ||
| PrivateBuildTags = newVar("PRIVATE_BUILD_TAGS", "") |
There was a problem hiding this comment.
Let's rename this CustomBuildTags, CUSTOM_BUILD_TAGS
There was a problem hiding this comment.
Done in 352ff5a — renamed PrivateBuildTags → CustomBuildTags (and PRIVATE_BUILD_TAGS → CUSTOM_BUILD_TAGS) at the Var declaration, every reference (BuildTags composer, All slice, test names), and the test env-cleanup. go test ./buildvars/... passes.
| svc.Image = opts.Image + ":" + opts.Tag | ||
| svc.ContainerName = containerName(svc.name) | ||
| svc.WorkingDir = fmt.Sprintf("/data/%s", svc.name) | ||
| if u := EmitUser(); u != "" { |
There was a problem hiding this comment.
Add a comment explaining what EmitUser() hook call here provides (when digraph runs as non root user in compose tests, hook overrides default return of "").
There was a problem hiding this comment.
Done in 352ff5a — added a paragraph above the call explaining the hook surface: default returns "" (service inherits image USER), downstream consumers running dgraph as a non-root compose-test user override to return e.g. "${UID:-65532}" so bind-mounted host paths are readable by the in-container uid.
|
|
||
| // hostBinaryFileName is the conventional filename for the host-OS-native | ||
| // dgraph binary when it differs from the container binary (non-Linux). On | ||
| // Linux the host and container binaries are the same file (named |
There was a problem hiding this comment.
s/file (named/file name returned by/
There was a problem hiding this comment.
Done in 352ff5a — "the same file (named buildvars.Bin.Get())" → "the same file name (returned by buildvars.Bin.Get())".
| if err != nil { | ||
| return errors.Wrap(err, "error while creating tempBinDir") | ||
| } | ||
| if err := WidenTempDirPerms(c.tempBinDir); err != nil { |
There was a problem hiding this comment.
Add explaining is a hook, default is no-op, can be overridden on forks where dgraph running as non-root user in compose test containers needs widened perms to read directories mounted from container host.
There was a problem hiding this comment.
Done in 352ff5a — added a paragraph at the first call site explaining: public hook, default no-op, downstream consumers running dgraph as non-root inside compose-test containers override to widen perms on host-side temp dirs (which are bind-mounted into containers) so the in-container uid can read/write those paths. The second call site below points back to the same hook with a one-line note.
| } | ||
|
|
||
| cconf := &container.Config{Cmd: cmd, Image: image, WorkingDir: dc.workingDir(), ExposedPorts: dc.ports()} | ||
| ApplyContainerUser(cconf) |
There was a problem hiding this comment.
Again add comment about hook here.
There was a problem hiding this comment.
Done in 352ff5a — comment explains: public hook, default no-op, downstream consumers running dgraph as a non-root user inside the test container override to set cconf.User to host uid:gid so files written by the container are readable on the host (and vice-versa for bind-mounts).
| if err := os.WriteFile(c.encKeyPath, encKey, 0600); err != nil { | ||
| return err | ||
| } | ||
| if err := WidenSecretFilePerms(c.encKeyPath); err != nil { |
There was a problem hiding this comment.
Add comment explaining hook and default behavior
There was a problem hiding this comment.
Done in 352ff5a — comment at the top of setupSecrets explains both call sites: public hook, default no-op; secret files write at 0600 (correct upstream); downstream consumers running the container as a non-root user that differs from the host owner override to widen perms (e.g. group/world-read) so the in-container uid can read the bind-mounted secrets.
| } | ||
|
|
||
| func (c *LocalCluster) GeneratePlugins(raceEnabled bool) error { | ||
| if tokenizers, handled, err := GeneratePlugins(raceEnabled, c.tempBinDir, baseRepoDir); handled { |
There was a problem hiding this comment.
Done in 352ff5a — comment explains: hook returns (nil, false, nil) upstream so the host-side fallback path runs; downstream consumers whose toolchain isn't directly host-invokable (e.g. forks pinning a Docker-only build image) override to compile inside that image and return the .so paths, in which case handled=true short-circuits the host fallback.
| } | ||
| }`, | ||
| jwt: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiZXhwIjozNTE2MjM5MDIyLCJlbWFpbCI6InRlc3RAZGdyYXBoLmlvIiwiVVNFUiI6InVzZXIxIiwiUk9MRSI6IkFETUlOIn0.cH_EcC8Sd0pawJs96XPhpRsYVXuTybT1oUkluBDS8B4", | ||
| jwt: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiZXhwIjozNTE2MjM5MDIyLCJlbWFpbCI6InRlc3RAZGdyYXBoLmlvIiwiVVNFUiI6InVzZXIxIiwiUk9MRSI6IkFETUlOIn0.pZ2-Dib2lXrCeXghCoPD7CnZ8GUGXhv1WbbRQ7mhPnM", |
There was a problem hiding this comment.
Add comment explaining length change, minimum length required for FIPS
There was a problem hiding this comment.
Done in 352ff5a — added a paragraph at the top of the testCases block explaining: pre-signed JWTs use the widened secret ("secret-long-enough"); secret + fixture JWTs were re-signed when secrets were widened to 14+ bytes (NIST SP 800-131A HMAC minimum, enforced by FIPS-validated providers at EVP_MAC_init). Signatures verified against the previous secret before re-signing so claim payloads are unchanged.
| mkdir -p /data/alpha2 | ||
| mkdir -p /data/alpha3 | ||
| /gobin/dgraph bulk --schema=${SCHEMA_FILE} --files=${DATA_FILE} \ | ||
| /gobin/${BIN:-dgraph} bulk --schema=${SCHEMA_FILE} --files=${DATA_FILE} \ |
There was a problem hiding this comment.
Shouldn't this be ${GOBIN_DGRAPH_PATH:-/gobin/dgraph} ? not /gobin/${BIN:-dgraph}:
There was a problem hiding this comment.
Good catch — done in 352ff5a. Switched all three sites (test-21million.sh, test-reindex.sh, loader-benchmark.sh) to ${GOBIN_DGRAPH_PATH:-/gobin/dgraph}. Both forms resolve to the same string (GoBinDgraphPath's default is /gobin/$Bin), but using the registry's named Var matches the rest of the codebase's conventions and keeps the Var ↔ shell mapping discoverable.
- buildvars: rename PrivateBuildTags -> CustomBuildTags; PRIVATE_BUILD_TAGS
-> CUSTOM_BUILD_TAGS. 'Private' read as access-control; 'Custom' is
clearer for the consumer-extensibility intent.
- compose/compose.go: explain EmitUser hook (default "" inherits image
USER; downstream non-root compose tests override to set service user).
- dgraphtest/load.go: tighten hostBinaryFileName grammar.
- dgraphtest/local_cluster.go: add hook-call comments at the four
override points (WidenTempDirPerms x2, ApplyContainerUser,
WidenSecretFilePerms, GeneratePlugins) explaining each is a public
hook with a no-op default and the downstream-override scenario.
- graphql/e2e/auth/auth_test.go: explain why JWT fixtures were re-signed
(NIST SP 800-131A 14-byte HMAC minimum + FIPS provider enforcement).
- systest/{1million,21million,loader-benchmark}/*.sh: prefer the
canonical buildvars path ${GOBIN_DGRAPH_PATH:-/gobin/dgraph} over
the synthetic /gobin/${BIN:-dgraph}; both resolve the same way but
the former matches the registry's named Var.
The comment was paraphrasing what ComposeFileArgs (t/hooks.go) already documents at its declaration, with extra fork-specific path references that don't belong in upstream. The variable name is self-documenting; the rewrite mechanism is explained on the hook.
The Var's Go identifier was 'Bin' which reads as an abbreviation. The
binary-naming concept benefits from a descriptive symbol; reads more
naturally as buildvars.BinaryName.Get() at every call site (compose,
dgraphtest, testutil, t).
The env-var name stays as BIN — Makefiles, shell scripts, and CI
configs reference $(BIN) / ${BIN} directly, and those are left
unchanged. The Go identifier rename is the only intent.
This comment has been minimized.
This comment has been minimized.
The FIPS-awareness surface lived in package x as two separate symbols: x.FIPSEnabled (var, compile-time signal flipped by tag-guarded init) and x.FIPSBinary() (function, runtime signal reading DGRAPH_FIPS_BINARY). Every call site combined them as 'if x.FIPSEnabled || x.FIPSBinary()'. Two improvements in one move: 1. Relocate to package buildvars. The FIPS-awareness surface is build- time configuration, alongside BinaryName, BuildImage, BUILD_TAGS, etc. It belongs in the registry, not in package x's grab-bag of low-level helpers. 2. Collapse to a single caller-facing helper. New buildvars.FIPSEnabled() ORs the two underlying signals internally; callers don't need to know about the compile-time-vs-runtime distinction. The two-piece API was honest about implementation but pushed boilerplate to every site. Layout: buildvars/fips.go — FIPSEnabled(), untagged buildvars/fips_requirefips.go — init() flips internal flag under -tags=requirefips buildvars/fips_test.go — exercises both signals Migrated call sites: acl/jwt_algo_test.go x.FIPSEnabled || x.FIPSBinary() -> buildvars.FIPSEnabled() check_upgrade/check_upgrade_test.go same systest/integration2/acl_test.go same Removed: x/fips_base.go — FIPSEnabled var + FIPSBinary func x/fips_base_test.go — moved to buildvars/fips_test.go
…API" This reverts commit e39f708.
Two changes that need to land together:
1. Keep FIPS-awareness in package x (revert the brief move to buildvars).
x is the right home for the FIPS-domain helpers (TLS cipher list,
JWT algorithms, RSA key size, OpenSSL provider validation) — those
are TLS/JWT-domain concerns the buildvars registry deliberately
doesn't pull in. The compile-time + runtime detection naturally
sits next to them.
2. Collapse the two-piece x.FIPSEnabled (var) + x.FIPSBinary() (func)
into a single x.FIPSEnabled() function that ORs both signals
internally. Every prior call site was 'if x.FIPSEnabled || x.FIPSBinary()';
the helper hides the compile-time-vs-runtime distinction. x.FIPSBinary
stays exported for the rare caller wanting the runtime-only signal.
3. Rename the build tag itself: 'requirefips' -> 'fips'. The 'require'
prefix was inherited from microsoft/go's tag name; for our purposes
it's noise. Internally we now own the tag name and the shorter form
reads better at every -tags=fips invocation.
Files:
x/fips_base.go (was: var FIPSEnabled + func FIPSBinary)
-> func FIPSEnabled() bool (ORs both signals)
func FIPSBinary() bool (runtime-only, kept for direct access)
var fipsEnabledCompiled (internal compile-time flag)
x/fips_base_test.go: assertions adapted to new API.
Migrated call sites:
acl/jwt_algo_test.go x.FIPSEnabled || x.FIPSBinary() -> x.FIPSEnabled()
check_upgrade/check_upgrade_test.go same
systest/integration2/acl_test.go same
Build-tag references in docs and example strings:
buildvars/{buildvars,buildvars_test}.go: 'myfork requirefips' -> 'myfork fips'
testutil/graphql.go: prose mention reworded.
Note: the actual //go:build fips file (x/fips.go with TLS/JWT/RSA helpers
and ValidateFIPSMode) lives in the fork tree, not in this OSS PR. The
upstream-mergeable surface stops at x/fips_base.go's untagged primitives.
The FIPS-awareness surface previously had two parts:
- x.FIPSEnabled (compile-time signal flipped by tag-guarded init)
- x.FIPSBinary() (runtime signal reading DGRAPH_FIPS_BINARY env var)
The runtime signal was never actually independent. The fork ships
'istari' and 'fips' build tags coupled in CUSTOM_BUILD_TAGS; if the
test binary is built with one, it's built with both. There's no
realistic config where the test binary is non-FIPS but the dgraph
subprocess is. The runtime env var was redundant boilerplate.
This commit:
1. Moves the flag to package buildvars as plain 'var FIPSEnabled bool'.
The tag-guarded init() in buildvars/fips_on.go (//go:build fips)
flips it to true. A simple bool, not a function, not a *Var — it's
a compile-time fact, not an env-driven config.
2. Drops x.FIPSBinary() and the DGRAPH_FIPS_BINARY env var entirely.
Call sites read buildvars.FIPSEnabled directly.
3. Renames helpers: skipIfFIPSBinary -> skipIfFIPS (the binary-vs-test
distinction was never meaningful given coupled tags).
Layout:
buildvars/fips.go — var FIPSEnabled (default false)
buildvars/fips_on.go — //go:build fips; init() flips to true
buildvars/fips_test.go — //go:build !fips; default-false test
buildvars/fips_on_test.go — //go:build fips; flipped-to-true test
Migrated call sites:
acl/jwt_algo_test.go x.FIPSEnabled || x.FIPSBinary() -> buildvars.FIPSEnabled
check_upgrade/check_upgrade_test.go same
systest/integration2/acl_test.go same
Removed:
x/fips_base.go (FIPSEnabled var + FIPSBinary func)
x/fips_base_test.go (tests for the dropped surface; default-false
test moved to buildvars/fips_test.go)
…ntion Replace the 4-file split (fips.go untagged + fips_on.go tagged + 2 tests) with a 2-file pair following crypto/internal/boring's pattern: fips.go (//go:build fips) -> var FIPSEnabled = true nofips.go (//go:build !fips) -> var FIPSEnabled = false fips_test.go (//go:build fips) -> TestFIPSEnabled_TrueUnderFIPSTag nofips_test.go (//go:build !fips) -> TestFIPSEnabled_FalseUnderNoFIPSTag Each compiled build sees exactly one declaration; no init() needed. The 'no<base>' prefix for the complement file matches Go stdlib's crypto/internal/boring/notboring.go style and reads better than the prior _on/_off pair. No call-site changes — buildvars.FIPSEnabled is still a plain bool read.
The previous commit (e355fbc) wrongly added a //go:build fips file declaring 'var FIPSEnabled = true' to the upstream PR. The upstream project never wants FIPS enabled — it's a downstream fork concern. The upstream PR's job is to expose the extension point (a public bool that forks can flip via a tag-guarded sibling), not to ship the flipping half itself. Now: a single untagged buildvars/fips.go declaring FIPSEnabled = false, plus a test asserting that default. Forks that need the FIPS-on side ship their own tag-guarded sibling file (//go:build fips, or whatever tag they prefer) that reassigns the var via init().
Three OSS PR sites referenced '-tags=fips' in comments. The OSS PR is upstream-mergeable; it shouldn't presume any particular fork's build- tag name. Switch to 'when buildvars.FIPSEnabled is true' (the visible behavior callers can reason about) and the buildvars/fips.go docstring to a generic 'tag-guarded init() under whatever tag the fork uses' form. Sites: acl/jwt_algo_test.go under -tags=fips -> when buildvars.FIPSEnabled is true check_upgrade/check_upgrade_test.go same systest/integration2/acl_test.go same buildvars/fips.go '//go:build fips' example -> generic tag-agnostic phrasing
Carry forward the explanatory comment from the fork PR. DBIN exists because BIN is a common shell variable name; rebinding it via := inside a recipe would leak to subsequent commands and subprocesses. A function/recipe-local alias is bounded-scope, semantics-equivalent.
Var had an internal sync.RWMutex on the defaultValue/defaulter pair, guarding a race that doesn't occur. SetDefault is documented and used exclusively during package init(): the buildvars package's own init sets the upstream defaults, then a tag-guarded fork init() runs after (via the import-ordering of istari/gopkg/env). All of that is single- threaded by Go's init contract; user code, including the goroutines that read via Get(), starts after init completes. The mutex didn't add safety; the docstring claim 'guarded by an internal mutex; all reads are consistent' was technically true but implied a concurrency story that isn't actually exercised. Drop the mutex, drop the import, and rewrite the docstring to say what's actually going on: 'SetDefault is expected to run during package init before any goroutines exist; no synchronization is performed because no concurrent reader/writer scenario is reachable in practice.' Default() docstring now states the real callers (tests + diagnostics) rather than just diagnostics. SetDefault docstring drops the misleading 'safe to call concurrently' claim.
…e invariant The comment on Var.defaultValue said 'Used iff defaulter is nil', which read as logic-textbook shorthand and was also slightly wrong (it described one direction of the relationship; the actual invariant is that defaultValue and defaulter are mutually exclusive storage for the default — exactly one supplies the answer at any time). Spell it out: defaultValue is the literal-default storage, defaulter is the computed-default storage, SetDefault freezes computed → literal.
Apply Elements-of-Style rules to the prose this PR added or modified.
Focus on the heavy-comment files: buildvars package docs, hook
declarations across compose/dgraphtest/t/testutil, hook-call comments
in dgraphtest/local_cluster.go, FIPS-aware skip helpers in
acl/jwt_algo_test.go and check_upgrade/check_upgrade_test.go and
systest/integration2/acl_test.go, plus the misc one-off comments in
dgraph/Makefile, t/Makefile, contrib/Dockerfile, dgraphtest/load.go,
and graphql/e2e/auth/auth_test.go.
Specific changes:
- Active voice over passive where natural (Rule 10).
- Positive form over negated (Rule 11): 'are unavailable' for 'isn't
available', 'lacks' for 'does not have', etc.
- Concrete over abstract (Rule 12): name the actual value or pattern
in the example rather than 'various' or 'some'.
- Drop needless words (Rule 13): cut hedging (essentially, basically,
typically), pleonasms (actually, really, very), 'in order to' -> 'to',
'owing to the fact that' -> 'because', and 'is a function which' /
'is initialized to' constructions.
- Em-dash discipline: at most one rhetorical em-dash per sentence;
replace pile-on parentheticals with semicolons or split sentences.
- Keep technical content unchanged. No code edits, only prose.
17 files; +277/-268 (net +9 from line wrapping).
Summary
Two bodies of work that together make the dgraph codebase easier to maintain downstream while preserving identical upstream behavior:
os.Getenvcalls. 2 commits.testutil,t,compose,dgraphtest), plus a minimal FIPS-awareness surface inx/(var + env helper), plus universally-beneficial resilience improvements (volume-race retry, resume-grace delay, test-skip helpers, widened test secrets). 7 commits.All 9 commits preserve upstream behavior byte-for-byte: every hook defaults to the exact code it replaces; every widened test secret is still valid under stock HMAC; every FIPS signal is opt-in via env and defaults off. The net effect on an upstream consumer is no behavior change; the net effect on a downstream fork is that none of these concerns require patching upstream files.
This PR supersedes #9690 with clean logical commit history. See Relationship to #9690 below.
Why
The expanded scope comes from discoveries while maintaining a downstream fork that:
--project-directoryprojection)Every one of these concerns was previously reachable only by patching upstream files with
//go:buildguards or inlineif os.Getenv(...)checks. Each such patch is a maintenance burden: the fork tracks upstream changes to the patched file and must re-apply edits on every rebase. Extracting extension hooks eliminates that burden — the fork owns a single registration file per package and never touches upstream source again.Upstream sees only: neutral public vars with upstream-pristine defaults, and resilience improvements (volume-race retry, resume-grace delay, test-skip helpers) that help every user.
Commits
1.
feat(buildvars): introduce typed build-config registryNew
buildvars/package (363 LOC + 324 LOC tests) +buildvars/cmd/buildvarsCLI withshell/make/plainoutput formats. Migrates hardcoded call sites incontrib/jepsen,testutil/exec,dgraphtest/dgraph, and systest scripts to read from the registry. Includes an incidental nil-panic fix ingetPortMappingsOnMac.2.
fix(makefile): make BIN overridable, expand jemalloc detection, use go build -odgraph/MakefileusesBIN ?= dgraph,go build -o $(INSTALL_TARGET)(respects renames), and broader jemalloc detection (/usr/lib,libjemalloc_pic.afor Debian/Alpine/Wolfi).t/Makefile'schecktarget threads$BIN.3.
test(restore): skip namespace-aware restore tests on non-Linuxsystest/online-restore/namespace-aware/restore_test.goguarded with//go:build linuxso Darwin CI does not fail on Linux-only kernel features.4.
feat(x): add FIPSEnabled var + FIPSBinary() runtime helperTwo minimal, coordinated FIPS-awareness signals in package
x:FIPSEnabled(var, default false): compile-time signal. Declared as a var (not a const) so a build-tag-guarded sibling file in a downstream fork can flip it viainit()before any test or main body runs. For all practical purposes behaves as a compile-time constant forif x.FIPSEnabled { ... }guards.FIPSBinary()(function): runtime signal viaDGRAPH_FIPS_BINARY=1. Covers the case where the test binary is built without FIPS tags but spawns a FIPS-enforcing dgraph subprocess.Includes tests covering the env-var parsing (only exact
"1"is true) and the default-false invariant.5.
refactor(testutil): extract ComposeArgs, EnvForCompose, BuildPlugins hooksThree public function-var hooks in new
testutil/hooks.go.StartAlphas/StopAlphasForCoveragecall the compose-args and env-for-compose hooks.GeneratePluginsdelegates to theBuildPluginshook (default is the verbatim previous implementation). Upstream behavior byte-exact.6.
refactor(compose,dgraphtest): add extension hooks; rename copy → copyFileOne hook in
compose/hooks.go(EmitUser, wired into service generation), six hooks indgraphtest/hooks.go(ApplyContainerUser,WidenTempDirPerms,WidenSecretFilePerms,GeneratePlugins,SetupLinuxBinaries,HostBinaryName, wired intolocal_cluster.go/image.go/load.go). All hooks default to no-op / upstream-pristine behavior. Also renames the localfunc copy(src, dst string) errorindgraphtest/image.gotocopyFile(the name shadowed the Go builtincopy).7.
test: widen HMAC/JWT/MinIO test secrets + add FIPS-aware skip helpersWidens every HMAC/JWT/MinIO test secret to the 14-byte minimum NIST SP 800-131A requires and some FIPS-validated crypto providers enforce at
EVP_MAC_init:"secret"→"secret-long-enough"(schema VerificationKey, JWT signer)"secret1"→"secret1-long-enough"(multi-tenancy)"secretkey"→"secretkey-long-enough"(schema VerificationKey, MinIO secret key)graphql/resolve/auth_test.goandgraphql/e2e/auth/auth_test.gore-signed with the new key (verified against old key before replacing signature).TestCheckUpgrade,TestQueryDuplicateNodes,TestRestoreFromOldBackup) and EdDSA (TestACLJwtAlgo) gain a localskipIfFIPSBinary(t)helper that callst.Skipwhenx.FIPSEnabled || x.FIPSBinary()is true. No-op on stock upstream builds.Also aligns the three env files (
dgraph/minio.env,systest/backup.env,systest/export/export.env) so docker-compose test harnesses see the same widened secrets as Go code.8.
refactor(t): extract EnvForCompose + ComposeFileArgs hooks; add resilienceHook surface in
t/hooks.go+ threaded through the test runner. Plus two universally-beneficial resilience improvements:startClusterretriesdocker compose upup to 3 times with 2s delay between attempts afterdown -von failure. Covers the docker volume-init race when multiple services share a named volume. Prior retry-once was insufficient because 300ms was not long enough for docker to release mount points.resumeDefaultwaits 5 seconds after the health-check wait-group before returning. Alpha/healthreturns OK before the alpha→zero connection pool is fully re-established, causing "No connection exists" on the first post-resume test.9.
style(admin): gofmt admin_auth_test.gogofmt -w. Collapsed alignment in a map literal + trailing newline. No functional change.API
Relationship to #9690
This PR supersedes #9690 with clean logical commit history. The final content is byte-identical to #9690's last green tip (
d63438211); only the commit structure changed.#9690 accumulated 17 commits through CI debugging and review feedback, including a merge commit from pulling
upstream/mainforward. Reviewers had to reconstruct intent across commits that touched the same area of concern multiple times. This PR groups the same content into 9 commits by area of concern.#9690 will be closed once this PR is green. Review comments do not migrate across GitHub PRs — please re-state any unresolved feedback here if it still applies.