[DRAFT] feat: add API tier classification and tier-report command - #3
[DRAFT] feat: add API tier classification and tier-report command#3jctanner wants to merge 1 commit into
Conversation
Add automated API tier classification for RHOAI CRDs, REST APIs, and SDKs (RHAIRFE-2077). Replaces the manual spreadsheet workflow with a declarative api_tiers.yaml mapping file and a new tier-report command that generates KCS-article-format output with coverage gap detection. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
📝 WalkthroughWalkthroughAdds YAML and Go models for API tier mappings with wildcard CRD matching. Extracted CRDs can receive configured API tiers, which are serialized and shown in existing Markdown views. A new tier-report renderer produces Markdown, CSV, and JSON reports with missing and stale configuration gaps, including REST API and SDK entries. The CLI accepts platform JSON files or directories, loads tier configuration, selects an output format, writes or prints the report, and emits coverage counts. Estimated code review effort: 4 (Complex) | ~45 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (2)
pkg/config/api_tiers.go (1)
53-73: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick winImprove partial wildcard precedence.
Currently, a partial wildcard (e.g., specific
Kind, but*forVersion) is treated identically to a full wildcard (*for both). Whichever appears first in the YAML iteration will be captured bywildcardMatchand lock out subsequent wildcard matches. This could lead to unexpected behavior if users define a mix of full and partial wildcards.Consider scoring wildcard specificity so that a more specific partial wildcard overrides a generic one, ensuring deterministic evaluation regardless of the YAML declaration order.
💡 Proposed refactor for deterministic wildcard priority
func (c *APITiersConfig) MatchCRDTier(group, kind, version string) (string, bool) { - var wildcardMatch string + var partialMatch string + var fullWildcardMatch string + for _, entry := range c.CRDs { if entry.Group != group { continue } - kindMatch := entry.Kind == kind || entry.Kind == "*" - versionMatch := entry.Version == version || entry.Version == "*" + + isKindWildcard := entry.Kind == "*" + isVersionWildcard := entry.Version == "*" + + kindMatch := entry.Kind == kind || isKindWildcard + versionMatch := entry.Version == version || isVersionWildcard + if !kindMatch || !versionMatch { continue } - if entry.Kind == kind && entry.Version == version { + + if !isKindWildcard && !isVersionWildcard { + // Exact match wins immediately return entry.Tier, true } - if wildcardMatch == "" { - wildcardMatch = entry.Tier + + if (!isKindWildcard || !isVersionWildcard) && partialMatch == "" { + // Partial wildcard (e.g. kind is exact, version is *) + partialMatch = entry.Tier + } else if fullWildcardMatch == "" { + // Full wildcard (* for both) + fullWildcardMatch = entry.Tier } } - if wildcardMatch != "" { - return wildcardMatch, true + + if partialMatch != "" { + return partialMatch, true + } + if fullWildcardMatch != "" { + return fullWildcardMatch, true } return "", false }🤖 Prompt for 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. In `@pkg/config/api_tiers.go` around lines 53 - 73, Update the wildcard selection logic in the CRD tier lookup loop to score matching entries by specificity: exact kind/version matches remain highest priority, partial wildcards must outrank full wildcards, and equal-specificity matches should retain deterministic behavior independent of YAML order. Replace the single wildcardMatch capture with tracking the best matching tier and its specificity before returning.cmd/arch-analyzer/cmd_tier_report.go (1)
35-41: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueUse
filepath.Joinfor cross-platform path construction.String concatenation for file paths can lead to malformed strings (e.g.,
//platform-architecture.jsonifinputPathhas a trailing slash). Usingfilepath.Joinhandles path separators cleanly.🛠 Proposed refactor
Add
"path/filepath"to your imports, then update the path construction:jsonPath := inputPath if info.IsDir() { - jsonPath = inputPath + "/platform-architecture.json" + jsonPath = filepath.Join(inputPath, "platform-architecture.json") if _, err := os.Stat(jsonPath); err != nil { return fmt.Errorf("no platform-architecture.json found in %s", inputPath) } }🤖 Prompt for 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. In `@cmd/arch-analyzer/cmd_tier_report.go` around lines 35 - 41, Update the directory branch in the tier report path resolution to use filepath.Join when constructing jsonPath with inputPath and "platform-architecture.json". Add the path/filepath import and preserve the existing os.Stat validation and error behavior.
🤖 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/renderer/tier_report.go`:
- Around line 70-72: Replace the naive plural construction in the tier report
API-version generation with a basic heuristic pluralizer: lowercase kind names
ending in y (except ey) should become ies, names ending in s, x, ch, or sh
should receive es, and all others should receive s. Preserve the existing
apiVersion formatting using the computed plural, group, and version.
- Around line 171-181: Update RenderTierReportCSV to use encoding/csv for
writing the header and each report entry instead of fmt.Sprintf with %q.
Preserve the existing column order and output, and handle writer errors
consistently while returning the generated CSV string.
---
Nitpick comments:
In `@cmd/arch-analyzer/cmd_tier_report.go`:
- Around line 35-41: Update the directory branch in the tier report path
resolution to use filepath.Join when constructing jsonPath with inputPath and
"platform-architecture.json". Add the path/filepath import and preserve the
existing os.Stat validation and error behavior.
In `@pkg/config/api_tiers.go`:
- Around line 53-73: Update the wildcard selection logic in the CRD tier lookup
loop to score matching entries by specificity: exact kind/version matches remain
highest priority, partial wildcards must outrank full wildcards, and
equal-specificity matches should retain deterministic behavior independent of
YAML order. Replace the single wildcardMatch capture with tracking the best
matching tier and its specificity before returning.
🪄 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: Repository: ugiordan/coderabbit/.coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 1b9b6753-01e1-4d3d-8a3a-edf798108522
📒 Files selected for processing (11)
api_tiers.yamlcmd/arch-analyzer/cmd_tier_report.gocmd/arch-analyzer/main.gopkg/config/api_tiers.gopkg/extractor/api_tiers.gopkg/extractor/extract.gopkg/extractor/types.gopkg/renderer/component_markdown.gopkg/renderer/docs_platform.gopkg/renderer/report.gopkg/renderer/tier_report.go
| // Build plural.group/version format for the API version example | ||
| plural := strings.ToLower(kind) + "s" | ||
| apiVersion := fmt.Sprintf("%s.%s/%s", plural, group, version) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Improve pluralization logic for Kubernetes API versions.
The naive approach of appending "s" to the lowercase kind produces incorrect plural names for many common Kubernetes resources (e.g., NetworkPolicy becomes networkpolicys, Ingress becomes ingresss).
Consider implementing a basic heuristic pluralizer or extracting the plural field directly from the CRD definition to ensure accurate API version strings in the generated reports.
💡 Proposed basic heuristic pluralizer
lower := strings.ToLower(kind)
var plural string
switch {
case strings.HasSuffix(lower, "y") && !strings.HasSuffix(lower, "ey"):
plural = strings.TrimSuffix(lower, "y") + "ies"
case strings.HasSuffix(lower, "s"), strings.HasSuffix(lower, "x"), strings.HasSuffix(lower, "ch"), strings.HasSuffix(lower, "sh"):
plural = lower + "es"
default:
plural = lower + "s"
}
apiVersion := fmt.Sprintf("%s.%s/%s", plural, group, version)🤖 Prompt for 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.
In `@pkg/renderer/tier_report.go` around lines 70 - 72, Replace the naive plural
construction in the tier report API-version generation with a basic heuristic
pluralizer: lowercase kind names ending in y (except ey) should become ies,
names ending in s, x, ch, or sh should receive es, and all others should receive
s. Preserve the existing apiVersion formatting using the computed plural, group,
and version.
| func RenderTierReportCSV(report *TierReportResult) string { | ||
| var b strings.Builder | ||
|
|
||
| b.WriteString("api_version_example,api_tier,category,component\n") | ||
| for _, entry := range report.Entries { | ||
| b.WriteString(fmt.Sprintf("%q,%q,%q,%q\n", | ||
| entry.APIVersionExample, entry.APITier, entry.Category, entry.Component)) | ||
| } | ||
|
|
||
| return b.String() | ||
| } |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Use encoding/csv for standard CSV formatting.
Using %q with fmt.Sprintf generates Go-style string literals, escaping internal double quotes with a backslash (\"). This violates RFC 4180, which requires escaping double quotes by doubling them (""). Standardizing on the encoding/csv package avoids parsing failures in strict downstream CSV processors.
📦 Proposed fix to use `encoding/csv`
Add "encoding/csv" to your file imports, then update the function:
// RenderTierReportCSV renders the tier report as CSV.
func RenderTierReportCSV(report *TierReportResult) string {
var b strings.Builder
-
- b.WriteString("api_version_example,api_tier,category,component\n")
- for _, entry := range report.Entries {
- b.WriteString(fmt.Sprintf("%q,%q,%q,%q\n",
- entry.APIVersionExample, entry.APITier, entry.Category, entry.Component))
- }
+ w := csv.NewWriter(&b)
+ w.Write([]string{"api_version_example", "api_tier", "category", "component"})
+ for _, entry := range report.Entries {
+ w.Write([]string{entry.APIVersionExample, entry.APITier, entry.Category, entry.Component})
+ }
+ w.Flush()
return b.String()
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| func RenderTierReportCSV(report *TierReportResult) string { | |
| var b strings.Builder | |
| b.WriteString("api_version_example,api_tier,category,component\n") | |
| for _, entry := range report.Entries { | |
| b.WriteString(fmt.Sprintf("%q,%q,%q,%q\n", | |
| entry.APIVersionExample, entry.APITier, entry.Category, entry.Component)) | |
| } | |
| return b.String() | |
| } | |
| func RenderTierReportCSV(report *TierReportResult) string { | |
| var b strings.Builder | |
| w := csv.NewWriter(&b) | |
| w.Write([]string{"api_version_example", "api_tier", "category", "component"}) | |
| for _, entry := range report.Entries { | |
| w.Write([]string{entry.APIVersionExample, entry.APITier, entry.Category, entry.Component}) | |
| } | |
| w.Flush() | |
| return b.String() | |
| } |
🤖 Prompt for 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.
In `@pkg/renderer/tier_report.go` around lines 171 - 181, Update
RenderTierReportCSV to use encoding/csv for writing the header and each report
entry instead of fmt.Sprintf with %q. Preserve the existing column order and
output, and handle writer errors consistently while returning the generated CSV
string.
Add automated API tier classification for RHOAI CRDs, REST APIs, and SDKs (RHAIRFE-2077). Replaces the manual spreadsheet workflow with a declarative api_tiers.yaml mapping file and a new tier-report command that generates KCS-article-format output with coverage gap detection.
Summary by CodeRabbit
New Features
tier-reportcommand to generate Markdown, CSV, or JSON reports.Documentation