Skip to content

[DRAFT] feat: add API tier classification and tier-report command - #3

Draft
jctanner wants to merge 1 commit into
ugiordan:mainfrom
jctanner:feature/api_tiers
Draft

[DRAFT] feat: add API tier classification and tier-report command#3
jctanner wants to merge 1 commit into
ugiordan:mainfrom
jctanner:feature/api_tiers

Conversation

@jctanner

@jctanner jctanner commented Jul 16, 2026

Copy link
Copy Markdown

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

    • Added API tier configuration for CRDs, REST APIs, and SDKs, including wildcard matching.
    • Added the tier-report command to generate Markdown, CSV, or JSON reports.
    • Reports include API tier assignments, coverage gaps, and stale configuration entries.
    • Added API tier details to CRD tables and ownership documentation.
  • Documentation

    • Updated command-line help with tier reporting options and usage.

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>
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds 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)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: API tier classification plus the new tier-report command.

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.

❤️ Share

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: 2

🧹 Nitpick comments (2)
pkg/config/api_tiers.go (1)

53-73: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Improve partial wildcard precedence.

Currently, a partial wildcard (e.g., specific Kind, but * for Version) is treated identically to a full wildcard (* for both). Whichever appears first in the YAML iteration will be captured by wildcardMatch and 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 value

Use filepath.Join for cross-platform path construction.

String concatenation for file paths can lead to malformed strings (e.g., //platform-architecture.json if inputPath has a trailing slash). Using filepath.Join handles 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

📥 Commits

Reviewing files that changed from the base of the PR and between 5cdc2e7 and cdb5e05.

📒 Files selected for processing (11)
  • api_tiers.yaml
  • cmd/arch-analyzer/cmd_tier_report.go
  • cmd/arch-analyzer/main.go
  • pkg/config/api_tiers.go
  • pkg/extractor/api_tiers.go
  • pkg/extractor/extract.go
  • pkg/extractor/types.go
  • pkg/renderer/component_markdown.go
  • pkg/renderer/docs_platform.go
  • pkg/renderer/report.go
  • pkg/renderer/tier_report.go

Comment on lines +70 to +72
// Build plural.group/version format for the API version example
plural := strings.ToLower(kind) + "s"
apiVersion := fmt.Sprintf("%s.%s/%s", plural, group, version)

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 | 🟡 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.

Comment on lines +171 to +181
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()
}

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 | 🟡 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.

Suggested change
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.

@jctanner jctanner changed the title feat: add API tier classification and tier-report command [DRAFT] feat: add API tier classification and tier-report command Jul 16, 2026
@jctanner
jctanner marked this pull request as draft July 16, 2026 20:41
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.

1 participant