1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-10-30 23:57:50 +02:00

golangBuild: update the way of installing golangci-lint (#4145)

* Add the OS agnostic way of installing golangci-lint

* Fix

* Clean up

* Modify unit tests

* Rename downloaded archive

* Refactor

* Expose golangci-lint url as a parameter

* Clean up

* Rename parameter

* Update mock

* Fix golangci-lint version
This commit is contained in:
Vyacheslav Starostin
2022-12-07 22:13:44 +06:00
committed by GitHub
parent 74a3133f35
commit 6a9ade78ff
4 changed files with 81 additions and 58 deletions

View File

@@ -35,8 +35,6 @@ const (
golangTestsumPackage = "gotest.tools/gotestsum@latest"
golangCycloneDXPackage = "github.com/CycloneDX/cyclonedx-gomod/cmd/cyclonedx-gomod@latest"
sbomFilename = "bom-golang.xml"
golangciLintURL = "https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh"
golangciLintVersion = "latest"
)
type golangBuildUtils interface {
@@ -49,6 +47,7 @@ type golangBuildUtils interface {
getDockerImageValue(stepName string) (string, error)
GetExitCode() int
DownloadFile(url, filename string, header http.Header, cookies []*http.Cookie) error
Untar(src string, dest string, stripComponentLevel int) error
// Add more methods here, or embed additional interfaces, or remove/replace as required.
// The golangBuildUtils interface should be descriptive of your runtime dependencies,
@@ -78,6 +77,10 @@ func (g *golangBuildUtilsBundle) getDockerImageValue(stepName string) (string, e
return GetDockerImageValue(stepName)
}
func (g *golangBuildUtilsBundle) Untar(src string, dest string, stripComponentLevel int) error {
return piperutils.Untar(src, dest, stripComponentLevel)
}
func newGolangBuildUtils(config golangBuildOptions) golangBuildUtils {
httpClientOptions := piperhttp.ClientOptions{}
@@ -175,7 +178,7 @@ func runGolangBuild(config *golangBuildOptions, telemetryData *telemetry.CustomD
goPath := os.Getenv("GOPATH")
golangciLintDir := filepath.Join(goPath, "bin")
if err := retrieveGolangciLint(utils, golangciLintDir); err != nil {
if err := retrieveGolangciLint(utils, golangciLintDir, config.GolangciLintURL); err != nil {
return err
}
@@ -433,19 +436,14 @@ func reportGolangTestCoverage(config *golangBuildOptions, utils golangBuildUtils
return nil
}
func retrieveGolangciLint(utils golangBuildUtils, golangciLintDir string) error {
installationScript := "./install.sh"
err := utils.DownloadFile(golangciLintURL, installationScript, nil, nil)
func retrieveGolangciLint(utils golangBuildUtils, golangciLintDir, golangciLintURL 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)
}
err = utils.Chmod(installationScript, 0777)
if err != nil {
return err
}
err = utils.RunExecutable(installationScript, "-b", golangciLintDir, golangciLintVersion)
err = utils.Untar(archiveName, golangciLintDir, 1)
if err != nil {
return fmt.Errorf("failed to install golangci-lint: %w", err)
}
@@ -455,6 +453,7 @@ func retrieveGolangciLint(utils golangBuildUtils, golangciLintDir string) error
func runGolangciLint(utils golangBuildUtils, golangciLintDir string, 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"])

View File

@@ -46,6 +46,7 @@ type golangBuildOptions struct {
PrivateModules string `json:"privateModules,omitempty"`
PrivateModulesGitToken string `json:"privateModulesGitToken,omitempty"`
ArtifactVersion string `json:"artifactVersion,omitempty"`
GolangciLintURL string `json:"golangciLintUrl,omitempty"`
}
type golangBuildCommonPipelineEnvironment struct {
@@ -245,6 +246,7 @@ func addGolangBuildFlags(cmd *cobra.Command, stepConfig *golangBuildOptions) {
cmd.Flags().StringVar(&stepConfig.PrivateModules, "privateModules", os.Getenv("PIPER_privateModules"), "Tells go which modules shall be considered to be private (by setting [GOPRIVATE](https://pkg.go.dev/cmd/go#hdr-Configuration_for_downloading_non_public_code)).")
cmd.Flags().StringVar(&stepConfig.PrivateModulesGitToken, "privateModulesGitToken", os.Getenv("PIPER_privateModulesGitToken"), "GitHub personal access token as per https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line.")
cmd.Flags().StringVar(&stepConfig.ArtifactVersion, "artifactVersion", os.Getenv("PIPER_artifactVersion"), "Version of the artifact to be built.")
cmd.Flags().StringVar(&stepConfig.GolangciLintURL, "golangciLintUrl", `https://github.com/golangci/golangci-lint/releases/download/v1.50.1/golangci-lint-1.50.1-linux-amd64.tar.gz`, "Specifies the download url of the Golangci-Lint Linux amd64 tar binary file. This can be found at https://github.com/golangci/golangci-lint/releases.")
cmd.MarkFlagRequired("targetArchitectures")
}
@@ -531,6 +533,15 @@ func golangBuildMetadata() config.StepData {
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_artifactVersion"),
},
{
Name: "golangciLintUrl",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
Default: `https://github.com/golangci/golangci-lint/releases/download/v1.50.1/golangci-lint-1.50.1-linux-amd64.tar.gz`,
},
},
},
Containers: []config.Container{

View File

@@ -27,9 +27,11 @@ type golangBuildMockUtils struct {
returnFileUploadStatus int // expected to be set upfront
returnFileUploadError error // expected to be set upfront
returnFileDownloadError error // expected to be set upfront
returnFileUntarError error // expected to be set upfront
clientOptions []piperhttp.ClientOptions // set by mock
fileUploads map[string]string // set by mock
clientOptions []piperhttp.ClientOptions // set by mock
fileUploads map[string]string // set by mock
untarFileNames []string
}
func (g *golangBuildMockUtils) DownloadFile(url, filename string, header http.Header, cookies []*http.Cookie) error {
@@ -74,6 +76,16 @@ func (g *golangBuildMockUtils) getDockerImageValue(stepName string) (string, err
return "golang:latest", nil
}
func (g *golangBuildMockUtils) Untar(src string, dest string, stripComponentLevel int) error {
if g.returnFileUntarError != nil {
return g.returnFileUntarError
}
for _, file := range g.untarFileNames {
g.AddFile(filepath.Join(dest, file), []byte("test content"))
}
return nil
}
func newGolangBuildTestsUtils() *golangBuildMockUtils {
utils := golangBuildMockUtils{
ExecMockRunner: &mock.ExecMockRunner{},
@@ -290,15 +302,12 @@ go 1.17`
err := runGolangBuild(&config, &telemetry, utils, &cpe)
assert.NoError(t, err)
b, err := utils.FileRead("install.sh")
b, err := utils.FileRead("golangci-lint.tar.gz")
assert.NoError(t, err)
assert.Equal(t, []byte("content"), b)
assert.Equal(t, "./install.sh", utils.Calls[0].Exec)
assert.Equal(t, []string{"-b", golangciLintDir, golangciLintVersion}, utils.Calls[0].Params)
assert.Equal(t, binaryPath, utils.Calls[1].Exec)
assert.Equal(t, []string{"run", "--out-format", "checkstyle"}, utils.Calls[1].Params)
assert.Equal(t, binaryPath, utils.Calls[0].Exec)
assert.Equal(t, []string{"run", "--out-format", "checkstyle"}, utils.Calls[0].Params)
})
t.Run("failure - install pre-requisites for testing", func(t *testing.T) {
@@ -476,20 +485,16 @@ go 1.17`
})
t.Run("failure - RunLint: retrieveGolangciLint failed", func(t *testing.T) {
goPath := os.Getenv("GOPATH")
golangciLintDir := filepath.Join(goPath, "bin")
config := golangBuildOptions{
RunLint: true,
}
utils := newGolangBuildTestsUtils()
utils.AddFile("go.mod", []byte(modTestFile))
utils.ShouldFailOnCommand = map[string]error{
fmt.Sprintf("./install.sh -b %s %s", golangciLintDir, golangciLintVersion): fmt.Errorf("installation err"),
}
utils.returnFileDownloadError = fmt.Errorf("downloading error")
telemetry := telemetry.CustomData{}
err := runGolangBuild(&config, &telemetry, utils, &cpe)
assert.EqualError(t, err, "failed to install golangci-lint: installation err")
assert.EqualError(t, err, "failed to download golangci-lint: downloading error")
})
t.Run("failure - RunLint: runGolangciLint failed", func(t *testing.T) {
@@ -1023,6 +1028,7 @@ func TestRunGolangciLint(t *testing.T) {
goPath := os.Getenv("GOPATH")
golangciLintDir := filepath.Join(goPath, "bin")
binaryPath := filepath.Join(golangciLintDir, "golangci-lint")
lintSettings := map[string]string{
"reportStyle": "checkstyle",
"reportOutputPath": "golangci-lint-report.xml",
@@ -1070,8 +1076,8 @@ func TestRunGolangciLint(t *testing.T) {
},
}
for i, test := range tt {
i, test := i, test
for _, test := range tt {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
utils := newGolangBuildTestsUtils()
@@ -1081,8 +1087,8 @@ func TestRunGolangciLint(t *testing.T) {
err := runGolangciLint(utils, golangciLintDir, lintSettings)
if test.expectedErr == nil {
assert.Equal(t, test.expectedCommand[0], utils.Calls[i].Exec)
assert.Equal(t, test.expectedCommand[1:], utils.Calls[i].Params)
assert.Equal(t, test.expectedCommand[0], utils.Calls[0].Exec)
assert.Equal(t, test.expectedCommand[1:], utils.Calls[0].Params)
} else {
assert.EqualError(t, err, test.expectedErr.Error())
}
@@ -1097,48 +1103,48 @@ func TestRetrieveGolangciLint(t *testing.T) {
golangciLintDir := filepath.Join(goPath, "bin")
tt := []struct {
name string
shouldFailOnCommand map[string]error
downloadErr error
expectedCommand []string
expectedErr error
name string
downloadErr error
untarErr error
expectedErr error
}{
{
name: "success",
shouldFailOnCommand: map[string]error{},
downloadErr: nil,
expectedCommand: []string{"./install.sh", "-b", golangciLintDir, golangciLintVersion},
expectedErr: nil,
name: "success",
},
{
name: "failure - failed to download golangci-lint",
shouldFailOnCommand: map[string]error{},
downloadErr: fmt.Errorf("download err"),
expectedCommand: []string{},
expectedErr: fmt.Errorf("failed to download golangci-lint: download err"),
name: "failure - failed to download golangci-lint",
downloadErr: fmt.Errorf("download err"),
expectedErr: fmt.Errorf("failed to download golangci-lint: download err"),
},
{
name: "failure - failed to install golangci-lint with sh error",
shouldFailOnCommand: map[string]error{fmt.Sprintf("./install.sh -b %s %s", golangciLintDir, golangciLintVersion): fmt.Errorf("installation err")},
expectedCommand: []string{},
expectedErr: fmt.Errorf("failed to install golangci-lint: installation err"),
name: "failure - failed to install golangci-lint",
untarErr: fmt.Errorf("retrieve archive err"),
expectedErr: fmt.Errorf("failed to install golangci-lint: retrieve archive err"),
},
}
for i, test := range tt {
i, test := i, test
for _, test := range tt {
test := test
t.Run(test.name, func(t *testing.T) {
t.Parallel()
utils := newGolangBuildTestsUtils()
utils.ShouldFailOnCommand = test.shouldFailOnCommand
utils.returnFileDownloadError = test.downloadErr
err := retrieveGolangciLint(utils, golangciLintDir)
utils.returnFileUntarError = test.untarErr
utils.untarFileNames = []string{"golangci-lint"}
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)
if test.expectedErr == nil {
assert.Equal(t, test.expectedCommand[0], utils.Calls[i].Exec)
assert.Equal(t, test.expectedCommand[1:], utils.Calls[i].Params)
} else {
if test.expectedErr != nil {
assert.EqualError(t, err, test.expectedErr.Error())
} else {
b, err := utils.ReadFile("golangci-lint.tar.gz")
assert.NoError(t, err)
assert.Equal(t, []byte("content"), b)
b, err = utils.ReadFile(filepath.Join(golangciLintDir, "golangci-lint"))
assert.NoError(t, err)
assert.Equal(t, []byte("test content"), b)
}
})
}

View File

@@ -241,6 +241,13 @@ spec:
resourceRef:
- name: commonPipelineEnvironment
param: artifactVersion
- name: golangciLintUrl
type: string
description: Specifies the download url of the Golangci-Lint Linux amd64 tar binary file. This can be found at https://github.com/golangci/golangci-lint/releases.
scope:
- PARAMETERS
- STEPS
default: "https://github.com/golangci/golangci-lint/releases/download/v1.50.1/golangci-lint-1.50.1-linux-amd64.tar.gz"
outputs:
resources:
- name: commonPipelineEnvironment