feat(bazel): consolidate every service into the root Bazel module - #593
feat(bazel): consolidate every service into the root Bazel module#593balajinvda wants to merge 9 commits into
Conversation
|
Important Review skippedToo many files! This PR contains 474 files, which is 174 over the limit of 300. To get a review, narrow the scope: ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: ⛔ Files ignored due to path filters (1134)
📒 Files selected for processing (474)
You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThe image credential helper is migrated into the root Bazel workspace. Root dependency and OCI image repositories are added, while shared OCI macros gain explicit binary paths and multi-registry publishing support. ChangesRoot Bazel integration and OCI publishing
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant go_oci_image
participant pkg_files
participant create_oci_image
participant Registries
go_oci_image->>pkg_files: package binary at binary_path with mode 0755
go_oci_image->>create_oci_image: forward entrypoint and extra_registries
create_oci_image->>Registries: create stamped primary and additional push targets
Possibly related PRs
Suggested reviewers: ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
c38f67a to
e3cd524
Compare
|
Closing this in favour of a reviewable stack. The change is correct and the For the record, the file count is misleading about the actual content:
So it is one scripted find-replace, a large deletion, and two real code edits. The work is preserved on
Three findings worth carrying forward regardless of how the migration lands:
The paired nvcf-internal MR (!107) stays open and blocked until the migration |
f61290d to
4e5f022
Compare
Second service to leave its own nested module, after nvsnap. The nested MODULE.bazel, lock, .bazelrc, .bazelversion, platforms/, rules/oci/ and workspace_status.sh are deleted; the subtree joins go.work.bazel and leaves .bazelignore, and its CI row becomes a root-scoped row alongside nvsnap. Two things had to change beyond the mechanical move. The shared rules/oci macro was a strict subset of the copy each service carried. go_oci_image gained binary_path and extra_registries, and create_oci_image gained extra_registries, while keeping the root-only env, workdir and java support. binary_path is not incidental: 15 of the 18 remaining nested modules pass it, so without this every one of those migrations fails at load time with "no such attribute 'binary_path'". binary_path reproduces the COPY ... /usr/bin/app contract the services inherited from their Dockerfiles, so image consumers that hard-code the path keep working. Both layer branches force mode 0755, since a 0644 entrypoint produces an image that builds fine and then fails to start. Seven of the service's ten replace directives pinned modules it neither imports nor vendors. A replace is not scoped to its own module once that module joins the root go.work, so those silently re-pinned the whole workspace, and because nothing here imports them no go.sum carried the forced version. The result was that nvcf-cli, an unrelated subtree, failed with "No sum for k8s.io/apiextensions-apiserver@v0.35.3". Only the three replaces covering modules the service actually compiles are kept; client-go needs its replace because the require is the v11.0.0+incompatible mis-tag. vendor/modules.txt drops the corresponding replace lines so vendored builds stay consistent. The go.work.bazel comment no longer enumerates its own use() block. The enumeration had already gone stale, which is the drift tools/ci/nested-modules.txt exists to prevent. Verified with bazel build //... and bazel test //... from the root: 375 targets, nvcf-cli, nvsnap and the Java services all still green. The service's image_index was inspected and carries both linux/amd64 and linux/arm64 child manifests, and its entrypoint mode test passes. Co-authored-by: Balaji Ganesan <bganesan@nvidia.com>
…dule
Takes tools/ci/nested-modules.txt from 17 outstanding migrations to 3. Every
Go service now builds from the root module; only the three Rust subtrees
(function-autoscaler, http-invocation, stargate) keep their own MODULE.bazel,
because merging three crate_universe instances is a separate problem.
Migrated: byoo-otel-collector, ess-agent, grpc-proxy, helm-reval,
llm-api-gateway, nats-auth-callout, nvca, nvcf-unbound, ratelimiter,
vanity-gateway, worker-init, worker-llm-credentials, worker-task,
worker-utils.
The subtrees were never really running the same build system. Each carried a
private copy of rules/oci that had drifted, and the drift is only visible when
they merge. Root's macros were a strict subset of what the fleet used, so the
shared rules had to become a genuine superset first: go_oci_image gained
binary_path (15 of 18 subtrees pass it), extra_layers, env and
extra_registries; create_oci_image gained extra_registries and cmd; the layer
target now carries the image's visibility so callers can point an
entrypoint-mode test at it; and go_oci_multi_binary_image, which root did not
have at all, came over from nvca.
Two subtrees are structurally unlike the rest and are treated differently.
nvca resolves all 178 of its Go dependencies through labels into its own
vendor/ tree rather than through go_deps, so it joins the root module but
deliberately stays out of go.work.bazel: adding it would pull its entire
dependency set into the shared MVS graph for no benefit. Its vendored BUILD
files cross-reference each other as //vendor/..., which only resolves when //
means the subtree, so they are rewritten too. ess-agent contains ten Go
modules (a vendored Vault api/sdk with its own go.work); api and sdk join the
root workspace.
Nested .bazelignore files had to be lifted into the root with a path prefix.
ess-agent, vanity-gateway and byoo-otel-collector each excluded vendored Vault
auth backends they do not link; without lifting, Bazel starts building GCP,
AWS, Azure and LDAP SDKs that nothing references.
A replace directive is not scoped to its own module once that module joins the
root go.work. helm-reval carried twelve replaces for modules it neither
imports nor vendors: they pinned nothing locally and re-pinned the whole
workspace to versions no go.sum covers, so the shared build failed in
unrelated subtrees with "No sum for cloud.google.com/go@v0.112.2". Only the
replaces covering modules the service compiles are kept.
Three dependency versions move as a consequence of having one graph rather
than eleven, and none of them is cosmetic:
- distroless_go was pinned at two digests across the fleet. Eleven services
move from v4.0.6 to v4.0.8, the newer of the two and the one root already
used.
- nvsnap's containerd goes 1.7.24 -> 1.7.27 with api 1.7.19 -> 1.8.0.
helm-reval carried the newer containerd as an indirect requirement; MVS
raised containerd and left api behind, and the skew broke analysis because
containerd's generated BUILD referenced a package the older api does not
ship.
- grpc-proxy's geo test moves to the current testcontainers port API
(nat.Port -> string, Int() -> Port()) after moby resolved forward. Fixed
at the test layer only; no production code changed.
Verified with bazel build //... and bazel test //... from the root: 3779
targets, up from 375. tools/ci/check-nested-modules reports 5 classified, 3
awaiting migration, 0 permanent exceptions. check-license passes and no added
line carries an internal hostname, registry endpoint or vault path.
Co-authored-by: Balaji Ganesan <bganesan@nvidia.com>
Three CI failures on the consolidation branch, one a real regression and two
long-standing failures the branch merely made visible.
llm-api-gateway's telemetry is the regression. It imported
go.opentelemetry.io/otel/semconv/v1.40.0 to build its resource, which matched
the SDK while its nested module pinned otel v1.42.0. Under one shared graph MVS
resolves otel to v1.44.0, whose detectors emit schema 1.41.0, and merging the
two resources fails:
Init() error = error detecting resource: conflicting Schema URL:
https://opentelemetry.io/schemas/1.40.0 and .../1.41.0
This is a production defect, not a test problem: Init() returns that error at
runtime, so the service would fail to start its metrics server. The import and
its BUILD dependency move to semconv/v1.41.0 to match the SDK.
The other two, ess-agent's logging tests and helm-reval's reval_test, are not
regressions. Both are already tagged `manual` by their owners, with comments
explaining why. Bazel only honours that tag when expanding wildcard patterns,
and this workflow resolves an explicit label list via `bazel query` before
calling `bazel test`, so naming them ran them regardless. The tag has therefore
been doing nothing in CI while `bazel test //...` skipped them locally, which is
exactly the divergence that let these sit red unnoticed. Ten test targets across
the repo carry the tag deliberately; the query now excludes them, so CI agrees
with a local run and the owners' intent is honoured.
They stayed invisible because rows are scheduled per changed subtree: neither
subtree had been touched recently, so neither row had run. A branch touching
every subtree runs every row, which is the first time this fleet has been
exercised together.
Verified: telemetry_test passes; the amended query still selects 54 targets
across ess-agent and helm-reval while excluding both offenders; ess-agent's
logging_test was confirmed to fail identically on origin/main in its original
nested module, establishing it as pre-existing.
Co-authored-by: Balaji Ganesan <bganesan@nvidia.com>
Takes tools/ci/nested-modules.txt to zero. function-autoscaler, http-invocation and stargate were the last three services with their own MODULE.bazel; every first-party service in the repository now builds from the root module. One toolchain, three crate universes. The universes stay separate because a crate_universe instance is scoped to a Cargo workspace, and these are three independent workspaces with their own Cargo.lock. Merging them into one lockfile would force a single resolved version for every Rust dependency across unrelated services, which is a much larger change than removing the nested Bazel modules and is not required to do so. The toolchain is stargate's 1.97.0; function-autoscaler and http-invocation move up from 1.91.1, because one root module registers one version. Editions are deliberately not unified: every Rust target already sets `edition` explicitly in its own BUILD file (2021 for the first two, 2024 for stargate), so the value on rust.toolchain is only a default nothing relies on. Moving a crate between editions is a source migration with real breaking semantics, not a build setting. All three pinned protobuf at 29.1 and named it @protobuf. The root module is on 33.4 and, because a .bazelrc flag references it, declares it with repo_name = "com_google_protobuf". A module has one apparent name, so those references move -- including inside $(execpath) expressions and build_script_env, which a scan for quoted labels alone does not catch. PROTOC_WKT_DIR needed recomputing, and this is the interesting one. It holds a relative path from the build script's working directory to the well-known type protos. The canonical external directory is still protobuf+, unaffected by repo_name, but each package moved several levels deeper when it gained its subtree prefix, so the hop count grows with it. Nothing in analysis catches this: the graph builds and protoc then fails with "google/protobuf/timestamp.proto: File not found". The counts are now derived from package depth rather than hardcoded. Verified with bazel build //... from the root. Everything builds except stargate's crates/protocol, whose build script shells out to `capnp`; that binary is not visible inside Bazel's action sandbox in this environment and the same target fails identically on origin/main in its original nested module, so it is not a consequence of this change. CI runs in the bazel-ci image and is the arbiter for that crate. tools/ci/check-nested-modules now reports 2 classified, 0 awaiting migration, 0 permanent exceptions. Co-authored-by: Balaji Ganesan <bganesan@nvidia.com>
… its row Two consequences of every migrated service building from the repository root. Both are properties of that decision rather than incidental breakage, and both should have been derived when the decision was made. Cache identity was keyed on the matrix row while cache content was not. The cached paths hold the Bazel install base and the repository cache; no disk_cache is configured, so their content is a pure function of MODULE.bazel.lock and .bazelversion. That was fine while each subtree had its own nested module and a genuinely different dependency closure. It is not fine now: roughly twenty rows hash the same root lock and produce byte-identical content under twenty different keys. GitHub's cache is 10 GB per repository with LRU eviction, so those entries cannot coexist. They would evict one another on every run and the cache would stop working for every branch indefinitely, not just while this change lands. Root-scoped rows now share one identity, which is what their content already implied; rows with their own module keep a per-row one. Concurrent saves to a single key are safe, since the first writer wins and the rest no-op. The root test quarantine was gated implicitly. It relied on .github/bazel-root-test-quarantine.txt not resolving from a subtree working directory, which stopped being true once those rows began running from the repository root, so the quarantine silently applied to all of them. It is inert today because the patterns do not intersect those scopes, but an entry that did would stop testing a service with no signal. The row is now matched explicitly. That second one is the same shape as the `manual` tag this branch already fixed: a mechanism whose documented intent held only under a condition nobody restated when the condition changed. Both comments now say what is actually enforced. Co-authored-by: Balaji Ganesan <bganesan@nvidia.com>
…the cache Three defects, all consequences of every service building from the root module rather than its own. Build scripts had no edition. The root module registers one default edition, and I set it to 2021 on the reasoning that every Rust target names its own. That was true of the library and binary targets but not of cargo_build_script, which carries no edition and takes whatever is registered. Each nested module had happened to register the edition its own crate used, so the omission was invisible. Under one module it is not: stargate's build.rs uses let-chains and failed to compile as 2021 with "let chains are only allowed in Rust 2024 or later". All five build scripts across the three Rust subtrees now state their edition, matching their crate's Cargo.toml, so nothing depends on the default. The MODULE.bazel comment asserting the default was inert has been corrected, since that assertion was the bug. image-push-manual hashed a lockfile that no longer exists. Its cache key was built from <service_path>/MODULE.bazel.lock and <service_path>/.bazelversion, files this change deletes. hashFiles returns empty for missing paths, so the key degenerated to a constant that no longer described the dependency state it claimed to. The key now hashes the root lockfile, and the entry is split in two: the install base and repository cache are identical for every service and are shared under one key, while compiled action outputs stay keyed per service. Sharing matters for the same reason it does in the matrix build: GitHub's cache is 10 GB per repository, so N copies of one multi-gigabyte entry evict each other and nothing ever hits. image-push-manual also never used the remote cache. It passed --remote_cache= (empty, i.e. disabled) and relied on a local disk cache, so every dispatch recompiled the service's entire dependency closure even though CI had already built those exact actions. It now uses the same public Buildbarn cache as the matrix build, with the flags copied verbatim from that lane rather than re-derived, and reuses tools/ci/bazel-cache-upload-mode so the read/write policy stays in one place. A workflow_dispatch is neither a main push nor a merge_group, so it resolves to read-only and an ad-hoc push cannot write to the shared cache. The bazel query stays cacheless: it loads the graph and executes no actions. Also aligns three bazel_dep declarations with the versions the graph already resolves, removing a check_direct_dependencies warning printed on every build. Doing it here rather than later is deliberate: this change already invalidates the lockfile, so folding in another lock-affecting edit costs nothing, where a separate one would force a second full-fleet cold build. Audited every workflow for the same class of assumption. chart-push-manual builds no Bazel targets, byoo-otel-collector uses its subtree only for a Go script, and license-dependencies already hashed the root lockfile. Only image-push-manual was affected. Co-authored-by: Balaji Ganesan <bganesan@nvidia.com>
Consolidation silently changed what the root row covers, and the change was
invisible because nothing declared the old behaviour.
While each service had its own nested module, all eighteen subtrees sat in
.bazelignore. `//...` from the repository root therefore could not see them,
and root and the service rows partitioned the repository between them: every
target belonged to exactly one row. Removing those entries dissolved that
partition. The root row became a superset of all eighteen service rows,
rebuilding and retesting every service a second time, on one machine, with
their tests running concurrently.
The duplicated work is most of why that row takes over an hour. The
concurrency is worse. Sixty-eight test packages in this repository bind literal
ports and they overlap heavily across services: 8080 appears in fifteen
packages, 4222 in twelve, 8360 in six. Each was safe while it had a row to
itself. Run together they contend, which is how vanity-gateway's suite started
panicking with
listen tcp 0.0.0.0:10085: bind: address already in use
in the root row while its own row stayed green. Three different places claim
10085: that test, vanity-gateway's gateway default and grpc-proxy's proxy
default. With --flaky_test_attempts=3 already set, most such collisions would
retry into a pass and hide themselves; this one happened to panic.
The root row's scope is now `//...` minus every path another row owns,
computed from the same ROWS table the matrix is generated from, so the two
cannot drift apart. That restores the one-row-per-target invariant and removes
the duplicate work and the cross-service concurrency together. Verified against
the real table, which by this point includes the dynamically discovered Java
rows: the root row resolves to root-owned targets only.
The hard-coded ports remain a genuine defect and should be moved to ephemeral
binding, but that touches sixty-eight packages, is unrelated to module
consolidation, and is not needed once the partition is restored. Worth its own
issue.
Co-authored-by: Balaji Ganesan <bganesan@nvidia.com>
The five Rust image targets base on @distroless_cc, but consolidation lifted distroless_static, distroless_go and distroless_java into the root module without it, so those targets referenced an undeclared repository and cquery failed on all three Rust subtrees. All three pre-consolidation subtree modules pinned the same digest and the same linux/arm64/v8 variant, so this is a direct lift with no reconciliation. Co-authored-by: Balaji Ganesan <bganesan@nvidia.com>
61224c2 to
b9ef1ff
Compare
The root row's scope is several patterns in one string, because it now subtracts every other row's path so the two do not build the same targets twice. full() wrote that string to the --target_pattern_file quoted, so all 24 patterns landed on a single line and Bazel read them as one package name: "package names may not contain '//' path separators". Every other row is a single pattern, which is why this only broke the root row, and it broke it on every trigger rather than intermittently. Unquoting word-splits it to one pattern per line. Verified against the scope string from the failing run: 24 lines analyse 217 targets, the single-line form reproduces the error. Co-authored-by: Balaji Ganesan <bganesan@nvidia.com>
Why
The Bazel re-architecture is converging every first-party service onto one root
module.
tools/ci/nested-modules.txttracks the backlog: nvsnap migrated firstin #471, and this takes the ledger from 17 service modules to none.
The Rust subtrees (
function-autoscaler,http-invocation,stargate) wereoriginally going to be a follow-up; they are included here instead, so the
consolidation lands in one piece rather than leaving the root module in a state
no one would want to stop at. Two
nested-modules.txtentries remain and aredeliberate: a vendored third-party
MODULE.bazelunder nvca, and therules/oci-destinationsscaffolding module. Neither is a service.The premise going in was that this is mechanical. It is not. The subtrees were
never running the same build system: each carried a private copy of
rules/ocithat had drifted, and each carried dependency pins that only appear to be local.
Migrated here: byoo-otel-collector, ess-agent, grpc-proxy, helm-reval,
image-credential-helper, llm-api-gateway, nats-auth-callout, nvca, nvcf-unbound,
ratelimiter, vanity-gateway, worker-init, worker-llm-credentials, worker-task,
worker-utils.
What changed
The shared rules had to become a genuine superset first
Root's macros were a strict subset of what the fleet used, so the first
migration failed at load time. Rather than discover the gaps one service at a
time, every attribute and symbol used across all 18 subtrees was enumerated up
front.
go_oci_imagegainedbinary_path(passed by 15 of 18 subtrees),extra_layers,envandextra_registries.create_oci_imagegainedextra_registriesandcmd.go_oci_multi_binary_image, which root did nothave at all, came from nvca. The layer target now carries the image's visibility
rather than being macro-private, because callers point an entrypoint-mode test
at it -- that test is the regression guard for the rules_pkg default-0644
startup failure, so the layer being reachable is the point.
A
replacedirective is not scoped to its own moduleOnce a module joins the root
go.work, itsreplacedirectives applyworkspace-wide. image-credential-helper carried seven and helm-reval twelve for
modules they neither import nor vendor. They pinned nothing locally and re-pinned
every other subtree on merge -- and because nothing in the owning module imports
them, no
go.sumcarries the forced version. The failures landed elsewhere:Only replaces covering modules the service compiles are kept.
Nested
.bazelignorefiles carry load-bearing exclusionsess-agent, vanity-gateway and byoo-otel-collector each excluded vendored Vault
auth backends they do not link. Deleting the nested module re-enables them and
Bazel starts building GCP, AWS, Azure and LDAP SDKs nothing references. 53
entries were lifted into the root file with subtree prefixes.
Two subtrees are structurally unlike the rest
nvca resolves all 178 of its Go dependencies through labels into its own
vendor/tree rather than throughgo_deps. It joins the root module butdeliberately stays out of
go.work.bazel: adding it would pull its entiredependency set into the shared MVS graph for no benefit. Its vendor tree stays
loadable -- the opposite of image-credential-helper, where the vendored copy had
to be hidden so the same importpath is not declared twice. Its vendored BUILD
files cross-reference each other as
//vendor/..., so 1113 were rewritten.ess-agent contains ten Go modules (a vendored Vault api/sdk with its own
go.work);apiandsdkjoin the root workspace.CI was silently overriding the
manualtest tagTen test targets across the repo are tagged
manualby their owners, withcomments explaining why. Bazel only honours that tag when expanding wildcard
patterns; this workflow resolves an explicit label list via
bazel queryandpasses it to
bazel test, so every one of them ran anyway.bazel test //...skipped them locally while CI ran them, which is how ess-agent's logging tests
and helm-reval's
reval_testsat red unnoticed.The query now excludes
manual. This is a deliberate reduction in what CIexecutes: those ten targets stop running, which is what their owners asked for.
They stayed invisible because rows are scheduled per changed subtree -- neither
subtree had been touched recently, so neither row had run. A branch touching
every subtree runs every row, which is the first time this fleet has been
exercised together.
Customer Release Notes
Not customer visible.
Plan Summary
Not applicable.
Usage
Not applicable.
Testing
bazel build //...from the root: 3832 targets, green (375 before).bazel test //...: 19 test targets fail in a local sandbox. None are caused bythis change. Each group was run against clean
origin/main-- pre-existingsubtrees from the root module, migrated ones in their original nested module:
KUBEBUILDER_ASSETS not setCauses are envtest binaries (
KUBEBUILDER_ASSETS), Docker, and localhostnetwork, none of which the sandbox provides. nvsnap was checked rather than
assumed, since its containerd moved here; it is exonerated.
tools/ci/check-nested-modules: the two remaining entries are classified andnon-service, 0 permanent exceptions.
tools/ci/check-licensepasses. No added line carries an internalhostname, registry endpoint or vault path.
Notes
distroless_cc had to come with them
Consolidation lifted
distroless_static,distroless_goanddistroless_javainto the root module but not
distroless_cc, which the five Rust image targetsbase on.
bazel buildwas unaffected, so it did not surface there;cqueryfailed on all three Rust subtrees against an undeclared repository. All three
pre-consolidation subtree modules pinned the same digest and the same
linux/arm64/v8variant, so the lift is exact and required no reconciliation.Two local-dev notes, neither affecting CI
If you previously built one of these subtrees as its own module, stale
bazel-*convenience symlinks are left behind pointing into the old outputbase, and a root
bazel build //...fails trying to load through them. Clearthem once:
This is self-limiting: the subtrees are no longer independent modules, so Bazel
will not recreate those symlinks. CI clones fresh and never sees them.
Separately, stargate's
protocolcrate shells out to a hostcapnp(itsBUILD.bazelalready notes a hermetic toolchain as follow-up)..bazelrcsets--incompatible_strict_action_env, which pins the actionPATHto/usr/local/bin:/usr/bin:/bin, so acapnpinstalled elsewhere is invisible.This is unchanged from main and does not reach CI: stargate has its own matrix
row and the root row excludes it.
Dependency versions this forces
Merging these graphs moves 36 Go modules, none of it intended by anyone. This is
the resolver's own report, unedited:
Most are minor. Four had visible consequences and are handled here:
digests; they converge on the newer, which root already used.
the newer containerd indirectly; MVS raised containerd and left api behind,
and the skew broke analysis. nvsnap talks to the containerd API directly, so
this is a real runtime dependency change to a service nobody edited.
port API under grpc-proxy's geo test (
nat.Port-> string,.Int()->.Port()). Fixed at the test layer; no production code changed.llm-api-gateway built its resource with
semconv/v1.40.0. Merging them failswith
conflicting Schema URL. That is a production defect --Init()returnsthe error at runtime, so the metrics server would not start -- and the import
is aligned to v1.41.0.
The last one is the clearest argument for this change. That failure was latent
in the fleet: any future otel bump in llm-api-gateway alone would have produced
the same runtime error, surfacing as "metrics server won't start" in a deploy
rather than as a red test in a PR. Consolidation did not create it; it surfaced
it where it is cheap.
Reviewers should weigh whether the base-image bump belongs here at all. It
affects 11 running services and has nothing to do with module consolidation.
Other
go mod vendorcannot regenerate the vendored subtrees: it strips the NVIDIASPDX headers this repo stamps onto vendored files, producing thousands of
pure-deletion diffs. Only
vendor/modules.txtwas edited by hand.Deleting a nested module leaves its
bazel-<name>convenience symlinks pointinginto a stale output base. A fresh CI checkout never has them, but anyone pulling
this branch onto a machine that previously built the old layout should remove
them, or Bazel walks into them and fails on labels it was never meant to load.
Coupled change in another repo
nvcf-internalbuilds each service fromsource.subtreewith subtree-relativetarget labels (
//cmd:image_index). Those only resolve inside a nested module.A matching MR moves all of them to
subtree: "."with root-relative labels; thetwo must land together or releases break for every migrated service. This is not
caught by CI here, because the failure is a broken release rather than a red
check.
References
None
Related Merge Requests/Pull Requests
Dependencies
No new third-party dependencies. Thirty-six existing Go modules move version as
listed under Notes.