diff --git a/.github/.testcoverage-local.yml b/.github/.testcoverage-local.yml index c33ba25c..8ce01510 100644 --- a/.github/.testcoverage-local.yml +++ b/.github/.testcoverage-local.yml @@ -1,7 +1,6 @@ # Config file for go-test-coverage running locally. profile: cover.profile -local-prefix: github.com/vladopajic/go-test-coverage/v2 threshold: file: 100 total: 98 diff --git a/.github/workflows/action-test.yml b/.github/workflows/action-test.yml index d97358f9..e1055379 100644 --- a/.github/workflows/action-test.yml +++ b/.github/workflows/action-test.yml @@ -95,7 +95,6 @@ jobs: id: test-3 with: profile: cover.out - local-prefix: "github.com/vladopajic/go-test-coverage/v2" threshold-file: 0 threshold-package: 0 threshold-total: 0 @@ -108,7 +107,6 @@ jobs: continue-on-error: true with: profile: cover.out - local-prefix: "github.com/vladopajic/go-test-coverage/v2" threshold-file: 0 threshold-package: 0 threshold-total: 100 diff --git a/.github/workflows/testdata/total100.yml b/.github/workflows/testdata/total100.yml index 96fd8d5b..4e7d3dee 100644 --- a/.github/workflows/testdata/total100.yml +++ b/.github/workflows/testdata/total100.yml @@ -1,7 +1,6 @@ # This file is used for integration tests profile: cover.out -local-prefix: "github.com/vladopajic/go-test-coverage/v2" threshold: file: 0 package: 0 diff --git a/.github/workflows/testdata/zero.yml b/.github/workflows/testdata/zero.yml index d509f878..479891ba 100644 --- a/.github/workflows/testdata/zero.yml +++ b/.github/workflows/testdata/zero.yml @@ -1,7 +1,6 @@ # This file is used for integration tests profile: cover.out -local-prefix: "github.com/vladopajic/go-test-coverage/v2" threshold: file: 0 package: 0 diff --git a/.testcoverage.example.yml b/.testcoverage.example.yml index f807bea8..da9937d3 100644 --- a/.testcoverage.example.yml +++ b/.testcoverage.example.yml @@ -7,10 +7,6 @@ # of profile files, e.g., 'cover_unit.out,cover_integration.out'. profile: cover.out -# (optional; but recommended to set) -# When specified reported file paths will not contain local prefix in the output. -local-prefix: "github.com/org/project" - # Holds coverage thresholds percentages, values should be in range [0-100]. threshold: # (optional; default 0) diff --git a/README.md b/README.md index b6caacc1..be334b8a 100644 --- a/README.md +++ b/README.md @@ -90,10 +90,6 @@ Here’s an example [.testcoverage.yml](./.testcoverage.example.yml) configurati # of profile files, e.g., 'cover_unit.out,cover_integration.out'. profile: cover.out -# (optional; but recommended to set) -# When specified reported file paths will not contain local prefix in the output. -local-prefix: "github.com/org/project" - # Holds coverage thresholds percentages, values should be in range [0-100]. threshold: # (optional; default 0) diff --git a/action.yml b/action.yml index 4ff3ab70..4dea6bf2 100644 --- a/action.yml +++ b/action.yml @@ -15,8 +15,9 @@ inputs: required: false default: "" type: string - local-prefix: - description: When specified reported file paths will not contain local prefix in the output. Overrides value from configuration. + # DEPRECATED + local-prefix: + description: DEPRECATED! not used anymore. required: false default: "" type: string @@ -132,7 +133,6 @@ runs: - --config=${{ inputs.config || '''''' }} - --profile=${{ inputs.profile || '''''' }} - --github-action-output=true - - --local-prefix=${{ inputs.local-prefix || '''''' }} - --threshold-file=${{ inputs.threshold-file }} - --threshold-package=${{ inputs.threshold-package }} - --threshold-total=${{ inputs.threshold-total }} diff --git a/docs/badge.md b/docs/badge.md index becf0a9b..eddf2998 100644 --- a/docs/badge.md +++ b/docs/badge.md @@ -21,7 +21,6 @@ Example: uses: vladopajic/go-test-coverage@v2 with: profile: cover.out - local-prefix: github.com/org/project threshold-total: 95 ## when token is not specified (value '') this feature is turned off @@ -67,7 +66,6 @@ Example: uses: vladopajic/go-test-coverage@v2 with: profile: cover.out - local-prefix: github.com/org/project threshold-total: 95 ## when secret is not specified (value '') this feature is turned off. @@ -94,7 +92,6 @@ Example: uses: vladopajic/go-test-coverage@v2 with: profile: cover.out - local-prefix: github.com/org/project threshold-total: 95 # badge will be generated and store on file system with `coverage.svg` name @@ -113,7 +110,6 @@ Example: uses: vladopajic/go-test-coverage@v2 with: profile: cover.out - local-prefix: github.com/org/project threshold-total: 95 ## in this case token should be from other repository that will host badges. diff --git a/docs/github_action.md b/docs/github_action.md index cd55da0f..93ef95d6 100644 --- a/docs/github_action.md +++ b/docs/github_action.md @@ -31,7 +31,6 @@ Alternatively, if you don't need advanced configuration options from a config fi uses: vladopajic/go-test-coverage@v2 with: profile: cover.out - local-prefix: github.com/org/project threshold-file: 80 threshold-package: 80 threshold-total: 95 diff --git a/main.go b/main.go index b88a5235..50ddb39a 100644 --- a/main.go +++ b/main.go @@ -26,7 +26,7 @@ const ( type args struct { ConfigPath string `arg:"-c,--config"` Profile string `arg:"-p,--profile" help:"path to coverage profile"` - LocalPrefix string `arg:"-l,--local-prefix"` + LocalPrefix string `arg:"-l,--local-prefix"` // deprecated GithubActionOutput bool `arg:"-o,--github-action-output"` ThresholdFile int `arg:"-f,--threshold-file"` ThresholdPackage int `arg:"-k,--threshold-package"` @@ -99,7 +99,7 @@ func (a *args) overrideConfig(cfg testcoverage.Config) (testcoverage.Config, err } if !isCIDefaultString(a.LocalPrefix) { - cfg.LocalPrefix = a.LocalPrefix + cfg.LocalPrefixDeprecated = a.LocalPrefix } if !isCIDefaultInt(a.ThresholdFile) { diff --git a/pkg/testcoverage/check.go b/pkg/testcoverage/check.go index d3474a02..a272734d 100644 --- a/pkg/testcoverage/check.go +++ b/pkg/testcoverage/check.go @@ -42,6 +42,11 @@ func Check(w io.Writer, cfg Config) bool { fmt.Fprintf(w, "failed setting github action output: %v\n", err) return false } + + if cfg.LocalPrefixDeprecated != "" { // coverage-ignore + reportGHWarning(w, "Deprecated option", + "local-prefix option is deprecated since v2.13.0, you can safely remove setting this option") + } } err = generateAndSaveBadge(w, cfg, result.TotalStats.CoveredPercentage()) @@ -68,8 +73,8 @@ func reportForHuman(w io.Writer, result AnalyzeResult) string { func GenerateCoverageStats(cfg Config) ([]coverage.Stats, error) { return coverage.GenerateCoverageStats(coverage.Config{ //nolint:wrapcheck // err wrapped above Profiles: strings.Split(cfg.Profile, ","), - LocalPrefix: cfg.LocalPrefix, ExcludePaths: cfg.Exclude.Paths, + RootDir: cfg.RootDir, }) } diff --git a/pkg/testcoverage/check_test.go b/pkg/testcoverage/check_test.go index c331a4c2..1773c726 100644 --- a/pkg/testcoverage/check_test.go +++ b/pkg/testcoverage/check_test.go @@ -21,6 +21,9 @@ const ( profileNOK = testdataDir + testdata.ProfileNOK breakdownOK = testdataDir + testdata.BreakdownOK breakdownNOK = testdataDir + testdata.BreakdownNOK + + prefix = "github.com/vladopajic/go-test-coverage/v2" + rootDir = "../../" ) func TestCheck(t *testing.T) { @@ -30,8 +33,6 @@ func TestCheck(t *testing.T) { return } - const prefix = "github.com/vladopajic/go-test-coverage/v2" - t.Run("no profile", func(t *testing.T) { t.Parallel() @@ -59,11 +60,12 @@ func TestCheck(t *testing.T) { t.Parallel() buf := &bytes.Buffer{} - cfg := Config{Profile: profileOK, Threshold: Threshold{Total: 65}} + cfg := Config{Profile: profileOK, Threshold: Threshold{Total: 65}, RootDir: rootDir} pass := Check(buf, cfg) assert.True(t, pass) assertGithubActionErrorsCount(t, buf.String(), 0) assertHumanReport(t, buf.String(), 1, 0) + assertNoFileNames(t, buf.String(), prefix) assertNoUncoveredLinesInfo(t, buf.String()) }) @@ -77,6 +79,7 @@ func TestCheck(t *testing.T) { Exclude: Exclude{ Paths: []string{`cdn\.go$`, `github\.go$`, `cover\.go$`, `check\.go$`, `path\.go$`}, }, + RootDir: rootDir, } pass := Check(buf, cfg) assert.True(t, pass) @@ -89,7 +92,7 @@ func TestCheck(t *testing.T) { t.Parallel() buf := &bytes.Buffer{} - cfg := Config{Profile: profileOK, Threshold: Threshold{Total: 100}} + cfg := Config{Profile: profileOK, Threshold: Threshold{Total: 100}, RootDir: rootDir} pass := Check(buf, cfg) assert.False(t, pass) assertGithubActionErrorsCount(t, buf.String(), 0) @@ -102,20 +105,6 @@ func TestCheck(t *testing.T) { }) }) - t.Run("valid profile - pass with prefix", func(t *testing.T) { - t.Parallel() - - buf := &bytes.Buffer{} - - cfg := Config{Profile: profileOK, LocalPrefix: prefix, Threshold: Threshold{Total: 65}} - pass := Check(buf, cfg) - assert.True(t, pass) - assertGithubActionErrorsCount(t, buf.String(), 0) - assertHumanReport(t, buf.String(), 1, 0) - assertNoFileNames(t, buf.String(), prefix) - assertNoUncoveredLinesInfo(t, buf.String()) - }) - t.Run("valid profile - pass after override", func(t *testing.T) { t.Parallel() @@ -124,6 +113,7 @@ func TestCheck(t *testing.T) { Profile: profileOK, Threshold: Threshold{File: 100}, Override: []Override{{Threshold: 10, Path: "^pkg"}}, + RootDir: rootDir, } pass := Check(buf, cfg) assert.True(t, pass) @@ -141,6 +131,7 @@ func TestCheck(t *testing.T) { Profile: profileOK, Threshold: Threshold{File: 10}, Override: []Override{{Threshold: 100, Path: "^pkg"}}, + RootDir: rootDir, } pass := Check(buf, cfg) assert.False(t, pass) @@ -162,6 +153,7 @@ func TestCheck(t *testing.T) { Profile: profileOK, Threshold: Threshold{File: 70}, Override: []Override{{Threshold: 60, Path: "pkg/testcoverage/badgestorer/github.go"}}, + RootDir: rootDir, } pass := Check(buf, cfg) assert.True(t, pass) @@ -179,6 +171,7 @@ func TestCheck(t *testing.T) { Profile: profileOK, Threshold: Threshold{File: 70}, Override: []Override{{Threshold: 80, Path: "pkg/testcoverage/badgestorer/github.go"}}, + RootDir: rootDir, } pass := Check(buf, cfg) assert.False(t, pass) @@ -202,6 +195,7 @@ func TestCheck(t *testing.T) { Badge: Badge{ FileName: t.TempDir(), // should failed because this is dir }, + RootDir: rootDir, } pass := Check(buf, cfg) assert.False(t, pass) @@ -215,6 +209,7 @@ func TestCheck(t *testing.T) { cfg := Config{ Profile: profileOK, BreakdownFileName: t.TempDir(), // should failed because this is dir + RootDir: rootDir, } pass := Check(buf, cfg) assert.False(t, pass) @@ -228,6 +223,7 @@ func TestCheck(t *testing.T) { cfg := Config{ Profile: profileOK, BreakdownFileName: t.TempDir() + "/breakdown.testcoverage", + RootDir: rootDir, } pass := Check(buf, cfg) assert.True(t, pass) @@ -250,6 +246,7 @@ func TestCheck(t *testing.T) { Diff: Diff{ BaseBreakdownFileName: t.TempDir(), // should failed because this is dir }, + RootDir: rootDir, } pass := Check(buf, cfg) assert.False(t, pass) @@ -267,7 +264,12 @@ func TestCheckNoParallel(t *testing.T) { t.Setenv(GaOutputFileEnv, "") buf := &bytes.Buffer{} - cfg := Config{Profile: profileOK, GithubActionOutput: true, Threshold: Threshold{Total: 100}} + cfg := Config{ + Profile: profileOK, + GithubActionOutput: true, + Threshold: Threshold{Total: 100}, + RootDir: rootDir, + } pass := Check(buf, cfg) assert.False(t, pass) }) @@ -277,7 +279,12 @@ func TestCheckNoParallel(t *testing.T) { t.Setenv(GaOutputFileEnv, testFile) buf := &bytes.Buffer{} - cfg := Config{Profile: profileOK, GithubActionOutput: true, Threshold: Threshold{Total: 10}} + cfg := Config{ + Profile: profileOK, + GithubActionOutput: true, + Threshold: Threshold{Total: 10}, + RootDir: rootDir, + } pass := Check(buf, cfg) assert.True(t, pass) assertGithubActionErrorsCount(t, buf.String(), 0) @@ -291,7 +298,12 @@ func TestCheckNoParallel(t *testing.T) { t.Setenv(GaOutputFileEnv, testFile) buf := &bytes.Buffer{} - cfg := Config{Profile: profileOK, GithubActionOutput: true, Threshold: Threshold{Total: 100}} + cfg := Config{ + Profile: profileOK, + GithubActionOutput: true, + Threshold: Threshold{Total: 100}, + RootDir: rootDir, + } pass := Check(buf, cfg) assert.False(t, pass) assertGithubActionErrorsCount(t, buf.String(), 1) @@ -319,7 +331,7 @@ func Test_Analyze(t *testing.T) { t.Parallel() result := Analyze( - Config{LocalPrefix: prefix, Threshold: Threshold{Total: 10}}, + Config{Threshold: Threshold{Total: 10}}, randStats(prefix, 10, 100), nil, ) @@ -350,7 +362,7 @@ func Test_Analyze(t *testing.T) { t.Parallel() result := Analyze( - Config{LocalPrefix: prefix, Threshold: Threshold{File: 10}}, + Config{Threshold: Threshold{File: 10}}, randStats(prefix, 10, 100), nil, ) @@ -379,7 +391,7 @@ func Test_Analyze(t *testing.T) { t.Parallel() result := Analyze( - Config{LocalPrefix: prefix, Threshold: Threshold{Package: 10}}, + Config{Threshold: Threshold{Package: 10}}, randStats(prefix, 10, 100), nil, ) diff --git a/pkg/testcoverage/config.go b/pkg/testcoverage/config.go index 7334f245..acc6e816 100644 --- a/pkg/testcoverage/config.go +++ b/pkg/testcoverage/config.go @@ -22,15 +22,16 @@ var ( ) type Config struct { - Profile string `yaml:"profile"` - LocalPrefix string `yaml:"local-prefix"` - Threshold Threshold `yaml:"threshold"` - Override []Override `yaml:"override,omitempty"` - Exclude Exclude `yaml:"exclude"` - BreakdownFileName string `yaml:"breakdown-file-name"` - GithubActionOutput bool `yaml:"github-action-output"` - Diff Diff `yaml:"diff"` - Badge Badge `yaml:"-"` + Profile string `yaml:"profile"` + LocalPrefixDeprecated string `yaml:"-"` + Threshold Threshold `yaml:"threshold"` + Override []Override `yaml:"override,omitempty"` + Exclude Exclude `yaml:"exclude"` + BreakdownFileName string `yaml:"breakdown-file-name"` + GithubActionOutput bool `yaml:"github-action-output"` + Diff Diff `yaml:"diff"` + Badge Badge `yaml:"-"` + RootDir string `yaml:"-"` } type Threshold struct { diff --git a/pkg/testcoverage/config_test.go b/pkg/testcoverage/config_test.go index af7bb6e8..24a686f0 100644 --- a/pkg/testcoverage/config_test.go +++ b/pkg/testcoverage/config_test.go @@ -201,10 +201,9 @@ func TestConfigYamlParse(t *testing.T) { func nonZeroConfig() Config { return Config{ - Profile: "cover.out", - LocalPrefix: "prefix", - Threshold: Threshold{100, 100, 100}, - Override: []Override{{Path: "pathToFile", Threshold: 99}}, + Profile: "cover.out", + Threshold: Threshold{100, 100, 100}, + Override: []Override{{Path: "pathToFile", Threshold: 99}}, Exclude: Exclude{ Paths: []string{"path1", "path2"}, }, @@ -219,7 +218,6 @@ func nonZeroConfig() Config { func nonZeroYaml() string { return ` profile: cover.out -local-prefix: prefix threshold: file: 100 package: 100 diff --git a/pkg/testcoverage/coverage/cover.go b/pkg/testcoverage/coverage/cover.go index 153730a0..a771c4f2 100644 --- a/pkg/testcoverage/coverage/cover.go +++ b/pkg/testcoverage/coverage/cover.go @@ -20,8 +20,8 @@ const IgnoreText = "coverage-ignore" type Config struct { Profiles []string - LocalPrefix string ExcludePaths []string + RootDir string } func GenerateCoverageStats(cfg Config) ([]Stats, error) { @@ -30,7 +30,7 @@ func GenerateCoverageStats(cfg Config) ([]Stats, error) { return nil, fmt.Errorf("parsing profiles: %w", err) } - files, err := findFiles(profiles, cfg.LocalPrefix) + files, err := findFiles(profiles, cfg.RootDir) if err != nil { return nil, err } @@ -45,7 +45,7 @@ func GenerateCoverageStats(cfg Config) ([]Stats, error) { return nil, fmt.Errorf("could not find file [%s]", profile.FileName) } - if ok := matches(excludeRules, fi.noPrefixName); ok { + if ok := matches(excludeRules, fi.name); ok { continue // this file is excluded } @@ -92,39 +92,47 @@ func coverageForFile(profile *cover.Profile, fi fileInfo) (Stats, error) { } s := sumCoverage(profile, funcs, blocks, annotations) - s.Name = fi.noPrefixName + s.Name = fi.name return s, nil } type fileInfo struct { - path string - noPrefixName string + path string + name string } -func findFiles(profiles []*cover.Profile, prefix string) (map[string]fileInfo, error) { +func findFiles(profiles []*cover.Profile, rootDir string) (map[string]fileInfo, error) { result := make(map[string]fileInfo) - findFile := findFileCreator() + findFile := findFileCreator(rootDir) for _, profile := range profiles { - file, noPrefixName, found := findFile(profile.FileName, prefix) + path, noPrefixName, found := findFile(profile.FileName) if !found { return nil, fmt.Errorf("could not find file [%s]", profile.FileName) } result[profile.FileName] = fileInfo{ - path: file, - noPrefixName: noPrefixName, + path: path, + name: noPrefixName, } } return result, nil } -func findFileCreator() func(file, prefix string) (string, string, bool) { - cache := make(map[string]*build.Package) - files := listAllFiles(".") +func defaultRootDir(rootDir string) string { + if rootDir == "" { + rootDir = "." + } + + return rootDir +} +func findFileCreator(rootDir string) func(file string) (string, string, bool) { + rootDir = defaultRootDir(rootDir) + + cache := make(map[string]*build.Package) findBuildImport := func(file string) (string, string, bool) { dir, file := filepath.Split(file) pkg, exists := cache[dir] @@ -147,6 +155,8 @@ func findFileCreator() func(file, prefix string) (string, string, bool) { return file, noPrefixName, err == nil } + prefix := findModuleDirective(rootDir) + files := listAllFiles(rootDir) findWalk := func(file, prefix string) (string, string, bool) { noPrefixName := stripPrefix(file, prefix) f, found := hasFile(files, noPrefixName) @@ -154,21 +164,21 @@ func findFileCreator() func(file, prefix string) (string, string, bool) { return path.NormalizeForOS(f), noPrefixName, found } - return func(file, prefix string) (string, string, bool) { - if fPath, fNoPrefix, found := findWalk(file, prefix); found { // coverage-ignore - return fPath, fNoPrefix, found + return func(fileName string) (string, string, bool) { + if path, name, found := findWalk(fileName, prefix); found { + return path, name, found } - if fPath, fNoPrefix, found := findBuildImport(file); found { - return fPath, fNoPrefix, found + if path, name, found := findBuildImport(fileName); found { + return path, name, found } return "", "", false } } -func listAllFiles(rootDir string) []string { - files := make([]string, 0) +func listAllFiles(rootDir string) []fileInfo { + files := make([]fileInfo, 0) //nolint:errcheck // error ignored because there is fallback mechanism for finding files filepath.Walk(rootDir, func(file string, info os.FileInfo, err error) error { @@ -179,7 +189,13 @@ func listAllFiles(rootDir string) []string { if !info.IsDir() && strings.HasSuffix(file, ".go") && !strings.HasSuffix(file, "_test.go") { - files = append(files, path.NormalizeForTool(file)) + name, _ := strings.CutPrefix(file, rootDir) + name = path.NormalizeForTool(name) + + files = append(files, fileInfo{ + path: file, + name: name, + }) } return nil @@ -188,16 +204,16 @@ func listAllFiles(rootDir string) []string { return files } -func hasFile(files []string, search string) (string, bool) { +func hasFile(files []fileInfo, search string) (string, bool) { var result string for _, f := range files { - if strings.HasSuffix(f, search) { + if strings.HasSuffix(f.name, search) { if result != "" { return "", false } - result = f + result = f.path } } diff --git a/pkg/testcoverage/coverage/cover_test.go b/pkg/testcoverage/coverage/cover_test.go index 6d6c4e65..87fb1e6b 100644 --- a/pkg/testcoverage/coverage/cover_test.go +++ b/pkg/testcoverage/coverage/cover_test.go @@ -24,6 +24,8 @@ const ( prefix = "github.com/vladopajic/go-test-coverage/v2" coverFilename = "pkg/testcoverage/coverage/cover.go" + + rootDir = "../../../" ) func Test_GenerateCoverageStats(t *testing.T) { @@ -39,12 +41,18 @@ func Test_GenerateCoverageStats(t *testing.T) { assert.Empty(t, stats) // should get error parsing invalid profile file - stats, err = GenerateCoverageStats(Config{Profiles: []string{profileNOK}}) + stats, err = GenerateCoverageStats(Config{ + Profiles: []string{profileNOK}, + RootDir: rootDir, + }) assert.Error(t, err) assert.Empty(t, stats) // should be okay to read valid profile - stats1, err := GenerateCoverageStats(Config{Profiles: []string{profileOK}}) + stats1, err := GenerateCoverageStats(Config{ + Profiles: []string{profileOK}, + RootDir: rootDir, + }) assert.NoError(t, err) assert.NotEmpty(t, stats1) @@ -52,38 +60,30 @@ func Test_GenerateCoverageStats(t *testing.T) { stats2, err := GenerateCoverageStats(Config{ Profiles: []string{profileOK}, ExcludePaths: []string{`cover\.go$`}, + RootDir: rootDir, }) assert.NoError(t, err) assert.NotEmpty(t, stats2) // stats2 should have less total statements because cover.go should have been excluded assert.Greater(t, StatsCalcTotal(stats1).Total, StatsCalcTotal(stats2).Total) - // should remove prefix from stats - stats3, err := GenerateCoverageStats(Config{ - Profiles: []string{profileOK}, - LocalPrefix: prefix, - }) - assert.NoError(t, err) - assert.NotEmpty(t, stats3) - assert.Equal(t, StatsCalcTotal(stats1), StatsCalcTotal(stats3)) - assert.NotContains(t, stats3[0].Name, prefix) - assert.NotEqual(t, 100, StatsCalcTotal(stats3).CoveredPercentage()) - // should have total coverage because of second profile - stats4, err := GenerateCoverageStats(Config{ + stats3, err := GenerateCoverageStats(Config{ Profiles: []string{profileOK, profileOKFull}, + RootDir: rootDir, }) assert.NoError(t, err) - assert.NotEmpty(t, stats4) - assert.Equal(t, 100, StatsCalcTotal(stats4).CoveredPercentage()) + assert.NotEmpty(t, stats3) + assert.Equal(t, 100, StatsCalcTotal(stats3).CoveredPercentage()) // should not have `badge/generate.go` in statistics because it has no statements - stats5, err := GenerateCoverageStats(Config{ + stats4, err := GenerateCoverageStats(Config{ Profiles: []string{profileOKNoStatements}, + RootDir: rootDir, }) assert.NoError(t, err) - assert.Len(t, stats5, 1) - assert.NotContains(t, `badge/generate.go`, stats5[0].Name) + assert.Len(t, stats4, 1) + assert.NotContains(t, `badge/generate.go`, stats4[0].Name) } func Test_findFile(t *testing.T) { @@ -95,23 +95,26 @@ func Test_findFile(t *testing.T) { const filename = "pkg/testcoverage/coverage/cover.go" - file, noPrefixName, found := FindFile(prefix+"/"+filename, "") + findFile := FindFileCreator("../../../") + findFileFallbackToImport := FindFileCreator("") + + file, noPrefixName, found := findFile(prefix + "/" + filename) assert.True(t, found) assert.Equal(t, filename, noPrefixName) assert.True(t, strings.HasSuffix(file, path.NormalizeForOS(filename))) - file, noPrefixName, found = FindFile(prefix+"/"+filename, prefix) + file, noPrefixName, found = findFileFallbackToImport(prefix + "/" + filename) assert.True(t, found) assert.Equal(t, filename, noPrefixName) assert.True(t, strings.HasSuffix(file, path.NormalizeForOS(filename))) - _, _, found = FindFile(prefix+"/main1.go", "") + _, _, found = findFile(prefix + "/main1.go") assert.False(t, found) - _, _, found = FindFile("", "") + _, _, found = findFile("") assert.False(t, found) - _, _, found = FindFile(prefix, "") + _, _, found = findFile(prefix) assert.False(t, found) } diff --git a/pkg/testcoverage/coverage/export_test.go b/pkg/testcoverage/coverage/export_test.go index e51bcf27..2fbbdcfb 100644 --- a/pkg/testcoverage/coverage/export_test.go +++ b/pkg/testcoverage/coverage/export_test.go @@ -1,7 +1,7 @@ package coverage var ( - FindFile = findFileCreator() + FindFileCreator = findFileCreator FindAnnotations = findAnnotations FindFuncsAndBlocks = findFuncsAndBlocks ParseProfiles = parseProfiles diff --git a/pkg/testcoverage/coverage/module.go b/pkg/testcoverage/coverage/module.go new file mode 100644 index 00000000..0d2f3cb9 --- /dev/null +++ b/pkg/testcoverage/coverage/module.go @@ -0,0 +1,55 @@ +package coverage + +import ( + "bufio" + "os" + "path/filepath" + "strings" +) + +func findModuleDirective(rootDir string) string { + goModFile := findGoModFile(rootDir) + if goModFile == "" { + return "" + } + + return readModuleDirective(goModFile) +} + +func findGoModFile(rootDir string) string { + var goModFile string + + //nolint:errcheck // error ignored because there is fallback mechanism for finding files + filepath.Walk(rootDir, func(file string, info os.FileInfo, err error) error { + if err != nil { // coverage-ignore + return err + } + + if info.Name() == "go.mod" { + goModFile = file + return filepath.SkipAll + } + + return nil + }) + + return goModFile +} + +func readModuleDirective(filename string) string { + file, err := os.Open(filename) + if err != nil { // coverage-ignore + return "" + } + defer file.Close() + + scanner := bufio.NewScanner(file) + for scanner.Scan() { + line := scanner.Text() + if strings.HasPrefix(line, "module ") { + return strings.TrimSpace(strings.TrimPrefix(line, "module ")) + } + } + + return "" // coverage-ignore +} diff --git a/pkg/testcoverage/report.go b/pkg/testcoverage/report.go index ae3ef13b..4568e251 100644 --- a/pkg/testcoverage/report.go +++ b/pkg/testcoverage/report.go @@ -166,6 +166,10 @@ func ReportForGithubAction(w io.Writer, result AnalyzeResult) { } } +func reportGHWarning(out io.Writer, title, msg string) { // coverage-ignore + fmt.Fprintf(out, "::warning title=%s::%s\n", title, msg) +} + const ( gaOutputFileEnv = "GITHUB_OUTPUT" gaOutputTotalCoverage = "total-coverage"