diff --git a/DEPENDENCIES b/DEPENDENCIES index 1ffd919..b558515 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -5,6 +5,7 @@ go/golang/github.com%2Fcpuguy83%2Fgo-md2man/v2/v2.0.2, MIT, approved, clearlydef go/golang/github.com%2Fcreack/pty/v1.1.9, MIT, approved, clearlydefined go/golang/github.com%2Fdavecgh/go-spew/v1.1.0, ISC, approved, clearlydefined go/golang/github.com%2Fdavecgh/go-spew/v1.1.1, ISC, approved, clearlydefined +go/golang/github.com%2Ffatih/color/v1.15.0, MIT, approved, #9689 go/golang/github.com%2Fgo-ini/ini/v1.67.0, Apache-2.0, approved, clearlydefined go/golang/github.com%2Fgolang/protobuf/v1.3.1, BSD-3-Clause, approved, clearlydefined go/golang/github.com%2Fgolang/protobuf/v1.5.0, BSD-3-Clause, approved, #5706 @@ -19,6 +20,9 @@ go/golang/github.com%2Fkr/pretty/v0.2.1, MIT, approved, clearlydefined go/golang/github.com%2Fkr/pty/v1.1.1, MIT, approved, clearlydefined go/golang/github.com%2Fkr/text/v0.1.0, MIT, approved, clearlydefined go/golang/github.com%2Fkr/text/v0.2.0, MIT, approved, clearlydefined +go/golang/github.com%2Fmattn/go-colorable/v0.1.13, MIT, approved, clearlydefined +go/golang/github.com%2Fmattn/go-isatty/v0.0.16, MIT, approved, clearlydefined +go/golang/github.com%2Fmattn/go-isatty/v0.0.17, MIT, approved, clearlydefined go/golang/github.com%2Fpmezard/go-difflib/v1.0.0, BSD-3-Clause, approved, clearlydefined go/golang/github.com%2Frussross%2Fblackfriday/v2/v2.1.0, BSD-2-Clause, approved, clearlydefined go/golang/github.com%2Fspf13/cobra/v1.7.0, Apache-2.0, approved, clearlydefined @@ -50,6 +54,7 @@ go/golang/golang.org%2Fx/sys/v0.0.0-20201119102817-f84b799fce68, Apache-2.0 AND go/golang/golang.org%2Fx/sys/v0.0.0-20210615035016-665e8c7367d1, Apache-2.0 AND BSD-3-Clause AND BSD-3-Clause, approved, #3437 go/golang/golang.org%2Fx/sys/v0.0.0-20220520151302-bc2c85ada10a, Apache-2.0 AND BSD-3-Clause AND BSD-3-Clause, approved, #3437 go/golang/golang.org%2Fx/sys/v0.0.0-20220722155257-8c9f86f7a55f, Apache-2.0 AND BSD-3-Clause AND BSD-3-Clause, approved, #3437 +go/golang/golang.org%2Fx/sys/v0.0.0-20220811171246-fbc7d0a398ab, Apache-2.0 AND BSD-3-Clause AND BSD-3-Clause, approved, #3437 go/golang/golang.org%2Fx/sys/v0.10.0, BSD-3-Clause, approved, #9282 go/golang/golang.org%2Fx/sys/v0.2.0, BSD-3-Clause, approved, #6379 go/golang/golang.org%2Fx/sys/v0.3.0, BSD-3-Clause, approved, #9289 diff --git a/cmd/checkLocal.go b/cmd/checkLocal.go index c580e6f..6d280d5 100644 --- a/cmd/checkLocal.go +++ b/cmd/checkLocal.go @@ -24,22 +24,24 @@ import ( "os" txqualitychecks "github.com/eclipse-tractusx/tractusx-quality-checks/internal" - "github.com/eclipse-tractusx/tractusx-quality-checks/internal/docs" - "github.com/eclipse-tractusx/tractusx-quality-checks/internal/helm" - "github.com/eclipse-tractusx/tractusx-quality-checks/internal/repo" + irepo "github.com/eclipse-tractusx/tractusx-quality-checks/internal/repo" "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/container" + "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/docs" + "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/helm" + "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/repo" + "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/tractusx" "github.com/spf13/cobra" ) -var releaseGuidelines = []txqualitychecks.QualityGuideline{ - docs.NewReadmeExists(), - docs.NewInstallExists(), - docs.NewChangelogExists(), - repo.NewLeadingRepositoryDefined(), - repo.NewDefaultBranch(), +var releaseGuidelines = []tractusx.QualityGuideline{ + docs.NewReadmeExists("./"), + docs.NewInstallExists("./"), + docs.NewChangelogExists("./"), + repo.NewLeadingRepositoryDefined("./"), + irepo.NewDefaultBranch(), container.NewAllowedBaseImage("./"), - repo.NewRepoStructureExists(), - helm.NewHelmStructureExists(), + repo.NewRepoStructureExists("./"), + helm.NewHelmStructureExists("./"), } // checkLocalCmd represents the checkLocal command diff --git a/internal/docs/install_exists_test.go b/internal/docs/install_exists_test.go deleted file mode 100644 index 743a611..0000000 --- a/internal/docs/install_exists_test.go +++ /dev/null @@ -1,75 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2023 Contributors to the Eclipse Foundation - * - * See the NOTICE file(s) distributed with this work for additional - * information regarding copyright ownership. - * - * This program and the accompanying materials are made available under the - * terms of the Apache License, Version 2.0 which is available at - * https://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - * SPDX-License-Identifier: Apache-2.0 - ******************************************************************************/ - -package docs - -import ( - "os" - "testing" -) - -func TestNewInstallExists(t *testing.T) { - t.Run("Provide ErrorDescription on Fail", func(t *testing.T) { - installTest := NewInstallExists() - expectedError := "Optional file INSTALL.md not found in current directory." - - result := installTest.Test() - - if result.ErrorDescription != expectedError { - t.Errorf("Install.md check does not provide correct error description fon failing check!\n"+ - "expected: %s\ngot: %s", expectedError, result.ErrorDescription) - } - }) - t.Run("Pass if file exists", func(t *testing.T) { - installTest := NewInstallExists() - _, err := os.Create("INSTALL.md") - if err != nil { - t.Errorf("Error creating test preconditions!") - } - - result := installTest.Test() - - if !result.Passed { - t.Errorf("INSTALL exists, but test still fails") - } - - err = os.Remove("INSTALL.md") - if err != nil { - t.Errorf("Error while removing test preconditions!") - } - }) - t.Run("No ErrorDescription if test pass", func(t *testing.T) { - installTest := NewInstallExists() - _, err := os.Create("INSTALL.md") - if err != nil { - t.Errorf("Error creating test preconditions!") - } - - result := installTest.Test() - - if result.ErrorDescription != "" { - t.Errorf("Passing test should not contain an error description") - } - - err = os.Remove("INSTALL.md") - if err != nil { - t.Errorf("Error while removing test preconditions!") - } - }) -} diff --git a/pkg/filesystem/filesystem.go b/internal/filesystem/filesystem.go similarity index 91% rename from pkg/filesystem/filesystem.go rename to internal/filesystem/filesystem.go index d0fedfb..5ab99f9 100644 --- a/pkg/filesystem/filesystem.go +++ b/internal/filesystem/filesystem.go @@ -19,11 +19,16 @@ package filesystem -import "os" +import ( + "log" + "os" +) func CreateFiles(files []string) { for _, file := range files { - os.Create(file) + if _, err := os.Create(file); err != nil { + log.Fatalf("could not create file %s. Error %s", file, err) + } } } diff --git a/pkg/filesystem/filesystem_test.go b/internal/filesystem/filesystem_test.go similarity index 100% rename from pkg/filesystem/filesystem_test.go rename to internal/filesystem/filesystem_test.go diff --git a/internal/helm/chartyaml.go b/internal/helm/chartyaml.go index 667a8f1..659dbd0 100644 --- a/internal/helm/chartyaml.go +++ b/internal/helm/chartyaml.go @@ -21,13 +21,14 @@ package helm import ( "fmt" - "gopkg.in/yaml.v3" "io/ioutil" "reflect" "regexp" + + "gopkg.in/yaml.v3" ) -type chartyaml struct { +type Chartyaml struct { ApiVersion string `yaml:"apiVersion"` Name string `yaml:"name"` Description string `yaml:"description"` @@ -35,8 +36,8 @@ type chartyaml struct { Version string `yaml:"version"` } -func newChartYaml() *chartyaml { - return &chartyaml{ +func newChartYaml() *Chartyaml { + return &Chartyaml{ ApiVersion: "", Name: "", Description: "", @@ -45,14 +46,14 @@ func newChartYaml() *chartyaml { } } -func chartYamlFromFile(ymlfile string) *chartyaml { +func ChartYamlFromFile(ymlfile string) *Chartyaml { data, err := ioutil.ReadFile(ymlfile) if err != nil { fmt.Printf("Unable to read %v.\n", ymlfile) return nil } - var c chartyaml + var c Chartyaml err = yaml.Unmarshal(data, &c) if err != nil { fmt.Printf("Unable to parse YAML file: %v.\n", ymlfile) @@ -62,7 +63,7 @@ func chartYamlFromFile(ymlfile string) *chartyaml { return &c } -func (c *chartyaml) isVersionValid() bool { +func (c *Chartyaml) IsVersionValid() bool { /* Below regular expresion is used to verify version string according to Semantic Versioning schema (https://semver.org). Following examples match: @@ -83,12 +84,12 @@ func (c *chartyaml) isVersionValid() bool { return match } -func (c *chartyaml) getMissingMandatoryFields() []string { +func (c *Chartyaml) GetMissingMandatoryFields() []string { chartValues := reflect.ValueOf(*c) chartType := chartValues.Type() numChartFields := chartValues.NumField() - missingFields := []string{} + var missingFields []string for i := 0; i < numChartFields; i++ { chartField := chartType.Field(i) chartFieldValue := chartValues.Field(i) diff --git a/internal/helm/chartyaml_test.go b/internal/helm/chartyaml_test.go index 27c03f5..23c07f3 100644 --- a/internal/helm/chartyaml_test.go +++ b/internal/helm/chartyaml_test.go @@ -22,7 +22,7 @@ package helm import "testing" func TestShouldPassIfCanReadChartYaml(t *testing.T) { - c := chartYamlFromFile("test/TestChartValid.yaml") + c := ChartYamlFromFile("test/TestChartValid.yaml") if c.Name != "test-application" { t.Errorf("Test should pass but name of the helm chart is not 'test-application'.") } @@ -31,7 +31,7 @@ func TestShouldPassIfCanReadChartYaml(t *testing.T) { func TestShouldBeValidForSemanticVersion(t *testing.T) { c := newChartYaml() c.Version = "1.2.3" - if !c.isVersionValid() { + if !c.IsVersionValid() { t.Errorf("Test should pass since version is valid according Semantic Version schema.") } } @@ -39,14 +39,14 @@ func TestShouldBeValidForSemanticVersion(t *testing.T) { func TestShouldBeInValidForSemanticVersion(t *testing.T) { c := newChartYaml() c.Version = "1.2.ABC" - if c.isVersionValid() { + if c.IsVersionValid() { t.Errorf("Test should fail since version is invalid according to Semantic Version schema.") } } func TestShouldPassIfConfigurationSettingsArePresent(t *testing.T) { - c := chartYamlFromFile("test/TestChartValid.yaml") - missingFields := c.getMissingMandatoryFields() + c := ChartYamlFromFile("test/TestChartValid.yaml") + missingFields := c.GetMissingMandatoryFields() if len(missingFields) > 0 { t.Errorf("Test should pass since all configuration settings are set.") @@ -54,8 +54,8 @@ func TestShouldPassIfConfigurationSettingsArePresent(t *testing.T) { } func TestShouldFailIfConfigurationSettingsAreMissing(t *testing.T) { - c := chartYamlFromFile("test/TestChartInValid.yaml") - missingFields := c.getMissingMandatoryFields() + c := ChartYamlFromFile("test/TestChartInValid.yaml") + missingFields := c.GetMissingMandatoryFields() if len(missingFields) == 0 { t.Errorf("Test should fail since one configuration setting is missing.") diff --git a/internal/repo/default_branch.go b/internal/repo/default_branch.go index dd79323..3a21e55 100644 --- a/internal/repo/default_branch.go +++ b/internal/repo/default_branch.go @@ -20,14 +20,18 @@ package repo import ( - "github.com/eclipse-tractusx/tractusx-quality-checks/internal" + "context" + "fmt" + "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/repo" + "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/tractusx" + "github.com/google/go-github/v50/github" ) type defaultBranch struct { } -func NewDefaultBranch() txqualitychecks.QualityGuideline { +func NewDefaultBranch() tractusx.QualityGuideline { return &defaultBranch{} } @@ -43,25 +47,37 @@ func (d defaultBranch) ExternalDescription() string { return "https://eclipse-tractusx.github.io/docs/release/trg-2/trg-2-1" } -func (d defaultBranch) Test() *txqualitychecks.QualityResult { - repoInfo := repo.GetRepoMetadata(repo.GetRepoBaseInfo()) +func (d defaultBranch) Test() *tractusx.QualityResult { + repoInfo := getRepoInfo(repo.GetRepoBaseInfo()) if *repoInfo.Fork { // There is no need to enforce default branches on forks // Since all the other checks should be executable on forks, we cannot let this single check break a workflow - return &txqualitychecks.QualityResult{Passed: true} + return &tractusx.QualityResult{Passed: true} } if *repoInfo.DefaultBranch != "main" { - return &txqualitychecks.QualityResult{ + return &tractusx.QualityResult{ Passed: false, ErrorDescription: "Default branch not set to 'main'.", } } - return &txqualitychecks.QualityResult{Passed: true} + return &tractusx.QualityResult{Passed: true} } func (d defaultBranch) IsOptional() bool { return false } + +func getRepoInfo(repo *repo.RepoInfo) *github.Repository { + ctx := context.Background() + client := *github.NewClient(nil) + + repoInfo, _, err := client.Repositories.Get(ctx, repo.Owner, repo.Reponame) + if err != nil { + fmt.Printf("Error querying GitHub API:\n%v\n", err) + } + + return repoInfo +} diff --git a/internal/test_runner.go b/internal/test_runner.go index 0017a5a..14179a7 100644 --- a/internal/test_runner.go +++ b/internal/test_runner.go @@ -22,15 +22,17 @@ package txqualitychecks import ( "errors" "fmt" + + "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/tractusx" "github.com/fatih/color" ) type GuidelineTestRunner struct { - guidelines []QualityGuideline - printer Printer + guidelines []tractusx.QualityGuideline + printer tractusx.Printer } -func NewTestRunner(tests []QualityGuideline) *GuidelineTestRunner { +func NewTestRunner(tests []tractusx.QualityGuideline) *GuidelineTestRunner { return &GuidelineTestRunner{guidelines: tests, printer: &StdoutPrinter{}} } diff --git a/internal/test_runner_mock.go b/internal/test_runner_mock.go index 55ec3a4..7b99d24 100644 --- a/internal/test_runner_mock.go +++ b/internal/test_runner_mock.go @@ -19,7 +19,11 @@ package txqualitychecks -import "fmt" +import ( + "fmt" + + "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/tractusx" +) type Guideline struct { name string @@ -48,8 +52,8 @@ func (f FailingQualityGuideline) ExternalDescription() string { return f.externalDescription } -func (f FailingQualityGuideline) Test() *QualityResult { - return &QualityResult{Passed: false} +func (f FailingQualityGuideline) Test() *tractusx.QualityResult { + return &tractusx.QualityResult{Passed: false} } type PassingQualityGuideline struct { @@ -72,8 +76,8 @@ func (p PassingQualityGuideline) ExternalDescription() string { return p.externalDescription } -func (p PassingQualityGuideline) Test() *QualityResult { - return &QualityResult{Passed: true} +func (p PassingQualityGuideline) Test() *tractusx.QualityResult { + return &tractusx.QualityResult{Passed: true} } type PrinterMock struct { diff --git a/internal/test_runner_test.go b/internal/test_runner_test.go index 4284ae3..94fe9d5 100644 --- a/internal/test_runner_test.go +++ b/internal/test_runner_test.go @@ -23,10 +23,12 @@ import ( "fmt" "strings" "testing" + + "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/tractusx" ) func TestShouldPassIfNotTestsAreRun(t *testing.T) { - err := NewTestRunner([]QualityGuideline{}).Run() + err := NewTestRunner([]tractusx.QualityGuideline{}).Run() if err != nil { t.Errorf("Running no tests should succeed") @@ -34,7 +36,7 @@ func TestShouldPassIfNotTestsAreRun(t *testing.T) { } func TestShouldFailWhenRunningFailingQualityTage(t *testing.T) { - err := NewTestRunner([]QualityGuideline{&FailingQualityGuideline{}}).Run() + err := NewTestRunner([]tractusx.QualityGuideline{&FailingQualityGuideline{}}).Run() if err == nil { t.Errorf("Expected error if only a failing quality guideline is run") @@ -42,7 +44,7 @@ func TestShouldFailWhenRunningFailingQualityTage(t *testing.T) { } func TestShouldPassIfOnlyPassingQualityGuidelinesAreRun(t *testing.T) { - err := NewTestRunner([]QualityGuideline{&PassingQualityGuideline{}}).Run() + err := NewTestRunner([]tractusx.QualityGuideline{&PassingQualityGuideline{}}).Run() if err != nil { t.Errorf("Should not raise an error if only succeeding quality guidelines are run") @@ -50,7 +52,7 @@ func TestShouldPassIfOnlyPassingQualityGuidelinesAreRun(t *testing.T) { } func TestShouldFailIfAtLeastOneFailingTestIsRun(t *testing.T) { - runner := NewTestRunner([]QualityGuideline{ + runner := NewTestRunner([]tractusx.QualityGuideline{ &PassingQualityGuideline{}, &PassingQualityGuideline{}, &FailingQualityGuideline{}, @@ -65,7 +67,7 @@ func TestShouldFailIfAtLeastOneFailingTestIsRun(t *testing.T) { func TestShouldLogTheGuidelineNameWhenRunningTheTest(t *testing.T) { runner := NewTestRunner( - []QualityGuideline{&PassingQualityGuideline{Guideline{name: "TRG 1 - README test"}}}, + []tractusx.QualityGuideline{&PassingQualityGuideline{Guideline{name: "TRG 1 - README test"}}}, ) printerMock := &PrinterMock{} runner.printer = printerMock @@ -89,7 +91,7 @@ func TestShouldLogDescriptionOfGuidelineIfTheTestIsFailing(t *testing.T) { externalDescription: "https://en.wikipedia.org/wiki/Chuck_Norris", }, } - runner := NewTestRunner([]QualityGuideline{failingGuideline}) + runner := NewTestRunner([]tractusx.QualityGuideline{failingGuideline}) printerMock := &PrinterMock{} runner.printer = printerMock @@ -125,7 +127,7 @@ func TestShouldOnlyLogAdditionalDescriptionForFailingTests(t *testing.T) { externalDescription: "https://de.wikipedia.org/wiki//dev/null", }, } - runner := NewTestRunner([]QualityGuideline{failingGuideline, passingGuideline}) + runner := NewTestRunner([]tractusx.QualityGuideline{failingGuideline, passingGuideline}) printerMock := &PrinterMock{} runner.printer = printerMock @@ -155,7 +157,7 @@ func TestShouldNotFailIfOptionalTestFail(t *testing.T) { }, } - runner := NewTestRunner([]QualityGuideline{failingGuideline}) + runner := NewTestRunner([]tractusx.QualityGuideline{failingGuideline}) err := runner.Run() if err != nil { diff --git a/pkg/container/allowed_base_image_check.go b/pkg/container/allowed_base_image_check.go index cd5a9c1..25240a5 100644 --- a/pkg/container/allowed_base_image_check.go +++ b/pkg/container/allowed_base_image_check.go @@ -23,7 +23,7 @@ import ( "fmt" "strings" - txqualitychecks "github.com/eclipse-tractusx/tractusx-quality-checks/internal" + txqualitychecks "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/tractusx" ) var baseImageAllowList = []string{ diff --git a/internal/docs/changelog_exists.go b/pkg/docs/changelog_exists.go similarity index 76% rename from internal/docs/changelog_exists.go rename to pkg/docs/changelog_exists.go index af53b03..15740cf 100644 --- a/internal/docs/changelog_exists.go +++ b/pkg/docs/changelog_exists.go @@ -21,19 +21,21 @@ package docs import ( "os" + "path" - "github.com/eclipse-tractusx/tractusx-quality-checks/internal" + "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/tractusx" ) type ChangeLogExists struct { + baseDir string } -func (c ChangeLogExists) IsOptional() bool { - return false +func NewChangelogExists(baseDir string) *ChangeLogExists { + return &ChangeLogExists{baseDir} } -func NewChangelogExists() *ChangeLogExists { - return &ChangeLogExists{} +func (c ChangeLogExists) IsOptional() bool { + return false } func (c ChangeLogExists) Name() string { @@ -48,11 +50,11 @@ func (c ChangeLogExists) ExternalDescription() string { return "https://eclipse-tractusx.github.io/docs/release/trg-1/trg-1-3" } -func (c ChangeLogExists) Test() *txqualitychecks.QualityResult { - _, err := os.Stat("CHANGELOG.md") +func (c ChangeLogExists) Test() *tractusx.QualityResult { + _, err := os.Stat(path.Join(c.baseDir, "CHANGELOG.md")) if err != nil { - return &txqualitychecks.QualityResult{ErrorDescription: "A CHANGELOG.md file has to be present, describing the changes on between your releases"} + return &tractusx.QualityResult{ErrorDescription: "A CHANGELOG.md file has to be present, describing the changes on between your releases"} } - return &txqualitychecks.QualityResult{Passed: true} + return &tractusx.QualityResult{Passed: true} } diff --git a/internal/docs/changelog_exists_test.go b/pkg/docs/changelog_exists_test.go similarity index 77% rename from internal/docs/changelog_exists_test.go rename to pkg/docs/changelog_exists_test.go index b3f51cb..22efa85 100644 --- a/internal/docs/changelog_exists_test.go +++ b/pkg/docs/changelog_exists_test.go @@ -21,13 +21,12 @@ package docs import ( "os" + "path" "testing" ) func TestShouldFailIfChangelogFileIsMissing(t *testing.T) { - changelogTest := NewChangelogExists() - - result := changelogTest.Test() + result := NewChangelogExists("./").Test() if result.Passed { t.Errorf("ChangelogExist should fail if no Changelog file present") @@ -36,22 +35,28 @@ func TestShouldFailIfChangelogFileIsMissing(t *testing.T) { func TestShouldPassIfChangelogExists(t *testing.T) { _, _ = os.Create("CHANGELOG.md") - defer func() { - _ = os.Remove("CHANGELOG.md") - }() - changelogTest := NewChangelogExists() + defer os.Remove("CHANGELOG.md") - result := changelogTest.Test() + result := NewChangelogExists("./").Test() if !result.Passed { t.Errorf("ChangelogExist should pass, if a CHANGELOG.md exists") } } -func TestShouldProvideErrorDescriptionIfFailing(t *testing.T) { - changelogTest := NewChangelogExists() +func TestShouldFindChangelogAtGivenBaseDir(t *testing.T) { + dir := t.TempDir() + _, _ = os.Create(path.Join(dir, "CHANGELOG.md")) + + result := NewChangelogExists(dir).Test() + + if !result.Passed { + t.Errorf("ChangelogExist should find file at given base dir") + } +} - result := changelogTest.Test() +func TestShouldProvideErrorDescriptionIfFailing(t *testing.T) { + result := NewChangelogExists("./").Test() if result.ErrorDescription == "" { t.Errorf("Failing tests should provide an error description") diff --git a/internal/docs/install_exists.go b/pkg/docs/install_exists.go similarity index 70% rename from internal/docs/install_exists.go rename to pkg/docs/install_exists.go index 581f4f4..49d7140 100644 --- a/internal/docs/install_exists.go +++ b/pkg/docs/install_exists.go @@ -21,41 +21,43 @@ package docs import ( "os" + "path" - "github.com/eclipse-tractusx/tractusx-quality-checks/internal" + "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/tractusx" ) type InstallExists struct { + baseDir string } // NewInstallExists returns a new check based on QualityGuideline interface. -func NewInstallExists() txqualitychecks.QualityGuideline { - return &InstallExists{} +func NewInstallExists(baseDir string) tractusx.QualityGuideline { + return &InstallExists{baseDir} } -func (r *InstallExists) Name() string { +func (i *InstallExists) Name() string { return "TRG 1.02 - INSTALL.md" } -func (r *InstallExists) Description() string { +func (i *InstallExists) Description() string { return "File INSTALL.md contains comprehensive instructions for installation." } -func (r *InstallExists) ExternalDescription() string { +func (i *InstallExists) ExternalDescription() string { return "https://eclipse-tractusx.github.io/docs/release/trg-1/trg-1-2" } -func (r *InstallExists) Test() *txqualitychecks.QualityResult { - _, err := os.Stat("INSTALL.md") +func (i *InstallExists) Test() *tractusx.QualityResult { + _, err := os.Stat(path.Join(i.baseDir, "INSTALL.md")) if err != nil { - return &txqualitychecks.QualityResult{ + return &tractusx.QualityResult{ ErrorDescription: "Optional file INSTALL.md not found in current directory.", } } - return &txqualitychecks.QualityResult{Passed: true} + return &tractusx.QualityResult{Passed: true} } -func (r *InstallExists) IsOptional() bool { +func (i *InstallExists) IsOptional() bool { return true } diff --git a/pkg/docs/install_exists_test.go b/pkg/docs/install_exists_test.go new file mode 100644 index 0000000..ad0b9c5 --- /dev/null +++ b/pkg/docs/install_exists_test.go @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) 2023 Contributors to the Eclipse Foundation + * + * See the NOTICE file(s) distributed with this work for additional + * information regarding copyright ownership. + * + * This program and the accompanying materials are made available under the + * terms of the Apache License, Version 2.0 which is available at + * https://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ******************************************************************************/ + +package docs + +import ( + "os" + "path" + "testing" +) + +func TestShouldFailIfFileDoesNotExist(t *testing.T) { + result := NewInstallExists("./").Test() + + if result.Passed { + t.Errorf("InstallExists should fail if no INSTALL.md present") + } +} + +func TestShouldProvideErrorDescriptionOnFailure(t *testing.T) { + expectedError := "Optional file INSTALL.md not found in current directory." + + result := NewInstallExists("./").Test() + + if result.ErrorDescription != expectedError { + t.Errorf("Install.md check does not provide correct error description fon failing check!\n"+ + "expected: %s\ngot: %s", expectedError, result.ErrorDescription) + } +} + +func TestShouldPassIfFileExists(t *testing.T) { + if _, err := os.Create("INSTALL.md"); err != nil { + t.Errorf("Error creating test preconditions!") + } + defer os.Remove("INSTALL.md") + + result := NewInstallExists("./").Test() + + if !result.Passed { + t.Errorf("INSTALL exists, but test still fails") + } +} + +func TestShouldFindFileAtGivenBaseDir(t *testing.T) { + tempDir := t.TempDir() + if _, err := os.Create(path.Join(tempDir, "INSTALL.md")); err != nil { + t.Errorf("Error creating test preconditions!") + } + + result := NewInstallExists(tempDir).Test() + + if !result.Passed { + t.Errorf("INSTALL exists, but test still fails") + } +} diff --git a/internal/docs/readme_exists.go b/pkg/docs/readme_exists.go similarity index 76% rename from internal/docs/readme_exists.go rename to pkg/docs/readme_exists.go index 9c00eda..8b584c6 100644 --- a/internal/docs/readme_exists.go +++ b/pkg/docs/readme_exists.go @@ -21,19 +21,21 @@ package docs import ( "os" + "path" - "github.com/eclipse-tractusx/tractusx-quality-checks/internal" + "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/tractusx" ) type ReadmeExists struct { + baseDir string } -func (r *ReadmeExists) IsOptional() bool { - return false +func NewReadmeExists(baseDir string) tractusx.QualityGuideline { + return &ReadmeExists{baseDir} } -func NewReadmeExists() txqualitychecks.QualityGuideline { - return &ReadmeExists{} +func (r *ReadmeExists) IsOptional() bool { + return false } func (r *ReadmeExists) Name() string { @@ -48,11 +50,11 @@ func (r *ReadmeExists) ExternalDescription() string { return "https://eclipse-tractusx.github.io/docs/release/trg-1/trg-1-1" } -func (r *ReadmeExists) Test() *txqualitychecks.QualityResult { - _, err := os.Stat("README.md") +func (r *ReadmeExists) Test() *tractusx.QualityResult { + _, err := os.Stat(path.Join(r.baseDir, "README.md")) if err != nil { - return &txqualitychecks.QualityResult{ErrorDescription: "Did not find a README.md file in current directory!"} + return &tractusx.QualityResult{ErrorDescription: "Did not find a README.md file in current directory!"} } - return &txqualitychecks.QualityResult{Passed: true} + return &tractusx.QualityResult{Passed: true} } diff --git a/internal/docs/readme_exists_test.go b/pkg/docs/readme_exists_test.go similarity index 73% rename from internal/docs/readme_exists_test.go rename to pkg/docs/readme_exists_test.go index b384f68..45afb71 100644 --- a/internal/docs/readme_exists_test.go +++ b/pkg/docs/readme_exists_test.go @@ -21,13 +21,12 @@ package docs import ( "os" + "path" "testing" ) func TestShouldFailIfReadmeDoesNotExist(t *testing.T) { - readmeTest := NewReadmeExists() - - result := readmeTest.Test() + result := NewReadmeExists("./").Test() if result.Passed { t.Errorf("Readme check should fail, if no README file present") @@ -35,10 +34,9 @@ func TestShouldFailIfReadmeDoesNotExist(t *testing.T) { } func TestProvideErrorDescriptionOnFailingTest(t *testing.T) { - readmeTest := NewReadmeExists() expectedError := "Did not find a README.md file in current directory!" - result := readmeTest.Test() + result := NewReadmeExists("./").Test() if result.ErrorDescription != expectedError { t.Errorf("Readme check does not provide correct error description on failing check! \nexprected: %s, \ngot: %s", expectedError, result.ErrorDescription) @@ -46,27 +44,28 @@ func TestProvideErrorDescriptionOnFailingTest(t *testing.T) { } func TestShouldPassIfReadmeExists(t *testing.T) { - readmeTest := NewReadmeExists() - os.Create("README.md") + if _, err := os.Create("README.md"); err != nil { + t.Errorf("Could not create README.md for test") + } + defer os.Remove("README.md") - result := readmeTest.Test() + result := NewReadmeExists("./").Test() if !result.Passed { t.Errorf("README exists, but test still fails") } - os.Remove("README.md") } -func TestShouldNotProvideErrorDescriptionForPassingTest(t *testing.T) { - readmeTest := NewReadmeExists() - os.Create("README.md") +func TestShouldFindReadmeAtGivenBasePath(t *testing.T) { + dir := t.TempDir() + if _, err := os.Create(path.Join(dir, "README.md")); err != nil { + t.Errorf("Could not create README.md for test") + } - result := readmeTest.Test() + result := NewReadmeExists(dir).Test() - if result.ErrorDescription != "" { - t.Errorf("Passing tests should not contain any error description") + if !result.Passed { + t.Errorf("Could not find README.md at given base path") } - - os.Remove("README.md") } diff --git a/internal/helm/helmchart_structure_exists.go b/pkg/helm/helmchart_structure_exists.go similarity index 74% rename from internal/helm/helmchart_structure_exists.go rename to pkg/helm/helmchart_structure_exists.go index 276b4a2..82dbd8e 100644 --- a/internal/helm/helmchart_structure_exists.go +++ b/pkg/helm/helmchart_structure_exists.go @@ -20,18 +20,23 @@ package helm import ( - "github.com/eclipse-tractusx/tractusx-quality-checks/internal" - "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/filesystem" + "fmt" "os" + "path" "path/filepath" "strings" + + "github.com/eclipse-tractusx/tractusx-quality-checks/internal/filesystem" + "github.com/eclipse-tractusx/tractusx-quality-checks/internal/helm" + "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/tractusx" ) type HelmStructureExists struct { + baseDir string } -func NewHelmStructureExists() txqualitychecks.QualityGuideline { - return &HelmStructureExists{} +func NewHelmStructureExists(baseDir string) tractusx.QualityGuideline { + return &HelmStructureExists{baseDir} } func (r *HelmStructureExists) Name() string { @@ -46,7 +51,7 @@ func (r *HelmStructureExists) ExternalDescription() string { return "https://eclipse-tractusx.github.io/docs/release/trg-5/trg-5-02" } -func (r *HelmStructureExists) Test() *txqualitychecks.QualityResult { +func (r *HelmStructureExists) Test() *tractusx.QualityResult { helmStructureFiles := []string{ ".helmignore", "Chart.yaml", @@ -55,18 +60,18 @@ func (r *HelmStructureExists) Test() *txqualitychecks.QualityResult { "values.yaml", } - mainDir := "charts" + mainDir := path.Join(r.baseDir, "charts") if fi, err := os.Stat(mainDir); err != nil || !fi.IsDir() { - return &txqualitychecks.QualityResult{Passed: true} + return &tractusx.QualityResult{Passed: true} } helmCharts, err := os.ReadDir(mainDir) if err != nil || len(helmCharts) == 0 { - return &txqualitychecks.QualityResult{ErrorDescription: "Can't read Helm Charts at charts/."} + return &tractusx.QualityResult{ErrorDescription: fmt.Sprintf("Can't read Helm Charts at %s.", mainDir)} } - missingFiles := []string{} - chartYamlFiles := []string{} + var missingFiles []string + var chartYamlFiles []string for _, hc := range helmCharts { if hc.IsDir() { for _, fname := range helmStructureFiles { @@ -93,10 +98,10 @@ func (r *HelmStructureExists) Test() *txqualitychecks.QualityResult { } if len(missingFiles) > 0 || !chartsValid { - return &txqualitychecks.QualityResult{ErrorDescription: "+ Following Helm Chart structure files are missing: " + strings.Join(missingFiles, ", ") + + return &tractusx.QualityResult{ErrorDescription: "+ Following Helm Chart structure files are missing: " + strings.Join(missingFiles, ", ") + errorDescriptionCharts} } - return &txqualitychecks.QualityResult{Passed: true} + return &tractusx.QualityResult{Passed: true} } func (r *HelmStructureExists) IsOptional() bool { @@ -106,14 +111,14 @@ func (r *HelmStructureExists) IsOptional() bool { func validateChart(chartyamlfile string) (bool, string) { isValid := true returnMessage := "\n\t+ Analysis for " + chartyamlfile + ": " - cyf := chartYamlFromFile(chartyamlfile) - missingFields := cyf.getMissingMandatoryFields() + cyf := helm.ChartYamlFromFile(chartyamlfile) + missingFields := cyf.GetMissingMandatoryFields() if len(missingFields) > 0 { isValid = false returnMessage += "\n\t\t - Missing mandatory fields: " + strings.Join(missingFields, ", ") } - if !cyf.isVersionValid() { + if !cyf.IsVersionValid() { isValid = false returnMessage += "\n\t\t - " + cyf.Version + " Version of the Helm Chart is incorrect. It needs to follow Semantic Version." } diff --git a/internal/helm/helmchart_structure_exists_test.go b/pkg/helm/helmchart_structure_exists_test.go similarity index 59% rename from internal/helm/helmchart_structure_exists_test.go rename to pkg/helm/helmchart_structure_exists_test.go index e369e85..a60350f 100644 --- a/internal/helm/helmchart_structure_exists_test.go +++ b/pkg/helm/helmchart_structure_exists_test.go @@ -20,30 +20,29 @@ package helm import ( - "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/filesystem" "os" + "path" "testing" + + "github.com/eclipse-tractusx/tractusx-quality-checks/internal/filesystem" ) -var ValidChartYmlTestFile string = "test/TestChartValid.yaml" -var InValidChartYmlTestFile string = "test/TestChartInValid.yaml" +var validChartYmlTestFile = "test/TestChartValid.yaml" func TestShouldPassIfHelmDirIsMissing(t *testing.T) { - helmStructureTest := NewHelmStructureExists() - - result := helmStructureTest.Test() + result := NewHelmStructureExists("./").Test() if !result.Passed { t.Errorf("Helm directory doesn't exist hence test should pass.") } } -func TestShouldFailIfNoHelmChartsFound(t *testing.T) { +func TestShouldFailForEmptyChartsDir(t *testing.T) { os.Mkdir("charts", 0750) defer os.Remove("charts") - helmStructureTest := NewHelmStructureExists() - result := helmStructureTest.Test() + result := NewHelmStructureExists("./").Test() + if result.Passed { t.Errorf("Helm directory doesn't contain any charts hence test should fail.") } @@ -53,7 +52,7 @@ func TestShouldFailIfHelmStructureIsMissing(t *testing.T) { os.MkdirAll("charts/exampleChart", 0750) defer os.RemoveAll("charts") - helmStructureTest := NewHelmStructureExists() + helmStructureTest := NewHelmStructureExists("./") result := helmStructureTest.Test() @@ -63,52 +62,48 @@ func TestShouldFailIfHelmStructureIsMissing(t *testing.T) { } func TestShouldPassIfHelmStructureExist(t *testing.T) { - helmStructureDirsExample := []string{ - "charts/exampleChart/templates", - } - - helmStructureFilesExample := []string{ + _ = os.MkdirAll("charts/exampleChart/templates", 0750) + filesystem.CreateFiles([]string{ "charts/exampleChart/.helmignore", "charts/exampleChart/Chart.yaml", "charts/exampleChart/LICENSE", "charts/exampleChart/README.md", "charts/exampleChart/values.yaml", - } - - filesystem.CreateDirs(helmStructureDirsExample) - filesystem.CreateFiles(helmStructureFilesExample) + }) defer os.RemoveAll("charts") - copyTemplateFileTo("charts/exampleChart/Chart.yaml", t) - helmStructureTest := NewHelmStructureExists() - result := helmStructureTest.Test() + result := NewHelmStructureExists("./").Test() if !result.Passed { t.Errorf("Helm structure exists hence test should pass.") } } -func TestShouldPassIfConfigurationSettingsAreCorrect(t *testing.T) { - c := chartYamlFromFile(ValidChartYmlTestFile) - if len(c.getMissingMandatoryFields()) > 0 || !c.isVersionValid() { - t.Errorf("Configuration settings at TestChartValid.yaml are valid but test still fails.") - } -} +func TestShouldPassIfChartStructureExistsAtGivenBaseDir(t *testing.T) { + dir := t.TempDir() + os.MkdirAll(path.Join(dir, "charts", "exampleChart"), 0770) + filesystem.CreateFiles([]string{ + path.Join(dir, "charts/exampleChart/.helmignore"), + path.Join(dir, "charts/exampleChart/LICENSE"), + path.Join(dir, "charts/exampleChart/README.md"), + path.Join(dir, "charts/exampleChart/values.yaml"), + }) + copyTemplateFileTo(path.Join(dir, "charts", "exampleChart", "Chart.yaml"), t) + + result := NewHelmStructureExists(dir).Test() -func TestShouldFailIfConfigurationSettingsAreIncorrect(t *testing.T) { - c := chartYamlFromFile(InValidChartYmlTestFile) - if len(c.getMissingMandatoryFields()) == 0 || c.isVersionValid() { - t.Errorf("Configuration settings TestChartInvalid.yaml are invalid hence the test should pass.") + if !result.Passed { + t.Errorf("Should pass, if helm chart file and dir structure exists at given base dir") } } func copyTemplateFileTo(path string, t *testing.T) { - templateFile, err := os.ReadFile(ValidChartYmlTestFile) + templateFile, err := os.ReadFile(validChartYmlTestFile) if err != nil { t.Errorf("Could not read template file necessary for this test") } - err = os.WriteFile(path, templateFile, 0644) + err = os.WriteFile(path, templateFile, 0770) if err != nil { t.Errorf("Could not copy template file to designated path") } diff --git a/pkg/helm/test/TestChartValid.yaml b/pkg/helm/test/TestChartValid.yaml new file mode 100644 index 0000000..c2808dd --- /dev/null +++ b/pkg/helm/test/TestChartValid.yaml @@ -0,0 +1,44 @@ +# ******************************************************************************* +# Copyright (c) 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# ******************************************************************************* + +# Valid Test Chart.yaml + +apiVersion: v2 +name: test-application +description: A Test Helm chart +type: application +version: 1.0.0 +appVersion: "2.0.0" +# home: https://eclipse-tractusx.github.io/ +# sources: +# - https://github.com/eclipse-tractusx/test-application +# dependencies: +# - name: postgresql +# repository: https://charts.bitnami.com/bitnami +# version: 11.x.x +# condition: postgresql.enabled +# - name: pgadmin4 +# repository: https://helm.runix.net +# version: 1.13.6 +# condition: pgadmin4.enabled +# maintainers: +# - name: Joe +# email: joe@email.com +# url: https://joe.website.com + diff --git a/internal/repo/leading_repo_defined.go b/pkg/repo/leading_repo_defined.go similarity index 68% rename from internal/repo/leading_repo_defined.go rename to pkg/repo/leading_repo_defined.go index 7bf987a..f77615f 100644 --- a/internal/repo/leading_repo_defined.go +++ b/pkg/repo/leading_repo_defined.go @@ -22,15 +22,15 @@ package repo import ( "strings" - "github.com/eclipse-tractusx/tractusx-quality-checks/internal" - "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/product" + "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/tractusx" ) type LeadingRepositoryDefined struct { + baseDir string } -func NewLeadingRepositoryDefined() txqualitychecks.QualityGuideline { - return &LeadingRepositoryDefined{} +func NewLeadingRepositoryDefined(baseDir string) tractusx.QualityGuideline { + return &LeadingRepositoryDefined{baseDir} } func (l *LeadingRepositoryDefined) Name() string { @@ -49,15 +49,15 @@ func (l *LeadingRepositoryDefined) IsOptional() bool { return false } -func (l *LeadingRepositoryDefined) Test() *txqualitychecks.QualityResult { - metadata, err := product.MetadataFromLocalFile() +func (l *LeadingRepositoryDefined) Test() *tractusx.QualityResult { + metadata, err := tractusx.MetadataFromLocalFile(l.baseDir) if err != nil { - return &txqualitychecks.QualityResult{ErrorDescription: "Failed! The leadingRepository property must be defined in .tractusx metadata file. Could not load metadata"} + return &tractusx.QualityResult{ErrorDescription: "Failed! The leadingRepository property must be defined in .tractusx metadata file. Could not load metadata"} } if strings.TrimSpace(metadata.LeadingRepository) == "" { - return &txqualitychecks.QualityResult{ErrorDescription: "Failed! The leadingRepository property must be defined in .tractusx metadata file"} + return &tractusx.QualityResult{ErrorDescription: "Failed! The leadingRepository property must be defined in .tractusx metadata file"} } - return &txqualitychecks.QualityResult{Passed: true} + return &tractusx.QualityResult{Passed: true} } diff --git a/internal/repo/leading_repo_defined_test.go b/pkg/repo/leading_repo_defined_test.go similarity index 70% rename from internal/repo/leading_repo_defined_test.go rename to pkg/repo/leading_repo_defined_test.go index f07401b..c405988 100644 --- a/internal/repo/leading_repo_defined_test.go +++ b/pkg/repo/leading_repo_defined_test.go @@ -21,10 +21,11 @@ package repo import ( "os" + "path" "strings" "testing" - "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/product" + "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/tractusx" "gopkg.in/yaml.v3" ) @@ -37,7 +38,7 @@ func TestMain(m *testing.M) { } func TestShouldFailIfMetadataFileIsMissing(t *testing.T) { - result := NewLeadingRepositoryDefined().Test() + result := NewLeadingRepositoryDefined("./").Test() if result.Passed { t.Errorf("LeadingRepoDefined should faild, if there is no repository metadata") @@ -45,14 +46,14 @@ func TestShouldFailIfMetadataFileIsMissing(t *testing.T) { } func TestShouldFailIfLeadingRepositoryMetadataPropertyIsUndefined(t *testing.T) { - metadata := product.Metadata{ + metadata := tractusx.Metadata{ ProductName: "ProductWithoutLeadingRepo", LeadingRepository: "", Repositories: nil, } givenProductMetadata(t, metadata) - result := NewLeadingRepositoryDefined().Test() + result := NewLeadingRepositoryDefined("./").Test() if result.Passed { t.Errorf("Check should fail if metadata file exists, but does not have leading repo defined") } @@ -62,27 +63,47 @@ func TestShouldFailIfLeadingRepositoryMetadataPropertyIsUndefined(t *testing.T) } func TestShouldSucceedIfLeadingRepoIsDefinedInMetadata(t *testing.T) { - metadata := product.Metadata{ + metadata := tractusx.Metadata{ ProductName: "ProductWithoutLeadingRepo", LeadingRepository: "https://github.com/eclipse-tractusx/sig-infra", Repositories: nil, } givenProductMetadata(t, metadata) - result := NewLeadingRepositoryDefined().Test() + result := NewLeadingRepositoryDefined("./").Test() if !result.Passed { t.Errorf("Leading Repo check should pass, if configured in metadata") } } -func givenProductMetadata(t *testing.T, metadata product.Metadata) { +func TestShouldUseMetadataAtSpecifiedDirectory(t *testing.T) { + testDir := t.TempDir() + metadata := tractusx.Metadata{ + ProductName: "ProductWithoutLeadingRepo", + LeadingRepository: "https://github.com/eclipse-tractusx/sig-infra", + Repositories: nil, + } + givenProductMetadataAtDir(t, metadata, testDir) + + result := NewLeadingRepositoryDefined(testDir).Test() + + if !result.Passed { + t.Errorf("Leading Repo check should use metadata from a given path") + } +} + +func givenProductMetadata(t *testing.T, metadata tractusx.Metadata) { + givenProductMetadataAtDir(t, metadata, "./") +} + +func givenProductMetadataAtDir(t *testing.T, metadata tractusx.Metadata, dir string) { yamlContent, err := yaml.Marshal(&metadata) if err != nil { t.Errorf("Could not serialize metadata test content") } - err = os.WriteFile(".tractusx", yamlContent, 0600) + err = os.WriteFile(path.Join(dir, ".tractusx"), yamlContent, 0600) if err != nil { t.Errorf("Could not write test metadata file") } diff --git a/internal/repo/repo_structure_exists.go b/pkg/repo/repo_structure_exists.go similarity index 72% rename from internal/repo/repo_structure_exists.go rename to pkg/repo/repo_structure_exists.go index 1a8936d..c553c5a 100644 --- a/internal/repo/repo_structure_exists.go +++ b/pkg/repo/repo_structure_exists.go @@ -21,22 +21,24 @@ package repo import ( "fmt" + "path" "strings" "github.com/eclipse-tractusx/tractusx-quality-checks/internal" - "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/filesystem" - "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/product" + "github.com/eclipse-tractusx/tractusx-quality-checks/internal/filesystem" + "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/tractusx" ) type RepoStructureExists struct { + baseDir string } -func (c RepoStructureExists) IsOptional() bool { - return false +func NewRepoStructureExists(baseDir string) tractusx.QualityGuideline { + return &RepoStructureExists{baseDir} } -func NewRepoStructureExists() *RepoStructureExists { - return &RepoStructureExists{} +func (c RepoStructureExists) IsOptional() bool { + return false } func (c RepoStructureExists) Name() string { @@ -51,28 +53,28 @@ func (c RepoStructureExists) ExternalDescription() string { return "https://eclipse-tractusx.github.io/docs/release/trg-2/trg-2-3" } -func (c RepoStructureExists) Test() *txqualitychecks.QualityResult { +func (c RepoStructureExists) Test() *tractusx.QualityResult { // Slices containing required files and folders in the repo structure. // Before modification make sure you align to TRG 2.03 guideline. listOfOptionalFilesToBeChecked := []string{ - "AUTHORS.md", - "INSTALL.md", + path.Join(c.baseDir, "AUTHORS.md"), + path.Join(c.baseDir, "INSTALL.md"), } listOfMandatoryFilesToBeChecked := []string{ - "CODE_OF_CONDUCT.md", - "CONTRIBUTING.md", - "DEPENDENCIES", - "LICENSE", - "NOTICE.md", - "README.md", - "SECURITY.md", + path.Join(c.baseDir, "CODE_OF_CONDUCT.md"), + path.Join(c.baseDir, "CONTRIBUTING.md"), + path.Join(c.baseDir, "DEPENDENCIES"), + path.Join(c.baseDir, "LICENSE"), + path.Join(c.baseDir, "NOTICE.md"), + path.Join(c.baseDir, "README.md"), + path.Join(c.baseDir, "SECURITY.md"), } mandatoryForLeadingRepo := []string{"docs", "charts"} printer := &txqualitychecks.StdoutPrinter{} - if product.IsLeadingRepo() { + if isLeadingRepo() { listOfMandatoryFilesToBeChecked = append(listOfMandatoryFilesToBeChecked, mandatoryForLeadingRepo...) } @@ -87,8 +89,8 @@ func (c RepoStructureExists) Test() *txqualitychecks.QualityResult { } if len(missingMandatoryFiles) > 0 { - return &txqualitychecks.QualityResult{ErrorDescription: "The check detected following mandatory files missing: " + strings.Join(missingMandatoryFiles, ", ")} + return &tractusx.QualityResult{ErrorDescription: "The check detected following mandatory files missing: " + strings.Join(missingMandatoryFiles, ", ")} } - return &txqualitychecks.QualityResult{Passed: true} + return &tractusx.QualityResult{Passed: true} } diff --git a/internal/repo/repo_structure_exists_test.go b/pkg/repo/repo_structure_exists_test.go similarity index 87% rename from internal/repo/repo_structure_exists_test.go rename to pkg/repo/repo_structure_exists_test.go index af061c4..42e37cf 100644 --- a/internal/repo/repo_structure_exists_test.go +++ b/pkg/repo/repo_structure_exists_test.go @@ -20,12 +20,13 @@ package repo import ( - "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/filesystem" "os" "testing" + + "github.com/eclipse-tractusx/tractusx-quality-checks/internal/filesystem" ) -var listOfFilesToBeCreated []string = []string{ +var listOfFilesToBeCreated = []string{ "CODE_OF_CONDUCT.md", "CONTRIBUTING.md", "DEPENDENCIES", @@ -35,12 +36,12 @@ var listOfFilesToBeCreated []string = []string{ "SECURITY.md", } -var listOfDirsToBeCreated []string = []string{ +var listOfDirsToBeCreated = []string{ "docs", "charts", } -const metadataTestFile = "../../pkg/product/test/metadata_test_template.yaml" +const metadataTestFile = "./test/metadata_test_template.yaml" func TestShouldPassIfRepoStructureExistsWithoutOptional(t *testing.T) { setEnv(t) @@ -49,7 +50,7 @@ func TestShouldPassIfRepoStructureExistsWithoutOptional(t *testing.T) { filesystem.CreateFiles(listOfFilesToBeCreated) filesystem.CreateDirs(listOfDirsToBeCreated) - repostructureTest := NewRepoStructureExists() + repostructureTest := NewRepoStructureExists("./") result := repostructureTest.Test() filesystem.CleanFiles(append(listOfFilesToBeCreated, listOfDirsToBeCreated...)) @@ -67,7 +68,7 @@ func TestShouldPassIfRepoStructureExistsWithOptional(t *testing.T) { filesystem.CreateFiles(listOfFilesToBeCreated) filesystem.CreateDirs(listOfDirsToBeCreated) - repostructureTest := NewRepoStructureExists() + repostructureTest := NewRepoStructureExists("./") result := repostructureTest.Test() filesystem.CleanFiles(append(listOfFilesToBeCreated, listOfDirsToBeCreated...)) @@ -81,7 +82,7 @@ func TestShouldFailIfRepoStructureIsMissing(t *testing.T) { setEnv(t) defer os.Remove(".tractusx") - repostructureTest := NewRepoStructureExists() + repostructureTest := NewRepoStructureExists("./") result := repostructureTest.Test() diff --git a/pkg/repo/repoinfo.go b/pkg/repo/repoinfo.go index 63f844a..ee902f1 100644 --- a/pkg/repo/repoinfo.go +++ b/pkg/repo/repoinfo.go @@ -20,13 +20,12 @@ package repo import ( - "context" "fmt" "os" "strings" + "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/tractusx" "github.com/go-ini/ini" - "github.com/google/go-github/v50/github" ) // RepoInfo provides basic infor @@ -80,16 +79,14 @@ func GetRepoBaseInfo() *RepoInfo { return &result } -// getRepoInfo returns *github.Repository object and error. If GitHub API call -// failed, an error is returned. -func GetRepoMetadata(repo *RepoInfo) *github.Repository { - ctx := context.Background() - client := *github.NewClient(nil) +func isLeadingRepo() bool { + metadata, err := tractusx.MetadataFromLocalFile("./") + repoInfo := GetRepoBaseInfo() + fullRepoName := "https://github.com/eclipse-tractusx/" + (*repoInfo).Reponame - repoInfo, _, err := client.Repositories.Get(ctx, repo.Owner, repo.Reponame) - if err != nil { - fmt.Printf("Error querying GitHub API:\n%v\n", err) + if err != nil || metadata.LeadingRepository != fullRepoName { + return false } - return repoInfo + return true } diff --git a/pkg/product/test/metadata_test_template.yaml b/pkg/repo/test/metadata_test_template.yaml similarity index 100% rename from pkg/product/test/metadata_test_template.yaml rename to pkg/repo/test/metadata_test_template.yaml diff --git a/pkg/product/metadata.go b/pkg/tractusx/metadata.go similarity index 79% rename from pkg/product/metadata.go rename to pkg/tractusx/metadata.go index ac64e99..859665d 100644 --- a/pkg/product/metadata.go +++ b/pkg/tractusx/metadata.go @@ -17,13 +17,14 @@ * SPDX-License-Identifier: Apache-2.0 ******************************************************************************/ -package product +package tractusx import ( "fmt" - "github.com/eclipse-tractusx/tractusx-quality-checks/pkg/repo" - "gopkg.in/yaml.v3" "os" + "path" + + "gopkg.in/yaml.v3" ) const MetadataFilename = ".tractusx" @@ -54,11 +55,11 @@ func MetadataFromFile(fileContent []byte) (*Metadata, error) { return &metadata, nil } -// MetadataFromLocalFile will read a local file '.tractusx', that is supposed to contain information about +// MetadataFromLocalFile will read a local file '.tractusx in the specified dir', that is supposed to contain information about // a product. If the file exists, MetadataFromLocalFile will return the information as an instance of Metadata. // If the file cannot be parsed or does not exist, an error is returned and Metadata will be nil -func MetadataFromLocalFile() (*Metadata, error) { - metadataFileAsBytes, err := os.ReadFile(MetadataFilename) +func MetadataFromLocalFile(dir string) (*Metadata, error) { + metadataFileAsBytes, err := os.ReadFile(path.Join(dir, MetadataFilename)) if err != nil { fmt.Println(fmt.Sprintf("Could not read Tractus-X metadatafile from default location: %s", MetadataFilename)) @@ -73,16 +74,3 @@ func MetadataFromLocalFile() (*Metadata, error) { return file, nil } - -func IsLeadingRepo() bool { - - metadata, err := MetadataFromLocalFile() - repoInfo := repo.GetRepoBaseInfo() - fullRepoName := "https://github.com/eclipse-tractusx/" + (*repoInfo).Reponame - - if err != nil || metadata.LeadingRepository != fullRepoName { - return false - } - - return true -} diff --git a/pkg/product/metadata_test.go b/pkg/tractusx/metadata_test.go similarity index 76% rename from pkg/product/metadata_test.go rename to pkg/tractusx/metadata_test.go index 5338ff4..a859243 100644 --- a/pkg/product/metadata_test.go +++ b/pkg/tractusx/metadata_test.go @@ -17,10 +17,11 @@ * SPDX-License-Identifier: Apache-2.0 ******************************************************************************/ -package product +package tractusx import ( "os" + "path" "reflect" "testing" ) @@ -45,7 +46,7 @@ var metadataFromTestTemplate = Metadata{ const metadataTestFile = "./test/metadata_test_template.yaml" func TestShouldReturnErrorWhenReadingNonExistentDefaultMetadataFile(t *testing.T) { - _, err := MetadataFromLocalFile() + _, err := MetadataFromLocalFile("./") if err == nil { t.Errorf("Reading the product metadata file from default location should fail if not existing") @@ -58,7 +59,7 @@ func TestShouldReadProductMetadataFromDefaultFile(t *testing.T) { copyTemplateFileTo(".tractusx", t) defer os.Remove(".tractusx") - metadata, err := MetadataFromLocalFile() + metadata, err := MetadataFromLocalFile("./") if err != nil { t.Errorf("Should be able to read metadata file after copying to default location") @@ -69,26 +70,14 @@ func TestShouldReadProductMetadataFromDefaultFile(t *testing.T) { } } -func TestShouldPassIsLeadingRepoValidEnvVariable(t *testing.T) { - copyTemplateFileTo(".tractusx", t) - defer os.Remove(".tractusx") - os.Setenv("GITHUB_REPOSITORY", "eclipse-tractusx/sig-infra") - os.Setenv("GITHUB_REPOSITORY_OWNER", "tester") +func TestShouldReadMetadataFromGivenBaseDir(t *testing.T) { + tempDir := t.TempDir() + copyTemplateFileTo(path.Join(tempDir, ".tractusx"), t) - if !IsLeadingRepo() { - t.Errorf("Test should pass, but $GITHUB_REPOSITORY is not equal leadingRepo from .tractusx") - } - -} + metadata, _ := MetadataFromLocalFile(tempDir) -func TestShouldFailIsLeadingRepoFakeEnvVariable(t *testing.T) { - copyTemplateFileTo(".tractusx", t) - defer os.Remove(".tractusx") - os.Setenv("GITHUB_REPOSITORY", "repo/fake_reponame") - os.Setenv("GITHUB_REPOSITORY_OWNER", "tester") - - if IsLeadingRepo() { - t.Errorf("Repo shouldn't be identified as leading one, there is fake env variable $GITHUB_REPOSITORY.") + if !reflect.DeepEqual(metadata, &metadataFromTestTemplate) { + t.Errorf("Metadata read from given base directory does not match test template values") } } diff --git a/pkg/tractusx/test/metadata_test_template.yaml b/pkg/tractusx/test/metadata_test_template.yaml new file mode 100644 index 0000000..0066ee0 --- /dev/null +++ b/pkg/tractusx/test/metadata_test_template.yaml @@ -0,0 +1,29 @@ +############################################################################### +# Copyright (c) 2023 Contributors to the Eclipse Foundation +# +# See the NOTICE file(s) distributed with this work for additional +# information regarding copyright ownership. +# +# This program and the accompanying materials are made available under the +# terms of the Apache License, Version 2.0 which is available at +# https://www.apache.org/licenses/LICENSE-2.0. +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +# SPDX-License-Identifier: Apache-2.0 +############################################################################## +--- + +product: "sig-infra" +leadingRepository: "https://github.com/eclipse-tractusx/sig-infra" +repositories: + - name: "sig-infra" + usage: "Contains issue templates and workflows" + url: "https://github.com/eclipse-tractusx/sig-infra" + - name: "charts" + usage: "Central Helm repository containing all released charts of Tractus-X" + url: "https://github.com/eclipse-tractusx/charts" diff --git a/internal/types.go b/pkg/tractusx/types.go similarity index 98% rename from internal/types.go rename to pkg/tractusx/types.go index 01a481c..febe516 100644 --- a/internal/types.go +++ b/pkg/tractusx/types.go @@ -17,7 +17,7 @@ * SPDX-License-Identifier: Apache-2.0 ******************************************************************************/ -package txqualitychecks +package tractusx // QualityGuideline represents the QualityGuideline to check as an interface. //