Skip to content

feat(status): add component provenance tracking to environment status#635

Merged
ArangoGutierrez merged 2 commits intoNVIDIA:mainfrom
ArangoGutierrez:feat/issue-567-provenance
Feb 12, 2026
Merged

feat(status): add component provenance tracking to environment status#635
ArangoGutierrez merged 2 commits intoNVIDIA:mainfrom
ArangoGutierrez:feat/issue-567-provenance

Conversation

@ArangoGutierrez
Copy link
Copy Markdown
Collaborator

Summary

  • Add ComponentsStatus to EnvironmentStatus that tracks how each component was provisioned (source type, version, branch, git repo/ref/commit)
  • Provisioner.Run() now returns (*ComponentsStatus, error) with provenance after provisioning
  • holodeck describe shows source details for all components (e.g., Container Toolkit: v1.17.3 (git, abc12345))

Context

Part of #567 (Phase 3 — Provenance Tracking). This PR is independent of the driver/runtime multi-source phases and can be merged on its own.

New Types

  • ComponentProvenance — tracks source, version, branch, repo, ref, commit
  • ComponentsStatus — per-component provenance (driver, runtime, toolkit, kubernetes)
  • EnvironmentStatus.Components — new optional field

Changes

  • provisioner.Run() signature: (*ComponentsStatus, error) — all callers updated
  • BuildComponentsStatus() — builds provenance from environment spec
  • CLI describe merges status provenance with spec data for display
  • formatSourceDetail() helper for clean output formatting

Test plan

  • 10 unit tests for BuildComponentsStatus covering all component/source combinations
  • go build ./... passes
  • go vet ./... passes
  • All existing tests pass (api, provisioner, templates)
  • E2E: verify holodeck describe shows provenance after provisioning

Add ComponentsStatus to EnvironmentStatus that tracks how each component
was provisioned (source type, version, branch, git repo/ref/commit).
Populated after successful provisioning and displayed in `holodeck describe`.

- New types: ComponentProvenance, ComponentsStatus
- Provisioner.Run() now returns (*ComponentsStatus, error)
- CLI describe shows source details (git commit, branch tracking)
- Supports CTK and K8s multi-source; driver/runtime ready for Phase 1/2

Closes: NVIDIA#567 (Phase 3 — provenance tracking)
Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
@coveralls
Copy link
Copy Markdown

coveralls commented Feb 11, 2026

Pull Request Test Coverage Report for Build 21917678567

Details

  • 79 of 97 (81.44%) changed or added relevant lines in 3 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage increased (+0.8%) to 46.706%

Changes Missing Coverage Covered Lines Changed/Added Lines %
pkg/provisioner/cluster.go 0 1 0.0%
pkg/provisioner/provenance.go 79 85 92.94%
pkg/provisioner/provisioner.go 0 11 0.0%
Totals Coverage Status
Change from base Build 21903852228: 0.8%
Covered Lines: 2368
Relevant Lines: 5070

💛 - Coveralls

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds provenance tracking for provisioned components by extending the Environment status API, returning component provenance from the provisioner, and surfacing those details in holodeck describe.

Changes:

  • Add ComponentProvenance, ComponentsStatus, and EnvironmentStatus.Components to capture per-component source/version/ref/commit metadata.
  • Change Provisioner.Run() to return (*ComponentsStatus, error) and persist this status from CLI flows.
  • Update holodeck describe table output to include provenance details (git/latest hints, commit/ref/branch, etc.).

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
api/holodeck/v1alpha1/types.go Adds new status types/fields for component provenance tracking.
pkg/provisioner/provisioner.go Updates Run() signature and returns component provenance status.
pkg/provisioner/provenance.go Introduces BuildComponentsStatus() helper to build provenance from spec.
pkg/provisioner/provenance_test.go Adds unit tests for BuildComponentsStatus().
cmd/cli/create/create.go Captures ComponentsStatus after provisioning and stores it in env status.
cmd/cli/update/update.go Captures ComponentsStatus after provisioning and stores it in env status.
cmd/cli/describe/describe.go Merges status provenance into describe output and enhances table formatting.
pkg/provisioner/cluster.go Updates cluster provisioning to accommodate new Run() return signature.
cmd/action/ci/entrypoint.go Updates CI action provisioning call for new Run() signature.
tests/aws_test.go Updates E2E test to handle new Run() return value.

