You've already forked sap-jenkins-library
mirror of
https://github.com/SAP/jenkins-library.git
synced 2025-09-16 09:26:22 +02:00
feat: support golangci-lint v2
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/buildsettings"
|
||||
@@ -178,7 +179,8 @@ func runGolangBuild(config *golangBuildOptions, telemetryData *telemetry.CustomD
|
||||
goPath := os.Getenv("GOPATH")
|
||||
golangciLintDir := filepath.Join(goPath, "bin")
|
||||
|
||||
if err := retrieveGolangciLint(utils, golangciLintDir, config.GolangciLintURL); err != nil {
|
||||
version, err := retrieveGolangciLint(utils, golangciLintDir, config.GolangciLintURL)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -189,7 +191,7 @@ func runGolangBuild(config *golangBuildOptions, telemetryData *telemetry.CustomD
|
||||
"additionalParams": "",
|
||||
}
|
||||
|
||||
if err := runGolangciLint(utils, golangciLintDir, config.FailOnLintingError, lintSettings); err != nil {
|
||||
if err := runGolangciLint(utils, golangciLintDir, version, config.FailOnLintingError, lintSettings); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -417,27 +419,46 @@ func reportGolangTestCoverage(config *golangBuildOptions, utils golangBuildUtils
|
||||
return nil
|
||||
}
|
||||
|
||||
func retrieveGolangciLint(utils golangBuildUtils, golangciLintDir, golangciLintURL string) error {
|
||||
func retrieveGolangciLint(utils golangBuildUtils, golangciLintDir, golangciLintURL string) (string, error) {
|
||||
archiveName := "golangci-lint.tar.gz"
|
||||
err := utils.DownloadFile(golangciLintURL, archiveName, nil, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to download golangci-lint: %w", err)
|
||||
return "", fmt.Errorf("failed to download golangci-lint: %w", err)
|
||||
}
|
||||
|
||||
err = utils.Untar(archiveName, golangciLintDir, 1)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to install golangci-lint: %w", err)
|
||||
return "", fmt.Errorf("failed to install golangci-lint: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
// Extract version from URL using regex to match /v<version>/ pattern
|
||||
version := ""
|
||||
re := regexp.MustCompile(`/v([0-9]+\.[0-9]+(?:\.[0-9]+)?(?:-[a-zA-Z0-9\-\.]*)?)/`)
|
||||
matches := re.FindStringSubmatch(golangciLintURL)
|
||||
if len(matches) > 1 {
|
||||
version = "v" + matches[1]
|
||||
}
|
||||
|
||||
return version, nil
|
||||
}
|
||||
|
||||
func runGolangciLint(utils golangBuildUtils, golangciLintDir string, failOnError bool, lintSettings map[string]string) error {
|
||||
func runGolangciLint(utils golangBuildUtils, golangciLintDir, version string, failOnError bool, lintSettings map[string]string) error {
|
||||
binaryPath := filepath.Join(golangciLintDir, "golangci-lint")
|
||||
|
||||
var outputBuffer bytes.Buffer
|
||||
utils.Stdout(&outputBuffer)
|
||||
err := utils.RunExecutable(binaryPath, "run", "--out-format", lintSettings["reportStyle"])
|
||||
|
||||
var err error
|
||||
// Check if version starts with "v2" to use v2 format
|
||||
if strings.HasPrefix(version, "v2") {
|
||||
// Use v2 format flag
|
||||
outputFlag := fmt.Sprintf("--output.%s.path", lintSettings["reportStyle"])
|
||||
err = utils.RunExecutable(binaryPath, "run", outputFlag, lintSettings["reportOutputPath"])
|
||||
} else {
|
||||
// Use v1 format flag (fallback for v1 or when version detection fails)
|
||||
err = utils.RunExecutable(binaryPath, "run", "--out-format", lintSettings["reportStyle"])
|
||||
}
|
||||
|
||||
if err != nil && utils.GetExitCode() != 1 {
|
||||
return fmt.Errorf("running golangci-lint failed: %w", err)
|
||||
}
|
||||
|
@@ -969,6 +969,7 @@ func TestRunGolangciLint(t *testing.T) {
|
||||
|
||||
tt := []struct {
|
||||
name string
|
||||
version string
|
||||
shouldFailOnCommand map[string]error
|
||||
fileWriteError error
|
||||
exitCode int
|
||||
@@ -977,7 +978,8 @@ func TestRunGolangciLint(t *testing.T) {
|
||||
failOnLintingError bool
|
||||
}{
|
||||
{
|
||||
name: "success",
|
||||
name: "success - v1",
|
||||
version: "v1.55.2",
|
||||
shouldFailOnCommand: map[string]error{},
|
||||
fileWriteError: nil,
|
||||
exitCode: 0,
|
||||
@@ -985,15 +987,44 @@ func TestRunGolangciLint(t *testing.T) {
|
||||
expectedErr: nil,
|
||||
},
|
||||
{
|
||||
name: "failure - failed to run golangci-lint",
|
||||
name: "success - v2",
|
||||
version: "v2.0.1",
|
||||
shouldFailOnCommand: map[string]error{},
|
||||
fileWriteError: nil,
|
||||
exitCode: 0,
|
||||
expectedCommand: []string{binaryPath, "run", "--output.checkstyle.path", lintSettings["reportOutputPath"]},
|
||||
expectedErr: nil,
|
||||
},
|
||||
{
|
||||
name: "success - empty version fallback to v1",
|
||||
version: "",
|
||||
shouldFailOnCommand: map[string]error{},
|
||||
fileWriteError: nil,
|
||||
exitCode: 0,
|
||||
expectedCommand: []string{binaryPath, "run", "--out-format", lintSettings["reportStyle"]},
|
||||
expectedErr: nil,
|
||||
},
|
||||
{
|
||||
name: "failure - v1 failed to run golangci-lint",
|
||||
version: "v1.55.2",
|
||||
shouldFailOnCommand: map[string]error{fmt.Sprintf("%s run --out-format %s", binaryPath, lintSettings["reportStyle"]): fmt.Errorf("err")},
|
||||
fileWriteError: nil,
|
||||
exitCode: 0,
|
||||
expectedCommand: []string{},
|
||||
expectedErr: fmt.Errorf("running golangci-lint failed: err"),
|
||||
},
|
||||
{
|
||||
name: "failure - v2 failed to run golangci-lint",
|
||||
version: "v2.0.1",
|
||||
shouldFailOnCommand: map[string]error{fmt.Sprintf("%s run --output.checkstyle.path %s", binaryPath, lintSettings["reportOutputPath"]): fmt.Errorf("err")},
|
||||
fileWriteError: nil,
|
||||
exitCode: 0,
|
||||
expectedCommand: []string{},
|
||||
expectedErr: fmt.Errorf("running golangci-lint failed: err"),
|
||||
},
|
||||
{
|
||||
name: "failure - failed to write golangci-lint report",
|
||||
version: "v2.0.1",
|
||||
shouldFailOnCommand: map[string]error{},
|
||||
fileWriteError: fmt.Errorf("failed to write golangci-lint report"),
|
||||
exitCode: 0,
|
||||
@@ -1002,6 +1033,7 @@ func TestRunGolangciLint(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "failure - failed with ExitCode == 1",
|
||||
version: "v2.0.1",
|
||||
shouldFailOnCommand: map[string]error{},
|
||||
exitCode: 1,
|
||||
expectedCommand: []string{},
|
||||
@@ -1010,6 +1042,7 @@ func TestRunGolangciLint(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "success - ignore failed with ExitCode == 1",
|
||||
version: "v1.55.2",
|
||||
shouldFailOnCommand: map[string]error{},
|
||||
exitCode: 1,
|
||||
expectedCommand: []string{binaryPath, "run", "--out-format", lintSettings["reportStyle"]},
|
||||
@@ -1026,7 +1059,7 @@ func TestRunGolangciLint(t *testing.T) {
|
||||
utils.ShouldFailOnCommand = test.shouldFailOnCommand
|
||||
utils.FileWriteError = test.fileWriteError
|
||||
utils.ExitCode = test.exitCode
|
||||
err := runGolangciLint(utils, golangciLintDir, test.failOnLintingError, lintSettings)
|
||||
err := runGolangciLint(utils, golangciLintDir, test.version, test.failOnLintingError, lintSettings)
|
||||
|
||||
if test.expectedErr == nil {
|
||||
assert.Equal(t, test.expectedCommand[0], utils.Calls[0].Exec)
|
||||
@@ -1045,13 +1078,15 @@ func TestRetrieveGolangciLint(t *testing.T) {
|
||||
golangciLintDir := filepath.Join(goPath, "bin")
|
||||
|
||||
tt := []struct {
|
||||
name string
|
||||
downloadErr error
|
||||
untarErr error
|
||||
expectedErr error
|
||||
name string
|
||||
downloadErr error
|
||||
untarErr error
|
||||
expectedErr error
|
||||
expectedVersion string
|
||||
}{
|
||||
{
|
||||
name: "success",
|
||||
name: "success",
|
||||
expectedVersion: "v1.50.1",
|
||||
},
|
||||
{
|
||||
name: "failure - failed to download golangci-lint",
|
||||
@@ -1076,11 +1111,13 @@ func TestRetrieveGolangciLint(t *testing.T) {
|
||||
config := golangBuildOptions{
|
||||
GolangciLintURL: "https://github.com/golangci/golangci-lint/releases/download/v1.50.1/golangci-lint-1.50.0-darwin-amd64.tar.gz",
|
||||
}
|
||||
err := retrieveGolangciLint(utils, golangciLintDir, config.GolangciLintURL)
|
||||
version, err := retrieveGolangciLint(utils, golangciLintDir, config.GolangciLintURL)
|
||||
|
||||
if test.expectedErr != nil {
|
||||
assert.EqualError(t, err, test.expectedErr.Error())
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, test.expectedVersion, version)
|
||||
b, err := utils.ReadFile("golangci-lint.tar.gz")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("content"), b)
|
||||
@@ -1092,6 +1129,64 @@ func TestRetrieveGolangciLint(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRetrieveGolangciLintVersionDetection(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
goPath := os.Getenv("GOPATH")
|
||||
golangciLintDir := filepath.Join(goPath, "bin")
|
||||
|
||||
tt := []struct {
|
||||
name string
|
||||
golangciLintURL string
|
||||
expectedVersion string
|
||||
}{
|
||||
{
|
||||
name: "success - v1.55.2 official GitHub release",
|
||||
golangciLintURL: "https://github.com/golangci/golangci-lint/releases/download/v1.55.2/golangci-lint-1.55.2-darwin-amd64.tar.gz",
|
||||
expectedVersion: "v1.55.2",
|
||||
},
|
||||
{
|
||||
name: "success - v2.0.1 official GitHub release",
|
||||
golangciLintURL: "https://github.com/golangci/golangci-lint/releases/download/v2.0.1/golangci-lint-2.0.1-darwin-amd64.tar.gz",
|
||||
expectedVersion: "v2.0.1",
|
||||
},
|
||||
{
|
||||
name: "success - v2.1.0 official GitHub release",
|
||||
golangciLintURL: "https://github.com/golangci/golangci-lint/releases/download/v2.1.0/golangci-lint-2.1.0-linux-amd64.tar.gz",
|
||||
expectedVersion: "v2.1.0",
|
||||
},
|
||||
{
|
||||
name: "edge case - non-GitHub URL",
|
||||
golangciLintURL: "https://example.com/golangci-lint.tar.gz",
|
||||
expectedVersion: "",
|
||||
},
|
||||
{
|
||||
name: "edge case - GitHub but not releases URL",
|
||||
golangciLintURL: "https://github.com/golangci/golangci-lint/archive/main.tar.gz",
|
||||
expectedVersion: "",
|
||||
},
|
||||
{
|
||||
name: "edge case - malformed GitHub releases URL",
|
||||
golangciLintURL: "https://github.com/golangci/golangci-lint/releases/download/main/golangci-lint.tar.gz",
|
||||
expectedVersion: "",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tt {
|
||||
test := test
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
utils := newGolangBuildTestsUtils()
|
||||
utils.untarFileNames = []string{"golangci-lint"}
|
||||
|
||||
version, err := retrieveGolangciLint(utils, golangciLintDir, test.golangciLintURL)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, test.expectedVersion, version)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_gitConfigurationForPrivateModules(t *testing.T) {
|
||||
type args struct {
|
||||
privateMod string
|
||||
|
Reference in New Issue
Block a user