Files
spinifex/internal/awsmodel/coverage.go
T
Julian Sommer e2fb37c0ac docs: publish only the AWS operations Spinifex serves
The coverage pages led with a percentage and an "x of y" count, and every
table listed the modelled operations Spinifex does not implement, which reads
as a scorecard against AWS rather than a statement of what the platform serves.

A published page now opens with the operation count alone, tables the
operations the gateway serves, and carries a separate not-applicable table with
each reason inline instead of footnotes. The unimplemented operations and the
counts move to docs/coverage/internal-report.md, which no docs-site slug points
at. A service with no implemented operations has no publishable page.
2026-09-15 10:28:35 +10:00

185 lines
6.5 KiB
Go

package awsmodel
import (
"fmt"
"sort"
"strings"
)
// DispatchInventory is the gateway-side operation registration state supplied
// to CompareOperations.
type DispatchInventory struct {
Registered []string
Stubbed []string
Unsupported []string
Opaque bool
Note string
}
// OperationCoverage is a deterministic model-versus-dispatch comparison.
// Implemented contains only modelled operations with a real handler; Extra
// contains registered operations absent from the pinned model.
type OperationCoverage struct {
Service Service
APIVersion string
Modelled []string
Registered []string
Implemented []string
Stubbed []string
Unsupported []string
Missing []string
Extra []string
Opaque bool
Note string
}
// CompareOperations compares one embedded service model with an authoritative
// gateway dispatch inventory.
func CompareOperations(service Service, dispatch DispatchInventory) (OperationCoverage, error) {
model, err := Load(service)
if err != nil {
return OperationCoverage{}, err
}
coverage := OperationCoverage{
Service: service,
APIVersion: model.Metadata().APIVersion,
Modelled: model.Operations(),
Opaque: dispatch.Opaque,
Note: dispatch.Note,
}
if dispatch.Opaque {
return coverage, nil
}
registered, err := uniqueSorted("registered", dispatch.Registered)
if err != nil {
return OperationCoverage{}, fmt.Errorf("awsmodel: %s dispatch: %w", service, err)
}
stubbed, err := uniqueSorted("stubbed", dispatch.Stubbed)
if err != nil {
return OperationCoverage{}, fmt.Errorf("awsmodel: %s dispatch: %w", service, err)
}
unsupported, err := uniqueSorted("unsupported", dispatch.Unsupported)
if err != nil {
return OperationCoverage{}, fmt.Errorf("awsmodel: %s dispatch: %w", service, err)
}
registeredSet := toSet(registered)
stubbedSet := toSet(stubbed)
unsupportedSet := toSet(unsupported)
for operation := range stubbedSet {
if !registeredSet[operation] {
return OperationCoverage{}, fmt.Errorf("awsmodel: %s stubbed operation %q is not registered", service, operation)
}
if unsupportedSet[operation] {
return OperationCoverage{}, fmt.Errorf("awsmodel: %s operation %q is both stubbed and unsupported", service, operation)
}
}
for operation := range unsupportedSet {
if !registeredSet[operation] {
return OperationCoverage{}, fmt.Errorf("awsmodel: %s unsupported operation %q is not registered", service, operation)
}
}
modelledSet := toSet(coverage.Modelled)
for _, operation := range coverage.Modelled {
if !registeredSet[operation] {
coverage.Missing = append(coverage.Missing, operation)
continue
}
if !stubbedSet[operation] && !unsupportedSet[operation] {
coverage.Implemented = append(coverage.Implemented, operation)
}
}
for _, operation := range registered {
if !modelledSet[operation] {
coverage.Extra = append(coverage.Extra, operation)
}
}
coverage.Registered = registered
coverage.Stubbed = stubbed
coverage.Unsupported = unsupported
return coverage, nil
}
func uniqueSorted(label string, values []string) ([]string, error) {
result := append([]string(nil), values...)
sort.Strings(result)
for index, value := range result {
if value == "" {
return nil, fmt.Errorf("%s operation is empty", label)
}
if index > 0 && result[index-1] == value {
return nil, fmt.Errorf("%s operation %q is duplicated", label, value)
}
}
return result, nil
}
func toSet(values []string) map[string]bool {
set := make(map[string]bool, len(values))
for _, value := range values {
set[value] = true
}
return set
}
// RenderCoverageSummary renders the cross-service counts as plain text for a
// terminal. The published pages carry the per-operation detail.
func RenderCoverageSummary(coverages []OperationCoverage) string {
var report strings.Builder
fmt.Fprintf(&report, "AWS model operation coverage (aws-sdk-go %s)\n\n", SourceSDKVersion)
for _, coverage := range sortedCoverages(coverages) {
if coverage.Opaque {
fmt.Fprintf(&report, "%-24s %-12s not enumerable\n", coverage.Service, coverage.APIVersion)
continue
}
fmt.Fprintf(&report, "%-24s %-12s %3d of %3d implemented (%5.1f%%), %3d stubbed, %3d unsupported, %3d outside the model\n",
coverage.Service, coverage.APIVersion, len(coverage.Implemented), len(coverage.Modelled),
coverage.ImplementedPercent(), len(coverage.Stubbed), len(coverage.Unsupported), len(coverage.Extra))
}
return report.String()
}
// RenderInternalReport renders the full comparison, including the operations
// the published pages leave out. It is not a site page: the docs build renders
// only the slugs it is configured with, and this file is not one of them.
func RenderInternalReport(coverages []OperationCoverage) string {
var report strings.Builder
report.WriteString("# AWS Model Operation Coverage (internal)\n\n")
report.WriteString("Generated by `make aws-model-coverage`. This file is not published: it carries the counts and the unimplemented operations that the pages under this directory deliberately leave out.\n\n")
fmt.Fprintf(&report, "Pinned model source: `aws-sdk-go %s`.\n\n", SourceSDKVersion)
for _, coverage := range sortedCoverages(coverages) {
fmt.Fprintf(&report, "## %s\n\n", coverage.Service)
if coverage.Opaque {
fmt.Fprintf(&report, "`%s` — not enumerable. %s\n\n", coverage.APIVersion, coverage.Note)
continue
}
fmt.Fprintf(&report, "`%s` — %d of %d modelled operations implemented (%.1f%%), %d stubbed, %d unsupported, %d registered outside the pinned model.\n\n",
coverage.APIVersion, len(coverage.Implemented), len(coverage.Modelled), coverage.ImplementedPercent(),
len(coverage.Stubbed), len(coverage.Unsupported), len(coverage.Extra))
writeOperationList(&report, "Not implemented", coverage.Missing)
writeOperationList(&report, "Stubbed", coverage.Stubbed)
writeOperationList(&report, "Registered and refused", coverage.Unsupported)
writeOperationList(&report, "Registered outside the pinned model", coverage.Extra)
}
return report.String()
}
func writeOperationList(report *strings.Builder, heading string, operations []string) {
if len(operations) == 0 {
return
}
fmt.Fprintf(report, "### %s\n\n", heading)
for _, operation := range operations {
fmt.Fprintf(report, "- `%s`\n", operation)
}
report.WriteString("\n")
}
func sortedCoverages(coverages []OperationCoverage) []OperationCoverage {
ordered := append([]OperationCoverage(nil), coverages...)
sort.Slice(ordered, func(i, j int) bool { return ordered[i].Service < ordered[j].Service })
return ordered
}