Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lint: version stream #1062

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 88 additions & 0 deletions pkg/lint/rules.go
Original file line number Diff line number Diff line change
Expand Up @@ -468,6 +468,94 @@ var AllRules = func(l *Linter) Rules { //nolint:gocyclo
return err
},
},
{
Name: "valid-version-stream",
Description: "check the provides and tag filter if version stream suffix is passed to package name",
Severity: SeverityWarning,
LintFunc: func(c config.Configuration) error {
// This regex captures a string that ends with a semantic version (semver) suffix.
// It returns two groups:
// - Group 1: The prefix part of the string before the semver.
// - Group 2: The semver (major.minor or major.minor.patch).
// If there is no semver suffix, the string will not match.
re := regexp.MustCompile(`^(.*?)-(\d+\.\d+(?:\.\d+)?)$`)

// It means that the package is not a version streamed, so early return.
if !re.MatchString(c.Package.Name) {
return nil
}

matches := re.FindStringSubmatch(c.Package.Name)
if len(matches) != 3 {
return fmt.Errorf("invalid package name %s for version stream, regex matches %+v", c.Package.Name, matches)
}

packageName := matches[1]
versionStream := matches[2]

if !strings.HasPrefix(c.Package.Version, versionStream) {
return fmt.Errorf("package is version streamed but package.version %s starts with different than given version stream %s", c.Package.Version, versionStream)
}

var providesList []string
addToProvidesList := func(key string) {
providesList = append(providesList, fmt.Sprintf("%s=%s-r%d", key, c.Package.Version, c.Package.Epoch))
providesList = append(providesList, fmt.Sprintf("%s=%s-r%d", key, versionStream, c.Package.Epoch))
providesList = append(providesList, fmt.Sprintf("%s=%s", key, c.Package.Version))
providesList = append(providesList, fmt.Sprintf("%s=%s", key, versionStream))
providesList = append(providesList, fmt.Sprintf("%s=%s.999", key, versionStream))
}
addToProvidesList(packageName)

// Some packages have different provides for package name, i.e. python-3 instead of python.
if majorMinor := strings.Split(versionStream, "."); len(majorMinor) > 1 {
addToProvidesList(fmt.Sprintf("%s-%s", packageName, majorMinor[0]))
}

anyMatch := false
for _, provides := range providesList {
if slices.Contains(c.Package.Dependencies.Provides, provides) {
anyMatch = true
break
}
}

if !anyMatch {
return fmt.Errorf("package is version streamed but %s=${{package.full-version}} is missing on dependencies.provides", packageName)
}

// Any subpackage that contains the package name, should follow `${{package.name}}-xyz` format.
for _, s := range c.Subpackages {
if strings.Contains(s.Name, packageName) {
if !strings.HasPrefix(s.Name, c.Package.Name) {
return fmt.Errorf("subpackage %s should be in format ${{package.name}}-XYZ-SUBPACKAGENAME for a valid version stream", s.Name)
}
}
}

if c.Update.Enabled && !c.Update.Manual && c.Update.GitHubMonitor != nil {
prefixesToCheck := []string{"", "v", packageName, "release", strings.ReplaceAll(packageName, "-fips", ""), c.Update.GitHubMonitor.StripPrefix}
separators := []string{"", ".", "-", "_"}
versionsToCheck := []string{versionStream, strings.ReplaceAll(versionStream, ".", "-"), strings.ReplaceAll(versionStream, ".", "_")}

var filtersToCheck []string
for _, prefix := range prefixesToCheck {
for _, separator := range separators {
for _, version := range versionsToCheck {
for _, suffix := range separators {
filtersToCheck = append(filtersToCheck, prefix+separator+version+suffix)
}
}
}
}

if !slices.Contains(filtersToCheck, c.Update.GitHubMonitor.TagFilter) && !slices.Contains(filtersToCheck, c.Update.GitHubMonitor.TagFilterPrefix) {
return fmt.Errorf("package is version streamed but tag filter %s is mismatch on update.github", versionStream)
}
}
return nil
},
},
}
}