Comment on lines 448 to +476
if env.Spec.Kubernetes.Install {
k8sVersion := env.Spec.Kubernetes.KubernetesVersion
if env.Spec.Kubernetes.Release != nil {
k8sVersion = env.Spec.Kubernetes.Release.Version
}
output.Components.Kubernetes = &KubernetesInfo{
info := &KubernetesInfo{
Install: true,
Installer: env.Spec.Kubernetes.KubernetesInstaller,
Version: k8sVersion,
Source: string(env.Spec.Kubernetes.Source),
}
if info.Source == "" {
info.Source = "release"
}
if env.Status.Components != nil && env.Status.Components.Kubernetes != nil {
p := env.Status.Components.Kubernetes
if p.Repo != "" {
info.Repo = p.Repo
}
if p.Ref != "" {
info.Ref = p.Ref
}
if p.Commit != "" {
info.Commit = p.Commit
}
if p.Branch != "" {
info.Branch = p.Branch
}
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

Similarly, the Kubernetes describe output only pulls repo/ref/commit/branch from env.Status.Components.Kubernetes and doesn’t override Source/Version when status is present. If provisioning resolves a specific commit/version (or applies defaults), describe may not reflect what was actually installed. Consider using status to override Source/Version (and potentially Installer if it can differ) when those fields are populated.

Copilot uses AI. Check for mistakes.
Comment on lines +523 to +538
// formatSourceDetail builds a parenthetical detail string showing source provenance.
// Examples: " (package)", " (git, abc12345)", " (latest, main)"
func formatSourceDetail(source, ref, commit, branch string) string {
if source == "" || source == "package" || source == "release" {
return ""
}
parts := source
if commit != "" {
parts += ", " + commit
} else if ref != "" {
parts += ", " + ref
} else if branch != "" {
parts += ", " + branch
}
return " (" + parts + ")"
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

The new provenance formatting logic (formatSourceDetail and its usage in printTableFormat) isn’t covered by unit tests in this package. Adding focused tests for key combinations (package/release vs git/latest, commit vs ref vs branch, and CDI-enabled toolkit) would help prevent regressions in CLI output.

Copilot generated this review using guidance from repository custom instructions.
Comment on lines +70 to +86
switch prov.Source {
case "package":
if nct.Package != nil {
prov.Version = nct.Package.Version
} else if nct.Version != "" {
prov.Version = nct.Version
}
case "git":
if nct.Git != nil {
prov.Repo = nct.Git.Repo
prov.Ref = nct.Git.Ref
}
case "latest":
if nct.Latest != nil {
prov.Branch = nct.Latest.Track
prov.Repo = nct.Latest.Repo
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

BuildComponentsStatus currently leaves default provenance details empty for CTK git/latest when the spec omits optional fields. For example, if CTK git is used with an empty repo, or CTK latest is used with Latest=nil, the templates default repo/track branch (e.g., main + the default NVIDIA repo), but this status won’t reflect that. Consider applying the same defaults as templates.NewContainerToolkit so describe/status provenance matches what was actually provisioned.

Copilot uses AI. Check for mistakes.
Comment on lines +102 to +118
switch prov.Source {
case "release":
if k.Release != nil {
prov.Version = k.Release.Version
} else if k.KubernetesVersion != "" {
prov.Version = k.KubernetesVersion
}
case "git":
if k.Git != nil {
prov.Repo = k.Git.Repo
prov.Ref = k.Git.Ref
}
case "latest":
if k.Latest != nil {
prov.Branch = k.Latest.Track
prov.Repo = k.Latest.Repo
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

BuildComponentsStatus doesn’t apply the same default repo/track branch behavior as templates.NewKubernetes for git/latest sources. If Kubernetes git is used with an empty repo, or latest is used with Latest=nil, the provisioner defaults (kubernetes.git repo, master) will be used but won’t be captured in status provenance. Consider filling prov.Repo/prov.Branch with the same defaults as templates.NewKubernetes so provenance is accurate.

Copilot uses AI. Check for mistakes.
Comment on lines +401 to +415
if env.Status.Components != nil && env.Status.Components.Runtime != nil {
p := env.Status.Components.Runtime
info.Source = p.Source
if p.Repo != "" {
info.Repo = p.Repo
}
if p.Ref != "" {
info.Ref = p.Ref
}
if p.Commit != "" {
info.Commit = p.Commit
}
if p.Branch != "" {
info.Branch = p.Branch
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

buildDescribeOutput merges status provenance for the container runtime, but it never overrides Version from env.Status.Components.Runtime when it is present. That means describe output can show a stale/incorrect runtime version if provisioning resolved/installed a different version. Consider taking Version (and any other populated provenance fields) from status with precedence over spec, similar to the driver block above.

Copilot uses AI. Check for mistakes.
Comment on lines 420 to +444
if env.Spec.NVIDIAContainerToolkit.Install {
output.Components.ContainerToolkit = &ContainerToolkitInfo{
info := &ContainerToolkitInfo{
Install: true,
Source: string(env.Spec.NVIDIAContainerToolkit.Source),
Version: env.Spec.NVIDIAContainerToolkit.Version,
EnableCDI: env.Spec.NVIDIAContainerToolkit.EnableCDI,
}
if info.Source == "" {
info.Source = "package"
}
if env.Status.Components != nil && env.Status.Components.Toolkit != nil {
p := env.Status.Components.Toolkit
if p.Repo != "" {
info.Repo = p.Repo
}
if p.Ref != "" {
info.Ref = p.Ref
}
if p.Commit != "" {
info.Commit = p.Commit
}
if p.Branch != "" {
info.Branch = p.Branch
}
}
Copy link

Copilot AI Feb 11, 2026

Choose a reason for hiding this comment

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

buildDescribeOutput merges provenance from env.Status.Components.Toolkit, but it does not override Source/Version from status (only repo/ref/commit/branch). If provisioning sets a resolved Source/Version (or defaults), describe output will still reflect spec values instead of the post-provisioning status. Consider applying the same precedence rules as the driver block (use non-empty status fields to overwrite spec fields).

Copilot uses AI. Check for mistakes.
Resolves gocritic ifElseChain lint warning in formatSourceDetail.

Signed-off-by: Carlos Eduardo Arango Gutierrez <eduardoa@nvidia.com>
@ArangoGutierrez ArangoGutierrez merged commit 27e4faf into NVIDIA:main Feb 12, 2026
19 checks passed
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