Skip to content

Commit 1e38ebc

Browse files
authored
feat: narrow the special handling of github to just latest version (#182)
1 parent 2e306e6 commit 1e38ebc

17 files changed

+568
-491
lines changed

internal/generator/factory.go

Lines changed: 37 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,10 @@ import (
88
"regexp"
99
"runtime"
1010
"slices"
11-
"sort"
12-
"strconv"
13-
"strings"
1411

1512
"github.com/CustomResourceDefinition/catalog/internal/configuration"
1613
"github.com/CustomResourceDefinition/catalog/internal/crd"
1714
"github.com/CustomResourceDefinition/catalog/internal/registry"
18-
"github.com/CustomResourceDefinition/catalog/internal/semver"
1915
)
2016

2117
type Builder struct {
@@ -25,34 +21,24 @@ type Builder struct {
2521
logger io.Writer
2622
config configuration.Configuration
2723
generator Generator
28-
versionFilter *regexp.Regexp
2924
registry *registry.SourceRegistry
3025
}
3126

32-
func NewBuilder(config configuration.Configuration, reader crd.CrdReader, generatedRepository, schemaRepository, definitionRepository string, logger io.Writer, reg *registry.SourceRegistry) (*Builder, error) {
27+
func NewBuilder(
28+
config configuration.Configuration,
29+
reader crd.CrdReader,
30+
generatedRepository, schemaRepository, definitionRepository string,
31+
logger io.Writer,
32+
reg *registry.SourceRegistry,
33+
) (*Builder, error) {
3334
generator, err := resolveGenerator(config, reader, logger)
3435
if err != nil {
3536
return nil, err
3637
}
3738

38-
if len(config.Namespace) == 0 {
39-
config.Namespace = "namespace"
40-
}
41-
42-
pattern := defaultVersionPattern(config.Kind)
43-
if len(config.VersionPattern) > 0 {
44-
pattern = config.VersionPattern
45-
}
46-
47-
re, err := regexp.Compile(pattern)
48-
if err != nil {
49-
return nil, err
50-
}
51-
5239
return &Builder{
5340
config: config,
5441
generator: generator,
55-
versionFilter: re,
5642
logger: logger,
5743
schemaRepository: schemaRepository,
5844
generatedRepository: generatedRepository,
@@ -78,13 +64,20 @@ func (builder Builder) Build() error {
7864
fmt.Fprintf(logger, "Producing for %s@%s:\n", builder.config.Name, builder.config.Kind)
7965
defer fmt.Fprintf(logger, "End.\n")
8066

81-
latestVersion, isUpdated := builder.registryStatus()
67+
if _, ok := builder.generator.(*PreparedGitGenerator); ok {
68+
fmt.Fprintf(logger, " - using prepared git generator\n")
69+
}
70+
71+
latestVersion, isUpdated, err := builder.registryStatus()
72+
if err != nil {
73+
return err
74+
}
8275
if isUpdated {
8376
fmt.Fprintf(logger, " - skipping %s@%s (version %s unchanged)\n", builder.config.Name, builder.config.Kind, latestVersion)
8477
return nil
8578
}
8679

87-
versions, err := builder.versions()
80+
versions, err := builder.generator.Versions()
8881
if err != nil {
8982
return err
9083
}
@@ -157,51 +150,23 @@ func (builder Builder) Build() error {
157150
return nil
158151
}
159152

160-
func (builder Builder) versions() ([]string, error) {
161-
versions, err := builder.generator.Versions()
153+
// registryStatus reports on the state in registry based on the latest version
154+
// available and only uses the decided interface method for latest version information
155+
func (builder Builder) registryStatus() (string, bool, error) {
156+
version, err := builder.generator.LatestVersion()
162157
if err != nil {
163-
return nil, err
158+
return "", false, fmt.Errorf("unable to check registry: %w", err)
164159
}
165160

166-
filtered := make([]string, 0)
167-
for _, v := range versions {
168-
if builder.versionFilter.MatchString(v) {
169-
filtered = append(filtered, v)
170-
}
171-
}
172-
173-
sort.Slice(filtered, func(i, j int) bool {
174-
keyA, errA := builder.generator.VersionSortKey(filtered[i])
175-
keyB, errB := builder.generator.VersionSortKey(filtered[j])
176-
177-
if errA == nil && errB == nil && keyA != 0 && keyB != 0 && keyA != keyB {
178-
return keyA > keyB
179-
}
180-
181-
a := normalizeVersion(builder.versionFilter.FindAllStringSubmatch(filtered[i], -1))
182-
b := normalizeVersion(builder.versionFilter.FindAllStringSubmatch(filtered[j], -1))
183-
return semver.Compare(a, b) > 0
184-
})
185-
return filtered, nil
186-
}
187-
188-
func (builder Builder) registryStatus() (string, bool) {
189-
versions, err := builder.versions()
190-
if err != nil || len(versions) == 0 {
191-
return "", false
192-
}
193-
194-
version := versions[0]
195-
196161
if builder.registry == nil {
197-
return version, false
162+
return version, false, nil
198163
}
199164

200165
if entry, ok := builder.registry.Get(builder.config.Name); ok {
201-
return version, entry.Kind == string(builder.config.Kind) && entry.Version == version
166+
return version, entry.Kind == string(builder.config.Kind) && entry.Version == version, nil
202167
}
203168

204-
return version, false
169+
return version, false, nil
205170
}
206171

207172
func (builder Builder) updateRegistry(version string) {
@@ -212,37 +177,31 @@ func (builder Builder) updateRegistry(version string) {
212177
builder.registry.Set(builder.config.Name, string(builder.config.Kind), version)
213178
}
214179

215-
func normalizeVersion(matches [][]string) string {
216-
if len(matches) == 0 || len(matches[0]) < 2 {
217-
return "v0.0.0"
180+
func resolveGenerator(config configuration.Configuration, reader crd.CrdReader, logger io.Writer) (Generator, error) {
181+
if len(config.Namespace) == 0 {
182+
config.Namespace = "namespace"
218183
}
219184

220-
version := matches[0][1]
221-
parts := strings.Split(version, ".")
222-
if len(parts) < 3 {
223-
return "v0.0.0"
185+
pattern := defaultVersionPattern(config.Kind)
186+
if len(config.VersionPattern) > 0 {
187+
pattern = config.VersionPattern
224188
}
225189

226-
ints := make([]int, 3)
227-
for i := range 3 {
228-
n, _ := strconv.Atoi(parts[i])
229-
ints[i] = n
190+
filter, err := regexp.Compile(pattern)
191+
if err != nil {
192+
return nil, err
230193
}
231194

232-
return fmt.Sprintf("v%d.%d.%d", ints[0], ints[1], ints[2])
233-
}
234-
235-
func resolveGenerator(config configuration.Configuration, reader crd.CrdReader, logger io.Writer) (Generator, error) {
236195
switch config.Kind {
237196
case configuration.Git:
238-
return NewGitGeneratorFactory(config, reader, logger).Build()
197+
return NewGitGeneratorFactory(config, reader, filter, logger).Build()
239198
case configuration.Http:
240-
return NewHttpGenerator(config, reader), nil
199+
return NewHttpGenerator(config, reader, filter), nil
241200
case configuration.Helm:
242201
target := config.Entries[len(config.Entries)-1]
243-
return NewHelmGenerator(target, config, reader), nil
202+
return NewHelmGenerator(target, config, reader, filter), nil
244203
case configuration.HelmOci:
245-
return NewOciGenerator(config, reader), nil
204+
return NewOciGenerator(config, reader, filter), nil
246205
default:
247206
return nil, fmt.Errorf("no generators matched for kind '%s'", config.Kind)
248207
}

internal/generator/factory_test.go

Lines changed: 33 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package generator
22

33
import (
4-
"fmt"
54
"net/http"
65
"net/http/httptest"
76
"os"
@@ -14,107 +13,37 @@ import (
1413
"github.com/stretchr/testify/assert"
1514
)
1615

17-
func TestBuilderVersionSorting(t *testing.T) {
18-
seedVersions := []string{
19-
"2.10.0", "1.0.0", "2.2.0", "2.1.0", "1.01.01",
20-
}
21-
bundles := make([]gitBundle, 0)
22-
for _, v := range seedVersions {
23-
bundles = append(bundles, gitBundle{tag: v, paths: []gitPath{}})
16+
func TestBuildWithVersionPatternFiltering(t *testing.T) {
17+
config := configuration.Configuration{
18+
Kind: configuration.Http,
19+
Name: "test",
20+
ApiGroups: []string{"chart.uri"},
21+
VersionPattern: `^v([0-9]+\.[0-9]+\.[0-9]+)$`,
22+
Downloads: []configuration.ConfigurationDownload{
23+
{
24+
Version: "v1.0.0",
25+
},
26+
{
27+
Version: "v2.0.0",
28+
},
29+
{
30+
Version: "3.0.0",
31+
},
32+
},
2433
}
25-
expectedVersions := []string{seedVersions[0], seedVersions[2], seedVersions[3], seedVersions[4], seedVersions[1]}
2634

27-
p, err := setupGit(t, bundles)
35+
reader, err := crd.NewCrdReader(setupLogger())
2836
assert.Nil(t, err)
29-
assert.NotNil(t, p)
3037

31-
config := configuration.Configuration{
32-
Kind: configuration.Git,
33-
Repository: fmt.Sprintf("file://%s", *p),
34-
VersionPattern: `^([0-9]+\.[0-9]+\.[0-9]+)$`,
35-
}
38+
tmpDir := t.TempDir()
3639

37-
b, err := NewBuilder(config, nil, "-", "-", "-", nil, nil)
40+
builder, err := NewBuilder(config, reader, tmpDir, tmpDir, tmpDir, setupLogger(), nil)
3841
assert.Nil(t, err)
3942

40-
versions, err := b.versions()
43+
version, result, err := builder.registryStatus()
4144
assert.Nil(t, err)
42-
assert.NotNil(t, versions)
43-
assert.Equal(t, expectedVersions, versions)
44-
}
45-
46-
type testScenario struct {
47-
versions []string
48-
expectedVersions []string
49-
pattern string
50-
}
51-
52-
func TestBuilderVersionFiltering(t *testing.T) {
53-
tests := []testScenario{
54-
{
55-
versions: []string{"2.0.0", "1.3.0", "1.0.0"},
56-
expectedVersions: []string{"2.0.0", "1.3.0", "1.0.0"},
57-
},
58-
{
59-
versions: []string{"v2.0.0", "v1.3.0", "v1.0.0"},
60-
expectedVersions: []string{},
61-
},
62-
{
63-
versions: []string{"v2.0.0", "v1.3.0", "v1.0.0"},
64-
expectedVersions: []string{"v2.0.0", "v1.3.0", "v1.0.0"},
65-
pattern: `^v([0-9]+\.[0-9]+\.[0-9]+)$`,
66-
},
67-
{
68-
versions: []string{"2.0.0", "v1.3.0", "v1.0.0"},
69-
expectedVersions: []string{"2.0.0", "v1.3.0", "v1.0.0"},
70-
pattern: `^v?([0-9]+\.[0-9]+\.[0-9]+)$`,
71-
},
72-
{
73-
versions: []string{"2.0.0", "v1.3.0v", "v1.0.0"},
74-
expectedVersions: []string{"2.0.0", "v1.0.0"},
75-
pattern: `^v?([0-9]+\.[0-9]+\.[0-9]+)$`,
76-
},
77-
{
78-
versions: []string{"2.0.0-2", "1.3.0-1892", "1.0.0-01"},
79-
expectedVersions: []string{"2.0.0-2", "1.3.0-1892", "1.0.0-01"},
80-
pattern: `^([0-9]+\.[0-9]+\.[0-9]+-\d+)$`,
81-
},
82-
{
83-
versions: []string{"v1.33.2+k0s.0"},
84-
expectedVersions: []string{"v1.33.2+k0s.0"},
85-
pattern: `^v([0-9]+\.[0-9]+\.[0-9]+\+k0s\.0)$`,
86-
},
87-
{
88-
versions: []string{"main", "v1.0", "master"},
89-
expectedVersions: []string{"main", "master"},
90-
pattern: `^(main|master)$`,
91-
},
92-
{
93-
versions: []string{"main", "v1.0.0", "2.0.0", "master"},
94-
expectedVersions: []string{"2.0.0", "main", "master"},
95-
pattern: `^([0-9]+\.[0-9]+\.[0-9]+)|(main|master)$`,
96-
},
97-
}
98-
99-
for i, test := range tests {
100-
downloads := make([]configuration.ConfigurationDownload, 0)
101-
for _, v := range test.versions {
102-
downloads = append(downloads, configuration.ConfigurationDownload{Version: v})
103-
}
104-
config := configuration.Configuration{
105-
Kind: configuration.Http,
106-
Downloads: downloads,
107-
VersionPattern: test.pattern,
108-
}
109-
110-
b, err := NewBuilder(config, nil, "-", "-", "-", nil, nil)
111-
assert.Nil(t, err)
112-
113-
versions, err := b.versions()
114-
assert.Nil(t, err, "index %d failed", i)
115-
assert.NotNil(t, versions, "index %d failed", i)
116-
assert.Equal(t, test.expectedVersions, versions, "index %d failed", i)
117-
}
45+
assert.False(t, result)
46+
assert.Equal(t, "v2.0.0", version)
11847
}
11948

12049
func TestResolveGenerator(t *testing.T) {
@@ -241,11 +170,12 @@ func TestRegistryStatusNoRegistry(t *testing.T) {
241170
Downloads: []configuration.ConfigurationDownload{{Version: "1.0.0"}},
242171
}
243172

244-
b, err := NewBuilder(config, nil, "-", "-", "-", nil, nil)
173+
builder, err := NewBuilder(config, nil, "-", "-", "-", nil, nil)
245174
assert.Nil(t, err)
246-
assert.NotNil(t, b)
175+
assert.NotNil(t, builder)
247176

248-
version, result := b.registryStatus()
177+
version, result, err := builder.registryStatus()
178+
assert.Nil(t, err)
249179
assert.False(t, result)
250180
assert.Equal(t, "1.0.0", version)
251181
}
@@ -283,7 +213,8 @@ func TestRegistryStatusSameVersion(t *testing.T) {
283213
builder, err := NewBuilder(config, reader, tmpDir, tmpDir, tmpDir, setupLogger(), reg)
284214
assert.Nil(t, err)
285215

286-
version, result := builder.registryStatus()
216+
version, result, err := builder.registryStatus()
217+
assert.Nil(t, err)
287218
assert.True(t, result)
288219
assert.Equal(t, "1.0.0", version)
289220
}
@@ -321,7 +252,8 @@ func TestRegistryStatusDifferentVersion(t *testing.T) {
321252
builder, err := NewBuilder(config, reader, tmpDir, tmpDir, tmpDir, setupLogger(), reg)
322253
assert.Nil(t, err)
323254

324-
version, result := builder.registryStatus()
255+
version, result, err := builder.registryStatus()
256+
assert.Nil(t, err)
325257
assert.False(t, result)
326258
assert.Equal(t, "2.0.0", version)
327259
}
@@ -359,7 +291,8 @@ func TestRegistryStatusDifferentKind(t *testing.T) {
359291
builder, err := NewBuilder(config, reader, tmpDir, tmpDir, tmpDir, setupLogger(), reg)
360292
assert.Nil(t, err)
361293

362-
version, result := builder.registryStatus()
294+
version, result, err := builder.registryStatus()
295+
assert.Nil(t, err)
363296
assert.False(t, result)
364297
assert.Equal(t, "1.0.0", version)
365298
}

internal/generator/generator.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import (
88

99
type Generator interface {
1010
Versions() ([]string, error)
11+
LatestVersion() (string, error)
1112
MetaData(version string) ([]crd.CrdMetaSchema, error)
1213
Crds(version string) ([]crd.Crd, error)
13-
VersionSortKey(version string) (int64, error)
1414
io.Closer
1515
}

0 commit comments

Comments
 (0)