From c08f34cb8a4a4cb08f9b4af61d8fd662530999ce Mon Sep 17 00:00:00 2001 From: Samuel K Date: Fri, 17 Apr 2026 21:59:24 -0500 Subject: [PATCH 1/3] chore: reset release version to 1.0.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 38 ----------------------------------- 2 files changed, 1 insertion(+), 39 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index a1961ec9..1772e6fa 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.1.0" + ".": "1.0.0" } diff --git a/CHANGELOG.md b/CHANGELOG.md index b0eac95b..825c32f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,39 +1 @@ # Changelog - -## [1.0.2](https://github.com/devsy-org/apiserver/compare/v1.0.1...v1.0.2) (2026-04-12) - - -### Bug Fixes - -* export shell variables to resolve shellcheck SC2034 warnings ([#12](https://github.com/devsy-org/apiserver/issues/12)) ([7e0ae3e](https://github.com/devsy-org/apiserver/commit/7e0ae3e6220065484433e3578328c8aa577ecf93)) - -## [1.0.1](https://github.com/devsy-org/apiserver/compare/v1.0.0...v1.0.1) (2026-04-12) - - -### Bug Fixes - -* move exclude-dirs to linters.exclusions.paths for golangci-lint v2 ([#10](https://github.com/devsy-org/apiserver/issues/10)) ([5539adf](https://github.com/devsy-org/apiserver/commit/5539adf2f95d4e6e3dea41a7ee6b600e44cf96a4)) - -## 1.0.0 (2026-04-12) - - -### Features - -* add group converter ([28c307a](https://github.com/devsy-org/apiserver/commit/28c307acd2deeb75f18b1142119698e0589fe178)) -* add status rest generator ([a087db8](https://github.com/devsy-org/apiserver/commit/a087db850f7feeb85b15134b4874f2c41d11a47b)) -* add status rest generator ([07b679f](https://github.com/devsy-org/apiserver/commit/07b679fb7d0ec741c203eeeb44cf8de0989ee3dc)) - - -### Bug Fixes - -* add tags for unversioned apis ([a106e2f](https://github.com/devsy-org/apiserver/commit/a106e2f2e0f1f9392dc8c4a873a9e3c37ecf74f7)) -* add tags for unversioned apis ([acc9f39](https://github.com/devsy-org/apiserver/commit/acc9f397b07e4b7da29d467d24095d425cbf8420)) -* breaking changes after version bump ([5f191d3](https://github.com/devsy-org/apiserver/commit/5f191d3077814787694d7cf317ed3d09df5b5a09)) -* bump k8s version to 1.31 ([56b9af3](https://github.com/devsy-org/apiserver/commit/56b9af3c14844c35e1ec7a7344ef8dbd0e4b58e1)) -* disable validatingadmissionpolicy plugin ([79262a1](https://github.com/devsy-org/apiserver/commit/79262a153ae84a37ee7b5d93c1aa152db28e9c0b)) -* disable validatingadmissionpolicy plugin via config not feature flag ([f17d504](https://github.com/devsy-org/apiserver/commit/f17d504a4d0da95e503189e4e039fcbab214e325)) -* force JSON serialization ([619975b](https://github.com/devsy-org/apiserver/commit/619975b667ebdaa1dd558dd7e399deb3dd2215e2)) -* new tracerprovider required by admissionConfig ([cac25ae](https://github.com/devsy-org/apiserver/commit/cac25ae971c3929d2af969dbd1db8927ad646bfc)) -* properly init config ([395e1e5](https://github.com/devsy-org/apiserver/commit/395e1e5c9eac0136182bf884d1a143f6fa4349e5)) -* resolve pre-commit trailing whitespace, EOF, and formatting issues ([#8](https://github.com/devsy-org/apiserver/issues/8)) ([1b18f03](https://github.com/devsy-org/apiserver/commit/1b18f038ccb8c408654d9941f8631ac809f19b61)) -* wrong done channel ([#26](https://github.com/devsy-org/apiserver/issues/26)) ([2a1d356](https://github.com/devsy-org/apiserver/commit/2a1d356b8c09f87fdc5ca0b746e2390c7ba72547)) From d03d39c0935fcad99f1811e9f92c49c3b193ee52 Mon Sep 17 00:00:00 2001 From: Samuel K Date: Sat, 18 Apr 2026 14:13:27 -0500 Subject: [PATCH 2/3] fix: resolve import alias collisions and NewRESTFunc signature in generator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bugs in the register generator: 1. Import alias collisions: aliases are formed by joining the last two path segments (e.g. storage/v1 → storagev1). When two modules share the same trailing segments, this produces duplicate aliases. Fixed by tracking seen aliases per APIGroup and disambiguating with the module name when a collision is detected. 2. NewRESTFunc signature: the template emitted `func() rest.Storage` but subresource closures called `RESTFunc(Factory)`. Fixed the signature to `func(factory managerfactory.SharedManagerFactory) rest.Storage` and updated all call sites to pass Factory. --- pkg/generate/parse.go | 68 ++++++++++++++++----------- pkg/generate/unversioned_generator.go | 7 +-- 2 files changed, 45 insertions(+), 30 deletions(-) diff --git a/pkg/generate/parse.go b/pkg/generate/parse.go index 206138d1..5b5fb9ef 100644 --- a/pkg/generate/parse.go +++ b/pkg/generate/parse.go @@ -42,6 +42,43 @@ type APIGroup struct { Aliases map[string]*Alias Pkg *types.Package PkgPath string + + // importAliases tracks import alias → package path to detect and resolve collisions. + importAliases map[string]string +} + +// resolveImportAlias returns a unique import alias for the given package path. +// The base alias is formed from the last two path segments (e.g. "storage/v1" → "storagev1"). +// If that alias is already used by a different package, the module name (third path segment) +// is prepended to disambiguate (e.g. "agentstoragev1"). +func (g *APIGroup) resolveImportAlias(pkgPath string) string { + base := path.Base(path.Dir(pkgPath)) + path.Base(pkgPath) + + if existing, ok := g.importAliases[base]; ok && existing == pkgPath { + return base + } + + if _, ok := g.importAliases[base]; !ok { + g.importAliases[base] = pkgPath + return base + } + + // Collision: disambiguate using the module name (third segment of the import path). + parts := strings.Split(pkgPath, "/") + moduleName := "" + if len(parts) >= 3 { + moduleName = parts[2] + } + prefix := strings.ReplaceAll(moduleName, "-", "") + prefix = strings.TrimSuffix(prefix, "apis") + prefix = strings.TrimSuffix(prefix, "api") + if prefix == "" || prefix == base { + prefix = strings.ReplaceAll(moduleName, "-", "") + } + + alias := prefix + base + g.importAliases[alias] = pkgPath + return alias } type Struct struct { @@ -191,6 +228,7 @@ func (b *APIsBuilder) ParseAPIs() { Versions: map[string]*APIVersion{}, UnversionedResources: map[string]*APIResource{}, Aliases: map[string]*Alias{}, + importAliases: map[string]string{}, } for version, kindMap := range versionMap { @@ -639,11 +677,7 @@ func (apigroup *APIGroup) DoType(t *types.Type) (*Struct, []*types.Type) { if strings.HasPrefix(mSubType.Name.Package, "k8s.io/api/") { // Import the package under an alias so it doesn't conflict with other groups // having the same version - importAlias := path.Base( - path.Dir(mSubType.Name.Package), - ) + path.Base( - mSubType.Name.Package, - ) + importAlias := apigroup.resolveImportAlias(mSubType.Name.Package) uImport = fmt.Sprintf("%s \"%s\"", importAlias, mSubType.Name.Package) if hasElem { // Replace the full package with the alias when referring to the type @@ -683,42 +717,22 @@ func (apigroup *APIGroup) DoType(t *types.Type) (*Struct, []*types.Type) { name := str[endPkg+1:] prefix := str[:startPkg+1] - uImportBase := path.Base(pkg) - uImportName := path.Base(path.Dir(pkg)) + uImportBase + uImportName := apigroup.resolveImportAlias(pkg) uImport = fmt.Sprintf("%s \"%s\"", uImportName, pkg) uType = prefix + uImportName + "." + name - - // fmt.Printf("\nDifferent Parent Package: %s\nChild Package: %s\nKind: %s (Kind.String() %s)\nImport stmt: %s\nType: %s\n\n", - // pkg, - // member.Type.Name.Package, - // member.Type.Kind, - // member.Type.String(), - // uImport, - // uType) } else { // Handle non- Pointer, Maps, Slices pkg := t.Name.Package name := t.Name.Name - // Come up with the alias the package is imported under - // Concatenate with directory package to reduce naming collisions - uImportBase := path.Base(pkg) - uImportName := path.Base(path.Dir(pkg)) + uImportBase + uImportName := apigroup.resolveImportAlias(pkg) // Create the import statement uImport = fmt.Sprintf("%s \"%s\"", uImportName, pkg) // Create the field type name - should be . uType = uImportName + "." + name - - // fmt.Printf("\nDifferent Parent Package: %s\nChild Package: %s\nKind: %s (Kind.String() %s)\nImport stmt: %s\nType: %s\n\n", - // pkg, - // member.Type.Name.Package, - // member.Type.Kind, - // member.Type.String(), - // uImport, - // uType) } } } diff --git a/pkg/generate/unversioned_generator.go b/pkg/generate/unversioned_generator.go index 4a776ad9..e1540c82 100644 --- a/pkg/generate/unversioned_generator.go +++ b/pkg/generate/unversioned_generator.go @@ -60,10 +60,11 @@ var UnversionedAPIImports = []string{ "k8s.io/apiserver/pkg/registry/generic", "k8s.io/apiserver/pkg/registry/rest", "github.com/devsy-org/apiserver/pkg/builders", + "github.com/devsy-org/apiserver/pkg/managerfactory", } var UnversionedAPITemplate = ` -type NewRESTFunc func() rest.Storage +type NewRESTFunc func(factory managerfactory.SharedManagerFactory) rest.Storage var ( {{ range $api := .UnversionedResources -}} @@ -75,12 +76,12 @@ var ( New{{ $api.REST }}, ) New{{ $api.REST }} = func(getter generic.RESTOptionsGetter) rest.Storage { - return New{{ $api.REST }}Func() + return New{{ $api.REST }}Func(Factory) } New{{ $api.REST }}Func NewRESTFunc {{ if $api.StatusREST -}} New{{ $api.StatusREST }} = func(getter generic.RESTOptionsGetter) rest.Storage { - return New{{ $api.StatusREST }}Func() + return New{{ $api.StatusREST }}Func(Factory) } New{{ $api.StatusREST }}Func NewRESTFunc {{ end -}} From bcb5961453baffff0c9e58f0af1f75f00ab89c7f Mon Sep 17 00:00:00 2001 From: Samuel K Date: Sat, 18 Apr 2026 14:30:01 -0500 Subject: [PATCH 3/3] fix: move resolveImportAlias after DoType and remove free-disk-space CI step Place unexported resolveImportAlias method after the exported DoType method to satisfy funcorder linter. Remove unnecessary jlumbroso/free-disk-space step from lint workflow. --- .github/workflows/lint.yml | 2 -- pkg/generate/parse.go | 68 +++++++++++++++++++------------------- 2 files changed, 34 insertions(+), 36 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c21cbc12..c3900e01 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -11,8 +11,6 @@ jobs: name: Lint runs-on: ubuntu-latest steps: - - uses: jlumbroso/free-disk-space@v1.3.1 - - uses: actions/checkout@v6 - name: setup Go diff --git a/pkg/generate/parse.go b/pkg/generate/parse.go index 5b5fb9ef..76659f12 100644 --- a/pkg/generate/parse.go +++ b/pkg/generate/parse.go @@ -47,40 +47,6 @@ type APIGroup struct { importAliases map[string]string } -// resolveImportAlias returns a unique import alias for the given package path. -// The base alias is formed from the last two path segments (e.g. "storage/v1" → "storagev1"). -// If that alias is already used by a different package, the module name (third path segment) -// is prepended to disambiguate (e.g. "agentstoragev1"). -func (g *APIGroup) resolveImportAlias(pkgPath string) string { - base := path.Base(path.Dir(pkgPath)) + path.Base(pkgPath) - - if existing, ok := g.importAliases[base]; ok && existing == pkgPath { - return base - } - - if _, ok := g.importAliases[base]; !ok { - g.importAliases[base] = pkgPath - return base - } - - // Collision: disambiguate using the module name (third segment of the import path). - parts := strings.Split(pkgPath, "/") - moduleName := "" - if len(parts) >= 3 { - moduleName = parts[2] - } - prefix := strings.ReplaceAll(moduleName, "-", "") - prefix = strings.TrimSuffix(prefix, "apis") - prefix = strings.TrimSuffix(prefix, "api") - if prefix == "" || prefix == base { - prefix = strings.ReplaceAll(moduleName, "-", "") - } - - alias := prefix + base - g.importAliases[alias] = pkgPath - return alias -} - type Struct struct { // Name is the name of the type Name string @@ -772,3 +738,37 @@ func (apigroup *APIGroup) DoType(t *types.Type) (*Struct, []*types.Type) { } return s, remaining } + +// resolveImportAlias returns a unique import alias for the given package path. +// The base alias is formed from the last two path segments (e.g. "storage/v1" → "storagev1"). +// If that alias is already used by a different package, the module name (third path segment) +// is prepended to disambiguate (e.g. "agentstoragev1"). +func (g *APIGroup) resolveImportAlias(pkgPath string) string { + base := path.Base(path.Dir(pkgPath)) + path.Base(pkgPath) + + if existing, ok := g.importAliases[base]; ok && existing == pkgPath { + return base + } + + if _, ok := g.importAliases[base]; !ok { + g.importAliases[base] = pkgPath + return base + } + + // Collision: disambiguate using the module name (third segment of the import path). + parts := strings.Split(pkgPath, "/") + moduleName := "" + if len(parts) >= 3 { + moduleName = parts[2] + } + prefix := strings.ReplaceAll(moduleName, "-", "") + prefix = strings.TrimSuffix(prefix, "apis") + prefix = strings.TrimSuffix(prefix, "api") + if prefix == "" || prefix == base { + prefix = strings.ReplaceAll(moduleName, "-", "") + } + + alias := prefix + base + g.importAliases[alias] = pkgPath + return alias +}