Expand Down
90 changes: 90 additions & 0 deletions pkg/lint/rules_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,78 @@ func TestLinter_Rules(t *testing.T) {
wantErr: false,
matches: 1,
},
{
file: "version-stream-missing-provides-1.2.yaml",
minSeverity: SeverityWarning,
want: EvalResult{
File: "version-stream-missing-provides-1.2",
Errors: EvalRuleErrors{
{
Rule: Rule{
Name: "valid-version-stream",
Severity: SeverityWarning,
},
Error: fmt.Errorf("[valid-version-stream]: package is version streamed but version-stream-missing-provides=${{package.full-version}} is missing on dependencies.provides (WARNING)"),
},
},
},
wantErr: false,
matches: 1,
},
{
file: "version-stream-missing-update-tagfilter-1.2.yaml",
minSeverity: SeverityWarning,
want: EvalResult{
File: "version-stream-missing-update-tagfilter-1.2",
Errors: EvalRuleErrors{
{
Rule: Rule{
Name: "valid-version-stream",
Severity: SeverityWarning,
},
Error: fmt.Errorf("[valid-version-stream]: package is version streamed but tag filter 1.2 is mismatch on update.github (WARNING)"),
},
},
},
wantErr: false,
matches: 1,
},
{
file: "version-stream-missing-update-tagfilter-1.2-999.yaml",
minSeverity: SeverityWarning,
want: EvalResult{
File: "version-stream-missing-update-tagfilter-1.2",
Errors: EvalRuleErrors{
{
Rule: Rule{
Name: "valid-version-stream",
Severity: SeverityWarning,
},
Error: fmt.Errorf("[valid-version-stream]: package is version streamed but tag filter 1.2 is mismatch on update.github (WARNING)"),
},
},
},
wantErr: false,
matches: 1,
},
{
file: "version-stream-wrong-subpackage-naming-1.2.yaml",
minSeverity: SeverityWarning,
want: EvalResult{
File: "version-stream-wrong-subpackage-naming-1.2",
Errors: EvalRuleErrors{
{
Rule: Rule{
Name: "valid-version-stream",
Severity: SeverityWarning,
},
Error: fmt.Errorf("[valid-version-stream]: package is version streamed but version-stream-wrong-subpackage-naming=${{package.full-version}} is missing on dependencies.provides (WARNING)"),
},
},
},
wantErr: false,
matches: 1,
},
{
file: "valid-update-schedule.yaml",
minSeverity: SeverityWarning,
Expand All @@ -433,6 +505,24 @@ func TestLinter_Rules(t *testing.T) {
wantErr: false,
matches: 1,
},
{
file: "version-stream-mismatch-version-1.2.yaml",
minSeverity: SeverityWarning,
want: EvalResult{
File: "version-stream-mismatch-version-1.2",
Errors: EvalRuleErrors{
{
Rule: Rule{
Name: "valid-version-stream",
Severity: SeverityWarning,
},
Error: fmt.Errorf("[valid-version-stream]: package is version streamed but package.version 1.7 starts with different than given version stream 1.2 (WARNING)"),
},
},
},
wantErr: false,
matches: 1,
},
}

for _, tt := range tests {
Expand Down
18 changes: 18 additions & 0 deletions pkg/lint/testdata/files/version-stream-mismatch-version-1.2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package:
name: version-stream-mismatch-version-1.2
version: 1.7 # Supposed to be 1.2.*
epoch: 0
description: "a version-streamed package with no dependencies.provides"

pipeline:
- uses: fetch
with:
uri: https://test.com/version-stream-mismatch-version/${{package.version}}.tar.gz
expected-sha256: ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269

test:
pipeline:
- runs: "echo 'test'"

update:
enabled: true
18 changes: 18 additions & 0 deletions pkg/lint/testdata/files/version-stream-missing-provides-1.2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package:
name: version-stream-missing-provides-1.2
version: 1.2.3
epoch: 0
description: "a version-streamed package with no dependencies.provides"

pipeline:
- uses: fetch
with:
uri: https://test.com/version-stream-missing-provides/${{package.version}}.tar.gz
expected-sha256: ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269

test:
pipeline:
- runs: "echo 'test'"

update:
enabled: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package:
name: version-stream-missing-update-tagfilter-1.2
version: 1.2.3
epoch: 0
description: "a version-streamed package with no dependencies.provides"
dependencies:
provides:
- version-stream-missing-update-tagfilter=1.2.999

pipeline:
- uses: fetch
with:
uri: https://test.com/version-stream-missing-update-tagfilter/${{package.version}}.tar.gz
expected-sha256: ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269

test:
pipeline:
- runs: "echo 'test'"

update:
enabled: true
github:
identifier: test/version-stream-missing-update-tagfilter
use-tag: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package:
name: version-stream-missing-update-tagfilter-1.2
version: 1.2.3
epoch: 0
description: "a version-streamed package with no dependencies.provides"
dependencies:
provides:
- version-stream-missing-update-tagfilter=${{package.full-version}}

pipeline:
- uses: fetch
with:
uri: https://test.com/version-stream-missing-update-tagfilter/${{package.version}}.tar.gz
expected-sha256: ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269

test:
pipeline:
- runs: "echo 'test'"

update:
enabled: true
github:
identifier: test/version-stream-missing-update-tagfilter
use-tag: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package:
name: version-stream-wrong-subpackage-naming-1.2
version: 1.2.3
epoch: 0
description: "a version-streamed package with no dependencies.provides"

pipeline:
- uses: fetch
with:
uri: https://test.com/version-stream-missing-provides/${{package.version}}.tar.gz
expected-sha256: ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269

subpackages:
- name: this-is-subpackage-of-version-stream-wrong-subpackage-naming-1.2
description: "a package with incorrect subpackage prefix"
pipeline:
- runs: exit 0
- name: subpackage-of-version-stream-wrong-subpackage-naming-foo-bar-baz-1.2
description: "a package with incorrect subpackage prefix"
pipeline:
- runs: exit 0

test:
pipeline:
- runs: "echo 'test'"

update:
enabled: true