feat(aicr): wrap facade alias types as facade-owned structs#1111
Conversation
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughThis PR migrates the NVIDIA AICR facade package from transparent type aliases to facade-owned wrapper structs with a bidirectional translation layer. The Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
Suggested labels
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
Coverage Report ✅
Coverage BadgeNo Go source files changed in this PR. |
866c3be to
50458bb
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@pkg/aicr/translate.go`:
- Around line 104-107: The fallback snapshot reconstruction only copies
APIVersion and Kind and drops CapturedAt; update the code that builds the
snapshot (the block creating out := &snapshotter.Snapshot{} in the fallback
path) to also preserve the timestamp by assigning out.CapturedAt = s.CapturedAt
(i.e., copy s.CapturedAt into the snapshot before returning) so
Snapshot.RoundTrip of public fields remains faithful.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Enterprise
Run ID: df0dbcaa-3ce6-4e12-8a87-a9c50e69caef
📒 Files selected for processing (6)
docs/integrator/go-library.mddocs/integrator/public-api.mdpkg/aicr/aicr.gopkg/aicr/translate.gopkg/aicr/translate_internal_test.gopkg/aicr/types.go
Two coordinated changes shipped together so external Go importers migrate once: **1. Move pkg/aicr → pkg/client/v1** The previous pkg/aicr/ location read ambiguously (github.com/NVIDIA/aicr/pkg/aicr — duplicative). The new path follows the conventional Go SDK shape: pkg/client/v1/ with versioned `v1` signaling semver commitment, package name still `aicr`. Matches the existing pkg/api/validator/v1 pattern. External importers: - import aicr "github.com/NVIDIA/aicr/pkg/aicr" + import aicr "github.com/NVIDIA/aicr/pkg/client/v1" In-tree consumers (pkg/cli, pkg/api) updated mechanically. **2. Wrap facade alias types as facade-owned structs (closes #1078)** Replace transparent type aliases on the Public (stable) facade with facade-owned structs and translate at the boundary, so internal pkg/snapshotter and pkg/validator type-shape changes no longer propagate to external Go importers without notice. - Snapshot: facade-owned struct (APIVersion, Kind, CapturedAt) + unexported internal *snapshotter.Snapshot for zero-copy round-trip through ValidateState. Same pattern as RecipeResult.internal. WrapSnapshot(*snapshotter.Snapshot) exported so callers that load snapshots externally (e.g., CLI loading from YAML) can lift. - AgentConfig: facade-owned struct mirroring every field of snapshotter.AgentConfig. Tolerations keep k8s.io/api/core/v1 type. - PhaseResult: facade-owned struct with Phase/Status/Duration plus Summary (CTRF count breakdown), RawReport (marshaled CTRF JSON), and Report (typed *ctrf.Report retained for in-tree consumers that merge per-phase reports via ctrf.MergeReports). - Phase / phase constants: facade-owned typedef and string consts whose values match pkg/api/validator/v1 for byte-identical wire round-trip. - ReportSummary: new facade-owned type with CTRF count fields. CollectSnapshot and ValidateState translate at the boundary via toInternalAgentConfig / fromInternalSnapshot / toInternalSnapshot / fromInternalPhaseResults. The Recipe/AllowLists/Criteria/CriteriaRegistry aliases (introduced by #1077) remain aliases for now; #1078's scope covered the snapshotter/validator-tier aliases. docs/integrator/public-api.md updated to reflect the new path and the facade-ownership state. go-library.md updated. Closes #1078.
50458bb to
fe3e5c3
Compare
Summary
Replace the transparent type aliases on the
aicrPublic (stable) facade with facade-owned structs and translate at the boundary, so internalpkg/snapshotterandpkg/validatortype-shape changes no longer propagate to external Go importers without notice.Motivation / Context
Per
docs/integrator/public-api.md, thegithub.com/NVIDIA/aicrfacade is the Public (stable) contract — butSnapshot,AgentConfig,PhaseResult,Phase, and the phase constants were transparent type aliases to Public (evolving) packages. Any field-shape change in the source packages propagated to consumers without a minor-version signal, undermining the semver promise. This PR closes that gap so every type reachable from the stable surface is now facade-owned, with translation handled at each method boundary.Fixes: #1078
Related: #1076 (epic)
Type of Change
Component(s) Affected
cmd/aicr,pkg/cli)cmd/aicrd,pkg/api,pkg/server)pkg/recipe)pkg/bundler,pkg/component/*)pkg/collector,pkg/snapshotter)pkg/validator)pkg/errors,pkg/k8s)docs/,examples/)aicr/types.go,aicr/translate.go,aicr/aicr.go)Implementation Notes
Per-type translation shape (issue #1078 recommended option 1: wrap immediate type, drop transitively-referenced internal types):
SnapshotAPIVersion,Kind,CapturedAtparsed frommetadata.timestamp) + unexportedinternal *snapshotter.Snapshotfor zero-copy round-trip throughValidateState. Same pattern as existingRecipeResult.internal.AgentConfigsnapshotter.AgentConfig.Tolerationskept as[]corev1.Tolerationsincek8s.io/api/core/v1is itself a stable contract.PhaseResultSummary(CTRF counts, ergonomic pass/fail check) andRawReport []byte(marshaled CTRF JSON for callers needing per-test detail). Drops the*ctrf.ReportGo-type coupling — callers decodeRawReportagainst the CTRF spec athttps://ctrf.io.Phase+ 3 constantstype Phase stringwith constant values matchingpkg/api/validator/v1verbatim for byte-identical wire round-trip with the validator.ReportSummaryTranslation boundary:
CollectSnapshottranslates the return viafromInternalSnapshot;ValidateStatetranslatessnapin viatoInternalSnapshot(preserves internal pointer when set; rebuilds from public fields when nil) and the return slice viafromInternalPhaseResults. Helpers live intranslate.go.Behavior: No consumer-facing behavior change for the in-tree CLI / REST. The wire format on disk (snapshot YAML, CTRF JSON) is unchanged — the facade owns Go-type identity, not the wire schema.
Testing
New tests in
translate_internal_test.gocover every translation helper:toInternalAgentConfig: nil-safety + field-by-field mirror across all 20 fieldsfromInternalSnapshot/toInternalSnapshot: nil-safety, wrap-and-unwrap pointer preservation, rebuild-from-public-fields fallback, RFC3339 timestamp parsing (including unparseable-leaves-zero case)fromInternalPhaseResults/fromInternalPhaseResult: nil/empty contract, slice ordering, dual CTRF Summary + RawReport population, nil-Report path, value-pinning of phase constants to the validator's wire formatCoverage delta on
./.(the aicr package): 63.3% → 66.0% (+2.7%). All new functions intranslate.goare at 100% exceptfromInternalPhaseResultat 90% (thejson.Marshalerror branch is not realistically reachable). No new exported functions with 0% coverage.Risk Assessment
Rollout notes: No migration required for in-tree CLI / REST callers —
pkg/cliandpkg/api/server.goeither don't reach into these types or will adopt the facade-owned shape transparently via #1108. External Go importers that pinnedaicr.Snapshot's fields will see the facade now exposes a narrower public surface (no direct access toMeasurements/Fingerprint/header.Header). Consumers needing those should importpkg/snapshotterdirectly; the recommendation is documented in the updateddocs/integrator/public-api.md.Checklist
make testwith-race)make lint)docs/integrator/public-api.md,docs/integrator/go-library.md)git commit -S)