Skip to content

Split API into a standalone Go module - #2882

Open
aryangorwade wants to merge 8 commits into
NVIDIA:mainfrom
aryangorwade:aryan-api-module-split
Open

aryangorwade wants to merge 8 commits into
NVIDIA:mainfrom
aryangorwade:aryan-api-module-split

Conversation

@aryangorwade

@aryangorwade aryangorwade commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Description

This is a PR splitting /api into a standalone module, this would serve to fix GPU Operator versioning issues (Go supports v0.x.y and v1.x.y).

This architectural split involves:

  • Moving dependencies external to api/ into /api to avoid circular imports
  • Splitting API into its standalone module with its own go.mod and go.sum; root go.mod references this module now

CI checks introduced:

  • PR check ensuring shared module dependencies stay in sync
  • Post-release (after tagging) check ensuring compiled binary versions match tags
  • PR check ensuring version bump PRs do not reference preexisting API tags (checks for "operator", "version", "bump" in PR title)

Changes to CI pipeline:

  • Modified .nvidia-ci.yaml and .common-ci.yaml to ensure that tagging a release commit with operator and api tags does not cause a separate release process to trigger for the api tag in addition to the operator tag

Dependabot changes:

  • Modified dependabot.yaml using group-by: dependency-name and a cross-directory pattern to update each shared dependency between both modules in one PR (one PR per dependency; for both modules). Note that groups such as k8s.io/* can be created, resulting in one cross-directory PR for all deps under k8s.io/*.

Checklist

  • No secrets, sensitive information, or unrelated changes
  • Lint checks passing (make lint)
  • Generated assets in-sync (make validate-generated-assets)
  • Go mod artifacts in-sync (make validate-modules)

Testing

Tested building & deploying the operator on a cluster with some test workloads. Tested Makefile commands.

@aryangorwade
aryangorwade force-pushed the aryan-api-module-split branch 3 times, most recently from 470d8a1 to 0acdb89 Compare September 16, 2026 07:20
Comment thread go.mod Outdated
@aryangorwade aryangorwade changed the title [DRAFT]: Modeling splitting out API into its own module Split API into a standalone Go module Sep 16, 2026
@aryangorwade
aryangorwade marked this pull request as ready for review September 16, 2026 22:33
@coderabbitai

coderabbitai Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

📝 Walkthrough

Walkthrough

The repository now contains a separate api Go module with public driver constants and public image-package usage. Root consumers and tests reference the API package. Make targets cover API generation, builds, tests, vendoring, dependency synchronization, and API release validation. New scripts and GitHub Actions validate unpublished and published API versions. CI skips API-version tags for selected pipelines. Dependabot monitors both modules.

Priority: ➖ Normal

Merge Risk: 🟡 Moderate · up to 0acdb

A release PR can bypass API-tag collision validation by using a different title, risking an invalid release. The lint suppression can also hide new deprecated API usage. Resolve these checks before merge.

✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Note

Quiet mode is enabled, so only the most important comments were posted inline. Other review comments are grouped below.

🟡 Other comments (1)
.golangci.yml-30-30 (1)

30-30: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Limit the SA1019 exclusion to the known compatibility sites.

This rule has no path restriction. Both lint commands scan root and API packages with this configuration, so any matching .ConfigMapName or .Name diagnostic outside the compatibility sites will be silently excluded. Restore a path restriction or narrow the exclusion to the affected legacy types so CI reports reintroduced deprecated uses.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: QUIET

Plan: Enterprise

Run ID: c6cb07c3-751f-40f4-a465-f56bb1f4e5ad

📥 Commits

Reviewing files that changed from the base of the PR and between 5799cfa and 0acdb89.

⛔ Files ignored due to path filters (23)
  • api/go.sum is excluded by !**/*.sum
  • vendor/github.com/NVIDIA/gpu-operator/api/image/image.go is excluded by !vendor/**
  • vendor/github.com/NVIDIA/gpu-operator/api/nvidia/v1/clusterpolicy_types.go is excluded by !vendor/**
  • vendor/github.com/NVIDIA/gpu-operator/api/nvidia/v1/groupversion_info.go is excluded by !vendor/**
  • vendor/github.com/NVIDIA/gpu-operator/api/nvidia/v1/zz_generated.deepcopy.go is excluded by !vendor/**, !**/zz_generated.*.go
  • vendor/github.com/NVIDIA/gpu-operator/api/nvidia/v1alpha1/gpucluster_types.go is excluded by !vendor/**
  • vendor/github.com/NVIDIA/gpu-operator/api/nvidia/v1alpha1/groupversion_info.go is excluded by !vendor/**
  • vendor/github.com/NVIDIA/gpu-operator/api/nvidia/v1alpha1/nvidiadriver_types.go is excluded by !vendor/**
  • vendor/github.com/NVIDIA/gpu-operator/api/nvidia/v1alpha1/zz_generated.deepcopy.go is excluded by !vendor/**, !**/zz_generated.*.go
  • vendor/github.com/NVIDIA/gpu-operator/api/versioned/clientset.go is excluded by !vendor/**
  • vendor/github.com/NVIDIA/gpu-operator/api/versioned/scheme/doc.go is excluded by !vendor/**
  • vendor/github.com/NVIDIA/gpu-operator/api/versioned/scheme/register.go is excluded by !vendor/**
  • vendor/github.com/NVIDIA/gpu-operator/api/versioned/typed/nvidia/v1/clusterpolicy.go is excluded by !vendor/**
  • vendor/github.com/NVIDIA/gpu-operator/api/versioned/typed/nvidia/v1/doc.go is excluded by !vendor/**
  • vendor/github.com/NVIDIA/gpu-operator/api/versioned/typed/nvidia/v1/generated_expansion.go is excluded by !vendor/**
  • vendor/github.com/NVIDIA/gpu-operator/api/versioned/typed/nvidia/v1/nvidia_client.go is excluded by !vendor/**
  • vendor/github.com/NVIDIA/gpu-operator/api/versioned/typed/nvidia/v1alpha1/doc.go is excluded by !vendor/**
  • vendor/github.com/NVIDIA/gpu-operator/api/versioned/typed/nvidia/v1alpha1/generated_expansion.go is excluded by !vendor/**
  • vendor/github.com/NVIDIA/gpu-operator/api/versioned/typed/nvidia/v1alpha1/gpucluster.go is excluded by !vendor/**
  • vendor/github.com/NVIDIA/gpu-operator/api/versioned/typed/nvidia/v1alpha1/nvidia_client.go is excluded by !vendor/**
  • vendor/github.com/NVIDIA/gpu-operator/api/versioned/typed/nvidia/v1alpha1/nvidiadriver.go is excluded by !vendor/**
  • vendor/k8s.io/client-go/discovery/fake/discovery.go is excluded by !vendor/**
  • vendor/modules.txt is excluded by !vendor/**
📒 Files selected for processing (36)
  • .common-ci.yml
  • .github/dependabot.yml
  • .github/workflows/api-post-tag-validation.yaml
  • .github/workflows/api-release-checks.yaml
  • .golangci.yml
  • .nvidia-ci.yml
  • Makefile
  • api/go.mod
  • api/image/image.go
  • api/image/imagepath_validation_test.go
  • api/nvidia/v1alpha1/nvidiadriver_types.go
  • controllers/clusterpolicy_controller.go
  • controllers/clusterpolicy_controller_test.go
  • controllers/nodelabeling_controller.go
  • controllers/nodelabeling_controller_test.go
  • controllers/object_controls_test.go
  • controllers/upgrade_controller.go
  • controllers/upgrade_controller_test.go
  • docker/Dockerfile.devel
  • go.mod
  • hack/validate-api-version-unpublished.sh
  • hack/validate-published-api-module.sh
  • hack/validate-shared-dependencies.sh
  • internal/consts/consts.go
  • internal/nvidiadriver/nvidiadriver.go
  • internal/nvidiadriver/nvidiadriver_errors_test.go
  • internal/nvidiadriver/nvidiadriver_test.go
  • internal/state/configurable_state.go
  • internal/state/dra_driver.go
  • internal/state/driver.go
  • internal/state/driver_manifest_test.go
  • internal/state/driver_test.go
  • internal/state/nodepool.go
  • internal/state/nodepool_test.go
  • internal/validator/validator_test.go
  • tools/generate-third-party-notices.sh
💤 Files with no reviewable changes (1)
  • internal/consts/consts.go

Included review availability: Your plan provides up to 12 included reviews per hour; 11 remain after this review.

Comment on lines +31 to +33
contains(github.event.pull_request.title, 'operator') &&
contains(github.event.pull_request.title, 'version') &&
contains(github.event.pull_request.title, 'bump')

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🔎 Supported by static analysis

🏁 Script executed:

sed -n '1,120p' .github/workflows/api-release-checks.yaml
rg -n --glob '!vendor/**' 'validate-api-version-unpublished|API Release Checks|operator.*version.*bump|OPERATOR_VERSION|api/v' .github Makefile hack versions.mk . 2>/dev/null | head -240

Repository: NVIDIA/gpu-operator

Length of output: 10771


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- validator ---'
sed -n '1,220p' hack/validate-api-version-unpublished.sh
printf '%s\n' '--- make/version definitions ---'
sed -n '220,265p' Makefile
sed -n '1,180p' versions.mk
printf '%s\n' '--- release/version references ---'
rg -n -i --glob '!vendor/**' --glob '!third_party/**' '(version bump|bump.*version|release.*version|operator.*version|api.*tag|unpublished|pull request.*title|title.*operator)' .github README.md CONTRIBUTING.md AGENTS.md PROJECT Makefile hack versions.mk 2>/dev/null | head -300
printf '%s\n' '--- release workflow/template filenames ---'
git ls-files '.github' | rg -i '(release|pull|pr|version|api)'

Repository: NVIDIA/gpu-operator

Length of output: 15870


🤖 get_repo_knowledge executed:

get_repo_knowledge NVIDIA/gpu-operator /tmp/coderabbit-repo-knowledge/nvidia-gpu-operator-eed98df4/conventions

Length of output: 4401


🏁 Script executed:

#!/bin/bash
set -e
printf '%s\n' '--- pull request template ---'
sed -n '1,220p' .github/PULL_REQUEST_TEMPLATE.md
printf '%s\n' '--- contributing release guidance ---'
sed -n '45,75p' CONTRIBUTING.md
printf '%s\n' '--- API post-tag validation workflow ---'
sed -n '1,110p' .github/workflows/api-post-tag-validation.yaml
printf '%s\n' '--- release workflow triggers and version inputs ---'
sed -n '1,75p' .github/workflows/release.yaml
sed -n '1,55p' .github/workflows/release-rc-assets.yaml

Repository: NVIDIA/gpu-operator

Length of output: 8575


Run the API-tag check for version changes.

If a PR changes the API module version but its title does not contain all three required substrings, GitHub skips api-version-unpublished. The validator then does not check whether api/<version> already exists, so a title such as Release v25.3.0 can bypass this release check. The PR template does not require the current title format.

Gate the job on changed API version metadata, or use a required release signal that cannot be omitted by changing the title.

Relocate shared image path logic and NVIDIADriver constants so api/ no longer imports root internal packages ahead of becoming a standalone Go module.

Signed-off-by: Aryan Gorwade <agorwade@nvidia.com>
Give API consumers a Go-compatible versioned module while keeping root development builds pinned to the local API source.

Signed-off-by: Aryan Gorwade <agorwade@nvidia.com>
Signed-off-by: Aryan Gorwade <agorwade@nvidia.com>
Fail CI when direct dependencies shared by the root and API modules use different versions.

Signed-off-by: Aryan Gorwade <agorwade@nvidia.com>
Verify operator and API tags share a commit and that released binaries record the independently downloadable API module version.

Signed-off-by: Aryan Gorwade <agorwade@nvidia.com>
Have Dependabot update shared root and API dependencies together while preserving grouped Kubernetes upgrades.

Signed-off-by: Aryan Gorwade <agorwade@nvidia.com>
Run the unpublished-tag check for pull requests whose titles identify an operator version bump.

Signed-off-by: Aryan Gorwade <agorwade@nvidia.com>
Skip internal pipelines for API-only tags and prevent them from reaching Nspect or NGC publishing jobs.

Signed-off-by: Aryan Gorwade <agorwade@nvidia.com>
@aryangorwade
aryangorwade requested review from a team and removed request for karthikvetrivel September 22, 2026 19:00
Comment thread Makefile
$(if $(SKIP_REGISTRY),--skip-registry) \
--gpu-operator-version "$(IMAGE_TAG)"

validate-generated-assets: manifests generate generate-clientset sync-crds

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think with replace github.com/NVIDIA/gpu-operator/api => ./api plus the checked-in vendor/, root packages compile against vendor/github.com/NVIDIA/gpu-operator/api/..., not ./api. From the PR head, go list -f '{{.Dir}}' github.com/NVIDIA/gpu-operator/api/nvidia/v1 resolves to the vendor path.

I think we should have generate, generate-clientset and manifests depend on update-vendor, or add vendor to the diff here, so regenerating API code always leaves vendor/ consistent. maybe we can add a short not in AGENTS.md / CONTRIBUTING.md that api/ changes need make update-vendor.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • generate: can change /api; makes sense to run update-vendor at the end of this command
  • generate-clientset: same as above. Both of these read directly from /api and can change it
  • manifests: reads from /vendored and /api. The first step of this command should be update-vendor.

This could run go mod vendor up to three times and cause possible race conditions. The solution is to add a validate-vendor command that generates /vendor into a temporary directory and diffs against /api (unique tmp directories per invocation). This command will substitute update-vendor in the commands described above.

Some others that need this validation are:

  • cmd-*: prerequisite check
  • goimports: postprocess check
  • build-image: prerequisite check on the host
  • run: prerequisite check
  • lint: prerequisite check
  • build: postprocess check (would affect unit-test and coverage)
  • validate-modules: rewrite to use validate-vendor

Ideally only one command should run go mod vendor. I think this should be validate-generated-assets since it already writes to /api. What do you think?

API_MODULE="github.com/NVIDIA/gpu-operator/api"
UPSTREAM_REPOSITORY="${1:-https://github.com/NVIDIA/gpu-operator.git}"

api_version="$(go list -m -f '{{.Version}}' "${API_MODULE}")"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we also need to check if the api version maps to an operator version, basically validate the mapping here as well ? like we do inhack/validate-published-api-module.sh , so that we catch the issue before an image is published ?

@aryangorwade aryangorwade Oct 1, 2026 •

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the PR/pre-tag check, so the commit does not have operator version or api version tags at this point. Should it compare the operator version in versions.mk to the API version derived from root go.mod?

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants