diff --git a/.editorconfig b/.editorconfig index 0aa9c24746..fb326c32c8 100644 --- a/.editorconfig +++ b/.editorconfig @@ -24,4 +24,3 @@ indent_style = none indent_size = none [{go.mod,go.sum,*.go,*.golden}] indent_style = tab -indent_size = 8 diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 10febb1bb3..132997c45b 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -23,7 +23,7 @@ jobs: - uses: actions/setup-go@v5 with: - go-version: '1.22.4' + go-version: '1.23.4' - name: Install Groovy run: sudo apt-get update && sudo apt-get install groovy -y diff --git a/.github/workflows/update-go-dependencies.yml b/.github/workflows/update-go-dependencies.yml index fe7f350d3a..0157cbb697 100644 --- a/.github/workflows/update-go-dependencies.yml +++ b/.github/workflows/update-go-dependencies.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: - go-version: '1.22.4' + go-version: '1.23.4' - name: Perform update run: | git checkout -B gh-action-update-golang-dependencies diff --git a/.github/workflows/upload-go-master.yml b/.github/workflows/upload-go-master.yml index 9f88021517..b56c1f8771 100644 --- a/.github/workflows/upload-go-master.yml +++ b/.github/workflows/upload-go-master.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: - go-version: '1.22.4' + go-version: '1.23.4' - env: CGO_ENABLED: 0 run: | diff --git a/.github/workflows/verify-go.yml b/.github/workflows/verify-go.yml index 8226c83165..715e87f990 100644 --- a/.github/workflows/verify-go.yml +++ b/.github/workflows/verify-go.yml @@ -15,7 +15,7 @@ jobs: - uses: styfle/cancel-workflow-action@0.11.0 - uses: actions/setup-go@v5 with: - go-version: '1.22.4' + go-version: '1.23.4' - name: Cache Golang Packages uses: actions/cache@v3 with: @@ -43,7 +43,7 @@ jobs: steps: - uses: actions/setup-go@v5 with: - go-version: '1.22.4' + go-version: '1.23.4' - name: Cache Golang Packages uses: actions/cache@v3 with: @@ -63,7 +63,7 @@ jobs: steps: - uses: actions/setup-go@v5 with: - go-version: '1.22.4' + go-version: '1.23.4' - name: checkout uses: actions/checkout@v4 with: @@ -78,7 +78,7 @@ jobs: steps: - uses: actions/setup-go@v5 with: - go-version: '1.22.4' + go-version: '1.23.4' - name: Cache Golang Packages uses: actions/cache@v3 with: @@ -98,7 +98,7 @@ jobs: steps: - uses: actions/setup-go@v5 with: - go-version: '1.22.4' + go-version: '1.23.4' - name: Cache Golang Packages uses: actions/cache@v3 with: diff --git a/Dockerfile b/Dockerfile index 7a44ad5c56..1b6639dcb8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.22.4 AS build-env +FROM golang:1.23.4 AS build-env COPY . /build WORKDIR /build diff --git a/cmd/abapEnvironmentAssemblePackages.go b/cmd/abapEnvironmentAssemblePackages.go index 92df409019..4241637e8a 100644 --- a/cmd/abapEnvironmentAssemblePackages.go +++ b/cmd/abapEnvironmentAssemblePackages.go @@ -281,6 +281,10 @@ func checkIfFailedAndPrintLogs(builds []buildWithRepository) error { log.Entry().Errorf("Assembly of %s failed", builds[i].repo.PackageName) buildFailed = true } + if builds[i].build.ResultState == abapbuild.Erroneous { + log.Entry().Errorf("Assembly of %s revealed errors", builds[i].repo.PackageName) + buildFailed = true + } if builds[i].build.BuildID != "" { if err := builds[i].build.PrintLogs(); err != nil { return err diff --git a/cmd/abapEnvironmentCheckoutBranch_generated.go b/cmd/abapEnvironmentCheckoutBranch_generated.go index 342b11225e..3b8c066403 100644 --- a/cmd/abapEnvironmentCheckoutBranch_generated.go +++ b/cmd/abapEnvironmentCheckoutBranch_generated.go @@ -260,7 +260,7 @@ func abapEnvironmentCheckoutBranchMetadata() config.StepData { { Name: "logOutput", ResourceRef: []config.ResourceReference{}, - Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, diff --git a/cmd/abapEnvironmentCloneGitRepo_generated.go b/cmd/abapEnvironmentCloneGitRepo_generated.go index e1da421535..c285dbff77 100644 --- a/cmd/abapEnvironmentCloneGitRepo_generated.go +++ b/cmd/abapEnvironmentCloneGitRepo_generated.go @@ -310,7 +310,7 @@ func abapEnvironmentCloneGitRepoMetadata() config.StepData { { Name: "logOutput", ResourceRef: []config.ResourceReference{}, - Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, diff --git a/cmd/abapEnvironmentPullGitRepo_generated.go b/cmd/abapEnvironmentPullGitRepo_generated.go index d763185c8d..355e393bfd 100644 --- a/cmd/abapEnvironmentPullGitRepo_generated.go +++ b/cmd/abapEnvironmentPullGitRepo_generated.go @@ -273,7 +273,7 @@ func abapEnvironmentPullGitRepoMetadata() config.StepData { { Name: "logOutput", ResourceRef: []config.ResourceReference{}, - Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, diff --git a/cmd/checkmarxOneExecuteScan.go b/cmd/checkmarxOneExecuteScan.go index c457372c65..4eec98baf6 100644 --- a/cmd/checkmarxOneExecuteScan.go +++ b/cmd/checkmarxOneExecuteScan.go @@ -8,6 +8,7 @@ import ( "io" "maps" "math" + "net/url" "os" "path/filepath" "regexp" @@ -803,7 +804,7 @@ func (c *checkmarxOneExecuteScanHelper) getDetailedResults(scan *checkmarxOne.Sc } resultMap["Preset"] = scanmeta.PresetName - resultMap["DeepLink"] = fmt.Sprintf("%v/projects/%v/overview?branch=%v", c.config.ServerURL, c.Project.ProjectID, scan.Branch) + resultMap["DeepLink"] = fmt.Sprintf("%v/projects/%v/overview?branch=%v", c.config.ServerURL, c.Project.ProjectID, url.QueryEscape(scan.Branch)) resultMap["ReportCreationTime"] = time.Now().String() resultMap["High"] = map[string]int{} resultMap["Medium"] = map[string]int{} diff --git a/cmd/cloudFoundryDeploy.go b/cmd/cloudFoundryDeploy.go index 79a4e19aa2..6e9ac13662 100644 --- a/cmd/cloudFoundryDeploy.go +++ b/cmd/cloudFoundryDeploy.go @@ -6,6 +6,7 @@ import ( "io" "os" "regexp" + "slices" "sort" "strings" "time" @@ -414,7 +415,7 @@ func deployMta(config *cloudFoundryDeployOptions, mtarFilePath string, command c deployCommand = "bg-deploy" const noConfirmFlag = "--no-confirm" - if !piperutils.ContainsString(deployParams, noConfirmFlag) { + if !slices.Contains(deployParams, noConfirmFlag) { deployParams = append(deployParams, noConfirmFlag) } } diff --git a/cmd/cloudFoundryDeploy_generated.go b/cmd/cloudFoundryDeploy_generated.go index 51c4c51d7c..3c5b774990 100644 --- a/cmd/cloudFoundryDeploy_generated.go +++ b/cmd/cloudFoundryDeploy_generated.go @@ -565,7 +565,7 @@ func cloudFoundryDeployMetadata() config.StepData { }, }, Containers: []config.Container{ - {Name: "cfDeploy", Image: "ppiper/cf-cli:latest"}, + {Name: "cfDeploy", Image: "ppiper/cf-cli:latest", Options: []config.Option{{Name: "--ulimit", Value: "stack=67108864:67108864"}, {Name: "--ulimit", Value: "nofile=65536:65536"}}}, }, Outputs: config.StepOutputs{ Resources: []config.StepResources{ diff --git a/cmd/cnbBuild.go b/cmd/cnbBuild.go index 1bc012df79..3fea419bf9 100644 --- a/cmd/cnbBuild.go +++ b/cmd/cnbBuild.go @@ -6,6 +6,7 @@ import ( "os" "path" "path/filepath" + "slices" "github.com/SAP/jenkins-library/pkg/buildpacks" "github.com/SAP/jenkins-library/pkg/buildsettings" @@ -594,7 +595,7 @@ func runCnbBuild(config *cnbBuildOptions, telemetry *buildpacks.Telemetry, image } for _, tag := range config.AdditionalTags { target := fmt.Sprintf("%s:%s", containerImage, tag) - if !piperutils.ContainsString(creatorArgs, target) { + if !slices.Contains(creatorArgs, target) { creatorArgs = append(creatorArgs, "-tag", target) } } diff --git a/cmd/cnbBuild_generated.go b/cmd/cnbBuild_generated.go index 499ea506b2..8982c39009 100644 --- a/cmd/cnbBuild_generated.go +++ b/cmd/cnbBuild_generated.go @@ -265,7 +265,7 @@ func addCnbBuildFlags(cmd *cobra.Command, stepConfig *cnbBuildOptions) { cmd.Flags().StringVar(&stepConfig.Path, "path", os.Getenv("PIPER_path"), "Glob that should either point to a directory with your sources or one artifact in zip format.\nThis property determines the input to the buildpack.\n") cmd.Flags().StringVar(&stepConfig.ProjectDescriptor, "projectDescriptor", `project.toml`, "Relative path to the project.toml file.\nSee [buildpacks.io](https://buildpacks.io/docs/reference/config/project-descriptor/) for the reference.\nParameters passed to the cnbBuild step will take precedence over the parameters set in the project.toml file, except the `env` block.\nEnvironment variables declared in a project descriptor file, will be merged with the `buildEnvVars` property, with the `buildEnvVars` having a precedence.\n\n*Note*: The project descriptor path should be relative to what is set in the [path](#path) property. If the `path` property is pointing to a zip archive (e.g. jar file), project descriptor path will be relative to the root of the workspace.\n\n*Note*: Inline buildpacks (see [specification](https://buildpacks.io/docs/reference/config/project-descriptor/#build-_table-optional_)) are not supported yet.\n") cmd.Flags().StringVar(&stepConfig.DockerConfigJSON, "dockerConfigJSON", os.Getenv("PIPER_dockerConfigJSON"), "Path to the file `.docker/config.json` - this is typically provided by your CI/CD system. You can find more details about the Docker credentials in the [Docker documentation](https://docs.docker.com/engine/reference/commandline/login/).") - cmd.Flags().StringVar(&stepConfig.DockerConfigJSONCPE, "dockerConfigJSONCPE", os.Getenv("PIPER_dockerConfigJSONCPE"), "This property is intended only for reading the `dockerConfigJSON` from the Common Pipeline Environment. If you want to provide your own credentials, please refer to the [dockerConfigJSON](#dockerConfigJSON) property. If both properties are set, the config files will be merged, with the [dockerConfigJSON](#dockerConfigJSON) having higher priority.") + cmd.Flags().StringVar(&stepConfig.DockerConfigJSONCPE, "dockerConfigJSONCPE", os.Getenv("PIPER_dockerConfigJSONCPE"), "This property is intended only for reading the `dockerConfigJSON` from the Common Pipeline Environment. If you want to provide your own credentials, please refer to the [dockerConfigJSON](#dockerconfigjson) property. If both properties are set, the config files will be merged, with the [dockerConfigJSON](#dockerconfigjson) having higher priority.") cmd.Flags().StringSliceVar(&stepConfig.CustomTLSCertificateLinks, "customTlsCertificateLinks", []string{}, "List containing download links of custom TLS certificates. This is required to ensure trusted connections to registries with custom certificates.") cmd.Flags().StringSliceVar(&stepConfig.AdditionalTags, "additionalTags", []string{}, "List of tags which will be pushed to the registry (additionally to the provided `containerImageTag`), e.g. \"latest\".") diff --git a/cmd/detectExecuteScan.go b/cmd/detectExecuteScan.go index 5fc5561a10..9dd948f7a8 100644 --- a/cmd/detectExecuteScan.go +++ b/cmd/detectExecuteScan.go @@ -7,6 +7,7 @@ import ( "io" "net/http" "path/filepath" + "slices" "sort" "strconv" "strings" @@ -467,7 +468,7 @@ func addDetectArgs(args []string, config detectExecuteScanOptions, utils detectU handleExcludedDirectories(&args, &config) if config.Unmap { - if !piperutils.ContainsString(config.ScanProperties, "--detect.project.codelocation.unmap=true") { + if !slices.Contains(config.ScanProperties, "--detect.project.codelocation.unmap=true") { args = append(args, "--detect.project.codelocation.unmap=true") } config.ScanProperties, _ = piperutils.RemoveAll(config.ScanProperties, "--detect.project.codelocation.unmap=false") diff --git a/cmd/fortifyExecuteScan.go b/cmd/fortifyExecuteScan.go index f2110fa552..ac8898a728 100644 --- a/cmd/fortifyExecuteScan.go +++ b/cmd/fortifyExecuteScan.go @@ -11,6 +11,7 @@ import ( "path/filepath" "regexp" "runtime" + "slices" "strconv" "strings" "time" @@ -211,7 +212,7 @@ func runFortifyScan(ctx context.Context, config fortifyExecuteScanOptions, sys f prID, prAuthor := determinePullRequestMerge(config) if prID != "0" { log.Entry().Debugf("Determined PR ID '%v' for merge check", prID) - if len(prAuthor) > 0 && !piperutils.ContainsString(config.Assignees, prAuthor) { + if len(prAuthor) > 0 && !slices.Contains(config.Assignees, prAuthor) { log.Entry().Debugf("Determined PR Author '%v' for result assignment", prAuthor) config.Assignees = append(config.Assignees, prAuthor) } else { diff --git a/cmd/fortifyExecuteScan_generated.go b/cmd/fortifyExecuteScan_generated.go index 59e8b510aa..b92d24b04e 100644 --- a/cmd/fortifyExecuteScan_generated.go +++ b/cmd/fortifyExecuteScan_generated.go @@ -349,7 +349,7 @@ func addFortifyExecuteScanFlags(cmd *cobra.Command, stepConfig *fortifyExecuteSc cmd.Flags().StringVar(&stepConfig.PythonRequirementsInstallSuffix, "pythonRequirementsInstallSuffix", os.Getenv("PIPER_pythonRequirementsInstallSuffix"), "The suffix for the command used to install the requirements file in `buildTool: 'pip'` to populate the build environment with the necessary dependencies") cmd.Flags().StringVar(&stepConfig.PythonVersion, "pythonVersion", `python3`, "Python version to be used in `buildTool: 'pip'`") cmd.Flags().BoolVar(&stepConfig.UploadResults, "uploadResults", true, "Whether results shall be uploaded or not") - cmd.Flags().StringVar(&stepConfig.Version, "version", os.Getenv("PIPER_version"), "Version used in conjunction with [`versioningModel`](#versioningModel) to identify the Fortify project to be created and used for results aggregation.") + cmd.Flags().StringVar(&stepConfig.Version, "version", os.Getenv("PIPER_version"), "Version used in conjunction with [`versioningModel`](#versioningmodel) to identify the Fortify project to be created and used for results aggregation.") cmd.Flags().StringVar(&stepConfig.BuildDescriptorFile, "buildDescriptorFile", `./pom.xml`, "Path to the build descriptor file addressing the module/folder to be scanned.") cmd.Flags().StringVar(&stepConfig.CommitID, "commitId", os.Getenv("PIPER_commitId"), "Set the Git commit ID for identifying artifacts throughout the scan.") cmd.Flags().StringVar(&stepConfig.CommitMessage, "commitMessage", os.Getenv("PIPER_commitMessage"), "Set the Git commit message for identifying pull request merges throughout the scan.") diff --git a/cmd/fortifyExecuteScan_test.go b/cmd/fortifyExecuteScan_test.go index 3f47ec3a9d..b5933e46c7 100644 --- a/cmd/fortifyExecuteScan_test.go +++ b/cmd/fortifyExecuteScan_test.go @@ -13,6 +13,7 @@ import ( "os" "path/filepath" "reflect" + "slices" "strings" "testing" "time" @@ -21,7 +22,6 @@ import ( "github.com/SAP/jenkins-library/pkg/fortify" "github.com/SAP/jenkins-library/pkg/log" - "github.com/SAP/jenkins-library/pkg/piperutils" "github.com/SAP/jenkins-library/pkg/versioning" "github.com/google/go-github/v45/github" @@ -421,7 +421,7 @@ func (er *execRunnerMock) Stderr(err io.Writer) { func (er *execRunnerMock) RunExecutable(e string, p ...string) error { er.numExecutions++ er.currentExecution().executable = e - if len(p) > 0 && piperutils.ContainsString(p, "--failTranslate") { + if len(p) > 0 && slices.Contains(p, "--failTranslate") { return errors.New("Translate failed") } er.currentExecution().parameters = p diff --git a/cmd/getConfig.go b/cmd/getConfig.go index 0712f22e84..f8f54af0eb 100644 --- a/cmd/getConfig.go +++ b/cmd/getConfig.go @@ -138,6 +138,9 @@ func GetStageConfig() (config.StepConfig, error) { defaultConfig := []io.ReadCloser{} for _, f := range GeneralConfig.DefaultConfig { + if configOptions.OpenFile == nil { + return stepConfig, errors.New("config: open file function not set") + } fc, err := configOptions.OpenFile(f, GeneralConfig.GitHubAccessTokens) // only create error for non-default values if err != nil && f != ".pipeline/defaults.yaml" { diff --git a/cmd/kanikoExecute.go b/cmd/kanikoExecute.go index 1937dd66af..3eaf4c9180 100644 --- a/cmd/kanikoExecute.go +++ b/cmd/kanikoExecute.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "slices" "strings" "github.com/mitchellh/mapstructure" @@ -287,7 +288,7 @@ func runKanikoExecute(config *kanikoExecuteOptions, telemetryData *telemetry.Cus } return nil - case piperutils.ContainsString(config.BuildOptions, "--destination"): + case slices.Contains(config.BuildOptions, "--destination"): log.Entry().Infof("Running Kaniko build with destination defined via buildOptions: %v", config.BuildOptions) for i, o := range config.BuildOptions { diff --git a/cmd/mavenBuild.go b/cmd/mavenBuild.go index 5f8a4b0a96..3ce7d881b8 100644 --- a/cmd/mavenBuild.go +++ b/cmd/mavenBuild.go @@ -23,7 +23,7 @@ import ( const ( mvnBomFilename = "bom-maven" - mvnSimpleBomFilename = "bom-simple" + mvnSimpleBomFilename = "simple-bom-maven" ) func mavenBuild(config mavenBuildOptions, telemetryData *telemetry.CustomData, commonPipelineEnvironment *mavenBuildCommonPipelineEnvironment) { @@ -238,7 +238,9 @@ func runMavenBuild(config *mavenBuildOptions, _ *telemetry.CustomData, utils mav func createBuildArtifactsMetadata(config *mavenBuildOptions, commonPipelineEnvironment *mavenBuildCommonPipelineEnvironment) (error, bool) { fileUtils := &piperutils.Files{} buildCoordinates := []versioning.Coordinates{} - options := versioning.Options{} + options := versioning.Options{ + ProjectSettingsFile: config.ProjectSettingsFile, + } var utils versioning.Utils matches, _ := fileUtils.Glob("**/pom.xml") diff --git a/cmd/metadata_generated.go b/cmd/metadata_generated.go index 56cebc07d4..50b0d6dadb 100644 --- a/cmd/metadata_generated.go +++ b/cmd/metadata_generated.go @@ -103,6 +103,7 @@ func GetAllStepMetadata() map[string]config.StepData { "nexusUpload": nexusUploadMetadata(), "npmExecuteLint": npmExecuteLintMetadata(), "npmExecuteScripts": npmExecuteScriptsMetadata(), + "npmExecuteTests": npmExecuteTestsMetadata(), "pipelineCreateScanSummary": pipelineCreateScanSummaryMetadata(), "protecodeExecuteScan": protecodeExecuteScanMetadata(), "pythonBuild": pythonBuildMetadata(), diff --git a/cmd/mtaBuild_test.go b/cmd/mtaBuild_test.go index 273ff3af91..e784fc1d5d 100644 --- a/cmd/mtaBuild_test.go +++ b/cmd/mtaBuild_test.go @@ -87,6 +87,7 @@ func TestMtaBuild(t *testing.T) { SetConfigOptions(ConfigCommandOptions{ OpenFile: config.OpenPiperFile, }) + t.Run("Application name not set", func(t *testing.T) { utilsMock := newMtaBuildTestUtilsBundle() options := mtaBuildOptions{} diff --git a/cmd/newmanExecute_test.go b/cmd/newmanExecute_test.go index f209005dbf..ffb7429883 100644 --- a/cmd/newmanExecute_test.go +++ b/cmd/newmanExecute_test.go @@ -6,10 +6,10 @@ package cmd import ( "os" "path/filepath" + "slices" "strings" "testing" - sliceUtils "github.com/SAP/jenkins-library/pkg/piperutils" "github.com/google/uuid" "github.com/pkg/errors" "github.com/stretchr/testify/assert" @@ -317,7 +317,7 @@ func (e *newmanExecuteMockUtils) RunExecutable(executable string, params ...stri if e.errorOnNewmanExecution && strings.Contains(executable, "newman") { return errors.New("error on newman execution") } - if e.errorOnNewmanInstall && sliceUtils.ContainsString(params, "install") { + if e.errorOnNewmanInstall && slices.Contains(params, "install") { return errors.New("error on newman install") } diff --git a/cmd/npmExecuteTests.go b/cmd/npmExecuteTests.go new file mode 100644 index 0000000000..90dfaad2e5 --- /dev/null +++ b/cmd/npmExecuteTests.go @@ -0,0 +1,115 @@ +package cmd + +import ( + "fmt" + "os" + "strings" + + "github.com/SAP/jenkins-library/pkg/command" + "github.com/SAP/jenkins-library/pkg/log" + "github.com/SAP/jenkins-library/pkg/telemetry" +) + +type vaultUrl struct { + URL string `json:"url"` + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` +} + +func npmExecuteTests(config npmExecuteTestsOptions, _ *telemetry.CustomData) { + c := command.Command{} + + c.Stdout(log.Writer()) + c.Stderr(log.Writer()) + err := runNpmExecuteTests(&config, &c) + if err != nil { + log.Entry().WithError(err).Fatal("Step execution failed") + } +} + +func runNpmExecuteTests(config *npmExecuteTestsOptions, c command.ExecRunner) error { + if len(config.Envs) > 0 { + c.SetEnv(config.Envs) + } + + if len(config.Paths) > 0 { + path := fmt.Sprintf("PATH=%s:%s", os.Getenv("PATH"), strings.Join(config.Paths, ":")) + c.SetEnv([]string{path}) + } + + if config.WorkingDirectory != "" { + if err := os.Chdir(config.WorkingDirectory); err != nil { + return fmt.Errorf("failed to change directory: %w", err) + } + } + + installCommandTokens := strings.Fields(config.InstallCommand) + if err := c.RunExecutable(installCommandTokens[0], installCommandTokens[1:]...); err != nil { + return fmt.Errorf("failed to execute install command: %w", err) + } + + parsedURLs, err := parseURLs(config.VaultURLs) + if err != nil { + return err + } + + for _, app := range parsedURLs { + if err := runTestForUrl(app.URL, app.Username, app.Password, config, c); err != nil { + return err + } + } + + if err := runTestForUrl(config.BaseURL, config.VaultUsername, config.VaultPassword, config, c); err != nil { + return err + } + return nil +} + +func runTestForUrl(url, username, password string, config *npmExecuteTestsOptions, command command.ExecRunner) error { + credentialsToEnv(username, password, config.UsernameEnvVar, config.PasswordEnvVar, command) + // we need to reset the env vars as the next test might not have any credentials + defer resetCredentials(config.UsernameEnvVar, config.PasswordEnvVar, command) + + runScriptTokens := strings.Fields(config.RunCommand) + if config.UrlOptionPrefix != "" { + runScriptTokens = append(runScriptTokens, config.UrlOptionPrefix+url) + } + if err := command.RunExecutable(runScriptTokens[0], runScriptTokens[1:]...); err != nil { + return fmt.Errorf("failed to execute npm script: %w", err) + } + + return nil +} + +func parseURLs(urls []map[string]interface{}) ([]vaultUrl, error) { + parsedUrls := []vaultUrl{} + + for _, url := range urls { + parsedUrl := vaultUrl{} + urlStr, ok := url["url"].(string) + if !ok { + return nil, fmt.Errorf("url field is not a string") + } + parsedUrl.URL = urlStr + if username, ok := url["username"].(string); ok { + parsedUrl.Username = username + } + + if password, ok := url["password"].(string); ok { + parsedUrl.Password = password + } + parsedUrls = append(parsedUrls, parsedUrl) + } + return parsedUrls, nil +} + +func credentialsToEnv(username, password, usernameEnv, passwordEnv string, c command.ExecRunner) { + if username == "" || password == "" { + return + } + c.SetEnv([]string{usernameEnv + "=" + username, passwordEnv + "=" + password}) +} + +func resetCredentials(usernameEnv, passwordEnv string, c command.ExecRunner) { + c.SetEnv([]string{usernameEnv + "=", passwordEnv + "="}) +} diff --git a/cmd/npmExecuteTests_generated.go b/cmd/npmExecuteTests_generated.go new file mode 100644 index 0000000000..54fc441863 --- /dev/null +++ b/cmd/npmExecuteTests_generated.go @@ -0,0 +1,376 @@ +// Code generated by piper's step-generator. DO NOT EDIT. + +package cmd + +import ( + "fmt" + "os" + "reflect" + "strings" + "time" + + "github.com/SAP/jenkins-library/pkg/config" + "github.com/SAP/jenkins-library/pkg/gcp" + "github.com/SAP/jenkins-library/pkg/gcs" + "github.com/SAP/jenkins-library/pkg/log" + "github.com/SAP/jenkins-library/pkg/splunk" + "github.com/SAP/jenkins-library/pkg/telemetry" + "github.com/SAP/jenkins-library/pkg/validation" + "github.com/bmatcuk/doublestar" + "github.com/spf13/cobra" +) + +type npmExecuteTestsOptions struct { + InstallCommand string `json:"installCommand,omitempty"` + RunCommand string `json:"runCommand,omitempty"` + VaultURLs []map[string]interface{} `json:"vaultURLs,omitempty"` + VaultUsername string `json:"vaultUsername,omitempty"` + VaultPassword string `json:"vaultPassword,omitempty"` + BaseURL string `json:"baseUrl,omitempty"` + UsernameEnvVar string `json:"usernameEnvVar,omitempty"` + PasswordEnvVar string `json:"passwordEnvVar,omitempty"` + UrlOptionPrefix string `json:"urlOptionPrefix,omitempty"` + Envs []string `json:"envs,omitempty"` + Paths []string `json:"paths,omitempty"` + WorkingDirectory string `json:"workingDirectory,omitempty"` +} + +type npmExecuteTestsReports struct { +} + +func (p *npmExecuteTestsReports) persist(stepConfig npmExecuteTestsOptions, gcpJsonKeyFilePath string, gcsBucketId string, gcsFolderPath string, gcsSubFolder string) { + if gcsBucketId == "" { + log.Entry().Info("persisting reports to GCS is disabled, because gcsBucketId is empty") + return + } + log.Entry().Info("Uploading reports to Google Cloud Storage...") + content := []gcs.ReportOutputParam{ + {FilePattern: "**/e2e-results.xml", ParamRef: "", StepResultType: "end-to-end-test"}, + } + envVars := []gcs.EnvVar{ + {Name: "GOOGLE_APPLICATION_CREDENTIALS", Value: gcpJsonKeyFilePath, Modified: false}, + } + gcsClient, err := gcs.NewClient(gcs.WithEnvVars(envVars)) + if err != nil { + log.Entry().Errorf("creation of GCS client failed: %v", err) + return + } + defer gcsClient.Close() + structVal := reflect.ValueOf(&stepConfig).Elem() + inputParameters := map[string]string{} + for i := 0; i < structVal.NumField(); i++ { + field := structVal.Type().Field(i) + if field.Type.String() == "string" { + paramName := strings.Split(field.Tag.Get("json"), ",") + paramValue, _ := structVal.Field(i).Interface().(string) + inputParameters[paramName[0]] = paramValue + } + } + if err := gcs.PersistReportsToGCS(gcsClient, content, inputParameters, gcsFolderPath, gcsBucketId, gcsSubFolder, doublestar.Glob, os.Stat); err != nil { + log.Entry().Errorf("failed to persist reports: %v", err) + } +} + +// NpmExecuteTestsCommand Executes end-to-end tests using npm +func NpmExecuteTestsCommand() *cobra.Command { + const STEP_NAME = "npmExecuteTests" + + metadata := npmExecuteTestsMetadata() + var stepConfig npmExecuteTestsOptions + var startTime time.Time + var reports npmExecuteTestsReports + var logCollector *log.CollectorHook + var splunkClient *splunk.Splunk + telemetryClient := &telemetry.Telemetry{} + + var createNpmExecuteTestsCmd = &cobra.Command{ + Use: STEP_NAME, + Short: "Executes end-to-end tests using npm", + Long: `This step executes end-to-end tests in a Docker environment using npm. + +The step spins up a Docker container based on the specified ` + "`" + `dockerImage` + "`" + ` and executes the ` + "`" + `installScript` + "`" + ` and ` + "`" + `runScript` + "`" + ` from ` + "`" + `package.json` + "`" + `. + +The application URLs and credentials can be specified in ` + "`" + `appUrls` + "`" + ` and ` + "`" + `credentialsId` + "`" + ` respectively. If ` + "`" + `wdi5` + "`" + ` is set to ` + "`" + `true` + "`" + `, the step uses ` + "`" + `wdi5_username` + "`" + ` and ` + "`" + `wdi5_password` + "`" + ` for authentication. + +The tests can be restricted to run only on the productive branch by setting ` + "`" + `onlyRunInProductiveBranch` + "`" + ` to ` + "`" + `true` + "`" + `.`, + PreRunE: func(cmd *cobra.Command, _ []string) error { + startTime = time.Now() + log.SetStepName(STEP_NAME) + log.SetVerbose(GeneralConfig.Verbose) + + GeneralConfig.GitHubAccessTokens = ResolveAccessTokens(GeneralConfig.GitHubTokens) + + path, err := os.Getwd() + if err != nil { + return err + } + fatalHook := &log.FatalHook{CorrelationID: GeneralConfig.CorrelationID, Path: path} + log.RegisterHook(fatalHook) + + err = PrepareConfig(cmd, &metadata, STEP_NAME, &stepConfig, config.OpenPiperFile) + if err != nil { + log.SetErrorCategory(log.ErrorConfiguration) + return err + } + + if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 { + sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID) + log.RegisterHook(&sentryHook) + } + + if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 || len(GeneralConfig.HookConfig.SplunkConfig.ProdCriblEndpoint) > 0 { + splunkClient = &splunk.Splunk{} + logCollector = &log.CollectorHook{CorrelationID: GeneralConfig.CorrelationID} + log.RegisterHook(logCollector) + } + + if err = log.RegisterANSHookIfConfigured(GeneralConfig.CorrelationID); err != nil { + log.Entry().WithError(err).Warn("failed to set up SAP Alert Notification Service log hook") + } + + validation, err := validation.New(validation.WithJSONNamesForStructFields(), validation.WithPredefinedErrorMessages()) + if err != nil { + return err + } + if err = validation.ValidateStruct(stepConfig); err != nil { + log.SetErrorCategory(log.ErrorConfiguration) + return err + } + + return nil + }, + Run: func(_ *cobra.Command, _ []string) { + vaultClient := config.GlobalVaultClient() + if vaultClient != nil { + defer vaultClient.MustRevokeToken() + } + + stepTelemetryData := telemetry.CustomData{} + stepTelemetryData.ErrorCode = "1" + handler := func() { + reports.persist(stepConfig, GeneralConfig.GCPJsonKeyFilePath, GeneralConfig.GCSBucketId, GeneralConfig.GCSFolderPath, GeneralConfig.GCSSubFolder) + config.RemoveVaultSecretFiles() + stepTelemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds()) + stepTelemetryData.ErrorCategory = log.GetErrorCategory().String() + stepTelemetryData.PiperCommitHash = GitCommit + telemetryClient.SetData(&stepTelemetryData) + telemetryClient.Send() + if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 { + splunkClient.Initialize(GeneralConfig.CorrelationID, + GeneralConfig.HookConfig.SplunkConfig.Dsn, + GeneralConfig.HookConfig.SplunkConfig.Token, + GeneralConfig.HookConfig.SplunkConfig.Index, + GeneralConfig.HookConfig.SplunkConfig.SendLogs) + splunkClient.Send(telemetryClient.GetData(), logCollector) + } + if len(GeneralConfig.HookConfig.SplunkConfig.ProdCriblEndpoint) > 0 { + splunkClient.Initialize(GeneralConfig.CorrelationID, + GeneralConfig.HookConfig.SplunkConfig.ProdCriblEndpoint, + GeneralConfig.HookConfig.SplunkConfig.ProdCriblToken, + GeneralConfig.HookConfig.SplunkConfig.ProdCriblIndex, + GeneralConfig.HookConfig.SplunkConfig.SendLogs) + splunkClient.Send(telemetryClient.GetData(), logCollector) + } + if GeneralConfig.HookConfig.GCPPubSubConfig.Enabled { + err := gcp.NewGcpPubsubClient( + vaultClient, + GeneralConfig.HookConfig.GCPPubSubConfig.ProjectNumber, + GeneralConfig.HookConfig.GCPPubSubConfig.IdentityPool, + GeneralConfig.HookConfig.GCPPubSubConfig.IdentityProvider, + GeneralConfig.CorrelationID, + GeneralConfig.HookConfig.OIDCConfig.RoleID, + ).Publish(GeneralConfig.HookConfig.GCPPubSubConfig.Topic, telemetryClient.GetDataBytes()) + if err != nil { + log.Entry().WithError(err).Warn("event publish failed") + } + } + } + log.DeferExitHandler(handler) + defer handler() + telemetryClient.Initialize(GeneralConfig.NoTelemetry, STEP_NAME, GeneralConfig.HookConfig.PendoConfig.Token) + npmExecuteTests(stepConfig, &stepTelemetryData) + stepTelemetryData.ErrorCode = "0" + log.Entry().Info("SUCCESS") + }, + } + + addNpmExecuteTestsFlags(createNpmExecuteTestsCmd, &stepConfig) + return createNpmExecuteTestsCmd +} + +func addNpmExecuteTestsFlags(cmd *cobra.Command, stepConfig *npmExecuteTestsOptions) { + cmd.Flags().StringVar(&stepConfig.InstallCommand, "installCommand", `npm ci`, "Command to be executed for installation`.") + cmd.Flags().StringVar(&stepConfig.RunCommand, "runCommand", `npm run wdi5`, "Command to be executed for running tests`.") + + cmd.Flags().StringVar(&stepConfig.VaultUsername, "vaultUsername", os.Getenv("PIPER_vaultUsername"), "The base URL username.") + cmd.Flags().StringVar(&stepConfig.VaultPassword, "vaultPassword", os.Getenv("PIPER_vaultPassword"), "The base URL password.") + cmd.Flags().StringVar(&stepConfig.BaseURL, "baseUrl", `http://localhost:8080/index.html`, "Base URL of the application to be tested.") + cmd.Flags().StringVar(&stepConfig.UsernameEnvVar, "usernameEnvVar", `wdi5_username`, "Env var for username.") + cmd.Flags().StringVar(&stepConfig.PasswordEnvVar, "passwordEnvVar", `wdi5_password`, "Env var for password.") + cmd.Flags().StringVar(&stepConfig.UrlOptionPrefix, "urlOptionPrefix", os.Getenv("PIPER_urlOptionPrefix"), "If you want to specify an extra option that the tested url it appended to.\nFor example if the test URL is `http://localhost` and urlOptionPrefix is `--base-url=`,\nwe'll add `--base-url=http://localhost` to your runScript.\n") + cmd.Flags().StringSliceVar(&stepConfig.Envs, "envs", []string{}, "List of environment variables to be set") + cmd.Flags().StringSliceVar(&stepConfig.Paths, "paths", []string{}, "List of paths to be added to $PATH") + cmd.Flags().StringVar(&stepConfig.WorkingDirectory, "workingDirectory", `.`, "Directory where your tests are located relative to the root of your project") + + cmd.MarkFlagRequired("runCommand") +} + +// retrieve step metadata +func npmExecuteTestsMetadata() config.StepData { + var theMetaData = config.StepData{ + Metadata: config.StepMetadata{ + Name: "npmExecuteTests", + Aliases: []config.Alias{}, + Description: "Executes end-to-end tests using npm", + }, + Spec: config.StepSpec{ + Inputs: config.StepInputs{ + Parameters: []config.StepParameters{ + { + Name: "installCommand", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: `npm ci`, + }, + { + Name: "runCommand", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: true, + Aliases: []config.Alias{}, + Default: `npm run wdi5`, + }, + { + Name: "vaultURLs", + ResourceRef: []config.ResourceReference{ + { + Name: "appMetadataVaultSecretName", + Type: "vaultSecret", + Default: "appMetadata", + }, + }, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "[]map[string]interface{}", + Mandatory: false, + Aliases: []config.Alias{}, + }, + { + Name: "vaultUsername", + ResourceRef: []config.ResourceReference{ + { + Name: "appMetadataVaultSecretName", + Type: "vaultSecret", + Default: "appMetadata", + }, + }, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_vaultUsername"), + }, + { + Name: "vaultPassword", + ResourceRef: []config.ResourceReference{ + { + Name: "appMetadataVaultSecretName", + Type: "vaultSecret", + Default: "appMetadata", + }, + }, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_vaultPassword"), + }, + { + Name: "baseUrl", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: `http://localhost:8080/index.html`, + }, + { + Name: "usernameEnvVar", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: `wdi5_username`, + }, + { + Name: "passwordEnvVar", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: `wdi5_password`, + }, + { + Name: "urlOptionPrefix", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_urlOptionPrefix"), + }, + { + Name: "envs", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "[]string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: []string{}, + }, + { + Name: "paths", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "[]string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: []string{}, + }, + { + Name: "workingDirectory", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: `.`, + }, + }, + }, + Containers: []config.Container{ + {Name: "node", Image: "node:lts-bookworm", EnvVars: []config.EnvVar{{Name: "BASE_URL", Value: "${{params.baseUrl}}"}, {Name: "CREDENTIALS_ID", Value: "${{params.credentialsId}}"}, {Name: "no_proxy", Value: "localhost,selenium,$no_proxy"}, {Name: "NO_PROXY", Value: "localhost,selenium,$NO_PROXY"}}, WorkingDir: "/home/node"}, + }, + Sidecars: []config.Container{ + {Name: "selenium", Image: "selenium/standalone-chrome", EnvVars: []config.EnvVar{{Name: "NO_PROXY", Value: "localhost,selenium,$NO_PROXY"}, {Name: "no_proxy", Value: "localhost,selenium,$no_proxy"}}}, + }, + Outputs: config.StepOutputs{ + Resources: []config.StepResources{ + { + Name: "reports", + Type: "reports", + Parameters: []map[string]interface{}{ + {"filePattern": "**/e2e-results.xml", "type": "end-to-end-test"}, + }, + }, + }, + }, + }, + } + return theMetaData +} diff --git a/cmd/npmExecuteTests_generated_test.go b/cmd/npmExecuteTests_generated_test.go new file mode 100644 index 0000000000..58bab7ed11 --- /dev/null +++ b/cmd/npmExecuteTests_generated_test.go @@ -0,0 +1,20 @@ +//go:build unit +// +build unit + +package cmd + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestNpmExecuteTestsCommand(t *testing.T) { + t.Parallel() + + testCmd := NpmExecuteTestsCommand() + + // only high level testing performed - details are tested in step generation procedure + assert.Equal(t, "npmExecuteTests", testCmd.Use, "command name incorrect") + +} diff --git a/cmd/npmExecuteTests_test.go b/cmd/npmExecuteTests_test.go new file mode 100644 index 0000000000..bd044ead68 --- /dev/null +++ b/cmd/npmExecuteTests_test.go @@ -0,0 +1,88 @@ +package cmd + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestRunNpmExecuteTests(t *testing.T) { + t.Parallel() + + testCmd := NpmExecuteTestsCommand() + + // only high level testing performed - details are tested in step generation procedure + assert.Equal(t, "npmExecuteTests", testCmd.Use, "command name incorrect") +} + +func TestParseURLs(t *testing.T) { + tests := []struct { + name string + input []map[string]interface{} + expected []vaultUrl + wantErr bool + }{ + { + name: "Valid URLs", + input: []map[string]interface{}{ + { + "url": "http://example.com", + "username": "user1", + "password": "pass1", + }, + { + "url": "http://example2.com", + }, + }, + expected: []vaultUrl{ + { + URL: "http://example.com", + Username: "user1", + Password: "pass1", + }, + { + URL: "http://example2.com", + }, + }, + wantErr: false, + }, + { + name: "Invalid URL entry", + input: []map[string]interface{}{ + { + "username": "user1", + }, + }, + expected: nil, + wantErr: true, + }, + { + name: "Invalid URL field type", + input: []map[string]interface{}{ + { + "url": 123, + }, + }, + expected: nil, + wantErr: true, + }, + { + name: "Empty URLs", + input: []map[string]interface{}{}, + expected: []vaultUrl{}, + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := parseURLs(tt.input) + if tt.wantErr { + assert.Error(t, err) + } else { + assert.NoError(t, err) + } + assert.Equal(t, tt.expected, got) + }) + } +} diff --git a/cmd/piper.go b/cmd/piper.go index 1b4972987a..ed728f8099 100644 --- a/cmd/piper.go +++ b/cmd/piper.go @@ -24,14 +24,14 @@ type GeneralConfigOptions struct { CorrelationID string CustomConfig string GitHubTokens []string // list of entries in form of : to allow token authentication for downloading config / defaults - DefaultConfig []string //ordered list of Piper default configurations. Can be filePath or ENV containing JSON in format 'ENV:MY_ENV_VAR' + DefaultConfig []string // ordered list of Piper default configurations. Can be filePath or ENV containing JSON in format 'ENV:MY_ENV_VAR' IgnoreCustomDefaults bool ParametersJSON string EnvRootPath string NoTelemetry bool StageName string StepConfigJSON string - StepMetadata string //metadata to be considered, can be filePath or ENV containing JSON in format 'ENV:MY_ENV_VAR' + StepMetadata string // metadata to be considered, can be filePath or ENV containing JSON in format 'ENV:MY_ENV_VAR' StepName string Verbose bool LogFormat string @@ -41,7 +41,7 @@ type GeneralConfigOptions struct { VaultServerURL string VaultNamespace string VaultPath string - TrustEngineToken string + SystemTrustToken string HookConfig HookConfiguration MetaDataResolver func() map[string]config.StepData GCPJsonKeyFilePath string @@ -57,7 +57,7 @@ type HookConfiguration struct { SplunkConfig SplunkConfiguration `json:"splunk,omitempty"` PendoConfig PendoConfiguration `json:"pendo,omitempty"` OIDCConfig OIDCConfiguration `json:"oidc,omitempty"` - TrustEngineConfig TrustEngineConfiguration `json:"trustengine,omitempty"` + SystemTrustConfig SystemTrustConfiguration `json:"systemtrust,omitempty"` } type GCPPubSubConfiguration struct { @@ -93,7 +93,7 @@ type OIDCConfiguration struct { RoleID string `json:",roleID,omitempty"` } -type TrustEngineConfiguration struct { +type SystemTrustConfiguration struct { ServerURL string `json:"baseURL,omitempty"` TokenEndPoint string `json:"tokenEndPoint,omitempty"` TokenQueryParamName string `json:"tokenQueryParamName,omitempty"` @@ -161,6 +161,7 @@ func Execute() { rootCmd.AddCommand(AbapEnvironmentRunATCCheckCommand()) rootCmd.AddCommand(NpmExecuteScriptsCommand()) rootCmd.AddCommand(NpmExecuteLintCommand()) + rootCmd.AddCommand(NpmExecuteTestsCommand()) rootCmd.AddCommand(GctsCreateRepositoryCommand()) rootCmd.AddCommand(GctsExecuteABAPQualityChecksCommand()) rootCmd.AddCommand(GctsExecuteABAPUnitTestsCommand()) @@ -269,7 +270,6 @@ func addRootFlags(rootCmd *cobra.Command) { rootCmd.PersistentFlags().StringVar(&GeneralConfig.GCSFolderPath, "gcsFolderPath", "", "GCS folder path. One of the components of GCS target folder") rootCmd.PersistentFlags().StringVar(&GeneralConfig.GCSBucketId, "gcsBucketId", "", "Bucket name for Google Cloud Storage") rootCmd.PersistentFlags().StringVar(&GeneralConfig.GCSSubFolder, "gcsSubFolder", "", "Used to logically separate results of the same step result type") - } // ResolveAccessTokens reads a list of tokens in format host:token passed via command line @@ -353,7 +353,6 @@ func initStageName(outputToLog bool) { // PrepareConfig reads step configuration from various sources and merges it (defaults, config file, flags, ...) func PrepareConfig(cmd *cobra.Command, metadata *config.StepData, stepName string, options interface{}, openFile func(s string, t map[string]string) (io.ReadCloser, error)) error { - log.SetFormatter(GeneralConfig.LogFormat) initStageName(true) @@ -386,8 +385,8 @@ func PrepareConfig(cmd *cobra.Command, metadata *config.StepData, stepName strin } myConfig.SetVaultCredentials(GeneralConfig.VaultRoleID, GeneralConfig.VaultRoleSecretID, GeneralConfig.VaultToken) - GeneralConfig.TrustEngineToken = os.Getenv("PIPER_trustEngineToken") - myConfig.SetTrustEngineToken(GeneralConfig.TrustEngineToken) + GeneralConfig.SystemTrustToken = os.Getenv("PIPER_systemTrustToken") + myConfig.SetSystemTrustToken(GeneralConfig.SystemTrustToken) if len(GeneralConfig.StepConfigJSON) != 0 { // ignore config & defaults in favor of passed stepConfigJSON @@ -398,7 +397,7 @@ func PrepareConfig(cmd *cobra.Command, metadata *config.StepData, stepName strin // use config & defaults var customConfig io.ReadCloser var err error - //accept that config file and defaults cannot be loaded since both are not mandatory here + // accept that config file and defaults cannot be loaded since both are not mandatory here { projectConfigFile := getProjectConfigFile(GeneralConfig.CustomConfig) if exists, err := piperutils.FileExists(projectConfigFile); exists { @@ -625,7 +624,6 @@ func getStepOptionsStructType(stepOptions interface{}) reflect.Type { } func getProjectConfigFile(name string) string { - var altName string if ext := filepath.Ext(name); ext == ".yml" { altName = fmt.Sprintf("%v.yaml", strings.TrimSuffix(name, ext)) diff --git a/cmd/sonarExecuteScan_generated.go b/cmd/sonarExecuteScan_generated.go index 293ae88926..1f9e0c33c9 100644 --- a/cmd/sonarExecuteScan_generated.go +++ b/cmd/sonarExecuteScan_generated.go @@ -355,8 +355,8 @@ func sonarExecuteScanMetadata() config.StepData { }, { - Name: "sonarTrustengineSecretName", - Type: "trustengineSecret", + Name: "sonarSystemtrustSecretName", + Type: "systemTrustSecret", Default: "sonar", }, }, diff --git a/cmd/terraformExecute.go b/cmd/terraformExecute.go index e85344b729..bd2b8fa4fe 100644 --- a/cmd/terraformExecute.go +++ b/cmd/terraformExecute.go @@ -3,6 +3,7 @@ package cmd import ( "bytes" "fmt" + "slices" "github.com/SAP/jenkins-library/pkg/command" "github.com/SAP/jenkins-library/pkg/log" @@ -53,15 +54,15 @@ func runTerraformExecute(config *terraformExecuteOptions, telemetryData *telemet args := []string{} - if piperutils.ContainsString([]string{"apply", "destroy"}, config.Command) { + if slices.Contains([]string{"apply", "destroy"}, config.Command) { args = append(args, "-auto-approve") } - if piperutils.ContainsString([]string{"apply", "plan"}, config.Command) && config.TerraformSecrets != "" { + if slices.Contains([]string{"apply", "plan"}, config.Command) && config.TerraformSecrets != "" { args = append(args, fmt.Sprintf("-var-file=%s", config.TerraformSecrets)) } - if piperutils.ContainsString([]string{"init", "validate", "plan", "apply", "destroy"}, config.Command) { + if slices.Contains([]string{"init", "validate", "plan", "apply", "destroy"}, config.Command) { args = append(args, "-no-color") } diff --git a/cmd/whitesourceExecuteScan.go b/cmd/whitesourceExecuteScan.go index 14772ec8f6..16c9f09d2a 100644 --- a/cmd/whitesourceExecuteScan.go +++ b/cmd/whitesourceExecuteScan.go @@ -76,6 +76,9 @@ func (w *whitesourceUtilsBundle) FileOpen(name string, flag int, perm os.FileMod } func (w *whitesourceUtilsBundle) GetArtifactCoordinates(buildTool, buildDescriptorFile string, options *versioning.Options) (versioning.Coordinates, error) { + if err := validationBuildDescriptorFile(buildTool, buildDescriptorFile); err != nil { + return versioning.Coordinates{}, err + } artifact, err := versioning.GetArtifact(buildTool, buildDescriptorFile, options, w) if err != nil { return versioning.Coordinates{}, err @@ -83,6 +86,52 @@ func (w *whitesourceUtilsBundle) GetArtifactCoordinates(buildTool, buildDescript return artifact.GetCoordinates() } +func validationBuildDescriptorFile(buildTool, buildDescriptorFile string) error { + if buildDescriptorFile == "" { + return nil + } + switch buildTool { + case "dub": + if filepath.Ext(buildDescriptorFile) != ".json" { + return errors.New("extension of buildDescriptorFile must be in '*.json'") + } + case "gradle": + if filepath.Ext(buildDescriptorFile) != ".properties" { + return errors.New("extension of buildDescriptorFile must be in '*.properties'") + } + case "golang": + if !strings.HasSuffix(buildDescriptorFile, "go.mod") && + !strings.HasSuffix(buildDescriptorFile, "VERSION") && + !strings.HasSuffix(buildDescriptorFile, "version.txt") { + return errors.New("buildDescriptorFile must be one of [\"go.mod\",\"VERSION\", \"version.txt\"]") + } + case "maven": + if filepath.Ext(buildDescriptorFile) != ".xml" { + return errors.New("extension of buildDescriptorFile must be in '*.xml'") + } + case "mta": + if filepath.Ext(buildDescriptorFile) != ".yaml" { + return errors.New("extension of buildDescriptorFile must be in '*.yaml'") + } + case "npm", "yarn": + if filepath.Ext(buildDescriptorFile) != ".json" { + return errors.New("extension of buildDescriptorFile must be in '*.json'") + } + case "pip": + if !strings.HasSuffix(buildDescriptorFile, "setup.py") && + !strings.HasSuffix(buildDescriptorFile, "version.txt") && + !strings.HasSuffix(buildDescriptorFile, "VERSION") { + return errors.New("buildDescriptorFile must be one of [\"setup.py\",\"version.txt\", \"VERSION\"]") + } + case "sbt": + if !strings.HasSuffix(buildDescriptorFile, "sbtDescriptor.json") && + !strings.HasSuffix(buildDescriptorFile, "build.sbt") { + return errors.New("extension of buildDescriptorFile must be in '*.json' or '*sbt'") + } + } + return nil +} + func (w *whitesourceUtilsBundle) getNpmExecutor(config *ws.ScanOptions) npm.Executor { if w.npmExecutor == nil { w.npmExecutor = npm.NewExecutor(npm.ExecutorOptions{DefaultNpmRegistry: config.DefaultNpmRegistry}) diff --git a/cmd/whitesourceExecuteScan_test.go b/cmd/whitesourceExecuteScan_test.go index b9c7e22b59..d1383c17ae 100644 --- a/cmd/whitesourceExecuteScan_test.go +++ b/cmd/whitesourceExecuteScan_test.go @@ -871,3 +871,71 @@ func TestPersistScannedProjects(t *testing.T) { assert.Equal(t, []string{"project - 1"}, cpe.custom.whitesourceProjectNames) }) } + +func TestBuildToolFiles(t *testing.T) { + t.Parallel() + t.Run("buildTool = dub", func(t *testing.T) { + err := validationBuildDescriptorFile("dub", "/home/mta.yaml") + assert.ErrorContains(t, err, "extension of buildDescriptorFile must be in '*.json'") + err = validationBuildDescriptorFile("dub", "/home/dub.json") + assert.NoError(t, err) + }) + t.Run("buildTool = gradle", func(t *testing.T) { + err := validationBuildDescriptorFile("gradle", "/home/go.mod") + assert.ErrorContains(t, err, "extension of buildDescriptorFile must be in '*.properties'") + err = validationBuildDescriptorFile("gradle", "/home/gradle.properties") + assert.NoError(t, err) + }) + t.Run("buildTool = golang", func(t *testing.T) { + err := validationBuildDescriptorFile("golang", "/home/go.json") + assert.ErrorContains(t, err, "buildDescriptorFile must be one of [\"go.mod\",\"VERSION\", \"version.txt\"]") + err = validationBuildDescriptorFile("golang", "/home/go.mod") + assert.NoError(t, err) + err = validationBuildDescriptorFile("golang", "/home/VERSION") + assert.NoError(t, err) + err = validationBuildDescriptorFile("golang", "/home/version.txt") + assert.NoError(t, err) + }) + t.Run("buildTool = maven", func(t *testing.T) { + err := validationBuildDescriptorFile("maven", "/home/go.mod") + assert.ErrorContains(t, err, "extension of buildDescriptorFile must be in '*.xml'") + err = validationBuildDescriptorFile("maven", "/home/pom.xml") + assert.NoError(t, err) + }) + t.Run("buildTool = mta", func(t *testing.T) { + err := validationBuildDescriptorFile("mta", "/home/go.mod") + assert.ErrorContains(t, err, "extension of buildDescriptorFile must be in '*.yaml'") + err = validationBuildDescriptorFile("mta", "/home/mta.yaml") + assert.NoError(t, err) + }) + t.Run("buildTool = npm", func(t *testing.T) { + err := validationBuildDescriptorFile("npm", "/home/go.mod") + assert.ErrorContains(t, err, "extension of buildDescriptorFile must be in '*.json'") + err = validationBuildDescriptorFile("npm", "/home/package.json") + assert.NoError(t, err) + }) + t.Run("buildTool = yarn", func(t *testing.T) { + err := validationBuildDescriptorFile("yarn", "/home/go.mod") + assert.ErrorContains(t, err, "extension of buildDescriptorFile must be in '*.json'") + err = validationBuildDescriptorFile("yarn", "/home/package.json") + assert.NoError(t, err) + }) + t.Run("buildTool = pip", func(t *testing.T) { + err := validationBuildDescriptorFile("pip", "/home/go.mod") + assert.ErrorContains(t, err, "buildDescriptorFile must be one of [\"setup.py\",\"version.txt\", \"VERSION\"]") + err = validationBuildDescriptorFile("pip", "/home/setup.py") + assert.NoError(t, err) + err = validationBuildDescriptorFile("pip", "/home/version.txt") + assert.NoError(t, err) + err = validationBuildDescriptorFile("pip", "/home/VERSION") + assert.NoError(t, err) + }) + t.Run("buildTool = sbt", func(t *testing.T) { + err := validationBuildDescriptorFile("sbt", "/home/go.mod") + assert.ErrorContains(t, err, "extension of buildDescriptorFile must be in '*.json'") + err = validationBuildDescriptorFile("sbt", "/home/sbtDescriptor.json") + assert.NoError(t, err) + err = validationBuildDescriptorFile("sbt", "/home/build.sbt") + assert.NoError(t, err) + }) +} diff --git a/documentation/docs/steps/npmExecuteTests.md b/documentation/docs/steps/npmExecuteTests.md new file mode 100644 index 0000000000..c7ab63968d --- /dev/null +++ b/documentation/docs/steps/npmExecuteTests.md @@ -0,0 +1,114 @@ +# ${docGenStepName} + +> [!WARNING] +> Please note, that the npmExecuteTests step is in beta state, and there could be breaking changes before we remove the beta notice. + +## ${docGenDescription} + +## ${docGenParameters} + +## ${docGenConfiguration} + +## Examples + +### Simple example using wdi5 + +```yaml +stages: + - name: Test + steps: + - name: npmExecuteTests + type: npmExecuteTests + params: + baseUrl: "http://example.com/index.html" +``` + +This will run your wdi5 tests with the given baseUrl. + +### Advanced example using custom test script with credentials using Vault + +```yaml +stages: + - name: Test + steps: + - name: npmExecuteTests + type: npmExecuteTests + params: + installCommand: "npm install" + runCommand: "npm run custom-e2e-test" + usernameEnvVar: "e2e_username" + passwordEnvVar: "e2e_password" + baseUrl: "http://example.com/index.html" + urlOptionPrefix: "--base-url=" +``` + +and Vault configuration in PIPELINE-GROUP-/PIPELINE-/appMetadata + +```json +{ + "vaultURLs": [ + { + "url": "http://one.example.com/index.html", + "username": "some-username1", + "password": "some-password1" + }, + { + "url": "http://two.example.com/index.html", + "username": "some-username2", + "password": "some-password2" + } + ], + "vaultUsername": "base-url-username", + "vaultPassword": "base-url-password" +} +``` + +This will run your custom install and run script for each URL from secrets and use the given URL like so: + +```shell +npm run custom-e2e-test --base-url=http://one.example.com/index.html +``` + +Each test run will have their own environment variables set: + +```shell +e2e_username=some-username1 +e2e_password=some-password1 +``` + +Environment variables are reset before each test run with their corresponding values from the secrets + +### Custom environment variables and $PATH + +```yaml +stages: + - name: Test + steps: + - name: npmExecuteTests + type: npmExecuteTests + params: + envs: + - "MY_ENV_VAR=value" + paths: + - "/path/to/add" +``` + +If you're running uiVeri5 tests, you might need to set additional environment variables or add paths to the $PATH variable. This can be done using the `envs` and `paths` parameters: + +```yaml +stages: + - name: Test + steps: + - name: npmExecuteTests + type: npmExecuteTests + params: + runCommand: "/home/node/.npm-global/bin/uiveri5" + installCommand: "npm install @ui5/uiveri5 --global --quiet" + runOptions: ["--seleniumAddress=http://localhost:4444/wd/hub"] + usernameEnvVar: "PIPER_SELENIUM_HUB_USER" + passwordEnvVar: "PIPER_SELENIUM_HUB_PASSWORD" + envs: + - "NPM_CONFIG_PREFIX=~/.npm-global" + paths: + - "~/.npm-global/bin" +``` diff --git a/documentation/mkdocs.yml b/documentation/mkdocs.yml index c7e3674b75..953bfb2c94 100644 --- a/documentation/mkdocs.yml +++ b/documentation/mkdocs.yml @@ -155,6 +155,7 @@ nav: - npmExecuteEndToEndTests: steps/npmExecuteEndToEndTests.md - npmExecuteLint: steps/npmExecuteLint.md - npmExecuteScripts: steps/npmExecuteScripts.md + - npmExecuteTests: steps/npmExecuteTests.md - pipelineExecute: steps/pipelineExecute.md - pipelineRestartSteps: steps/pipelineRestartSteps.md - pipelineStashFiles: steps/pipelineStashFiles.md diff --git a/go.mod b/go.mod index 35fa8e764a..847e98c055 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/SAP/jenkins-library -go 1.22.4 +go 1.23.4 require ( cloud.google.com/go/pubsub v1.36.1 @@ -22,7 +22,7 @@ require ( github.com/getsentry/sentry-go v0.26.0 github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 github.com/go-git/go-billy/v5 v5.5.0 - github.com/go-git/go-git/v5 v5.11.0 + github.com/go-git/go-git/v5 v5.12.0 github.com/go-openapi/runtime v0.24.1 github.com/go-openapi/strfmt v0.21.3 github.com/go-playground/locales v0.14.1 @@ -60,7 +60,7 @@ require ( google.golang.org/api v0.169.0 gopkg.in/ini.v1 v1.67.0 gopkg.in/yaml.v2 v2.4.0 - helm.sh/helm/v3 v3.14.2 + helm.sh/helm/v3 v3.14.4 mvdan.cc/xurls/v2 v2.4.0 sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd ) @@ -78,7 +78,7 @@ require ( github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.25.4 // indirect github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.5 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/cloudflare/circl v1.3.3 // indirect + github.com/cloudflare/circl v1.3.7 // indirect github.com/containerd/errdefs v0.1.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect @@ -105,7 +105,7 @@ require ( github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/shirou/gopsutil/v3 v3.23.12 // indirect github.com/shoenig/go-m1cpu v0.1.6 // indirect - github.com/skeema/knownhosts v1.2.1 // indirect + github.com/skeema/knownhosts v1.2.2 // indirect github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect @@ -134,7 +134,7 @@ require ( github.com/Masterminds/semver v1.5.0 // indirect github.com/Masterminds/semver/v3 v3.2.1 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect + github.com/ProtonMail/go-crypto v1.1.3 // indirect github.com/antchfx/xpath v1.2.0 // indirect github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect github.com/aws/aws-sdk-go-v2 v1.30.4 // indirect @@ -238,7 +238,7 @@ require ( github.com/richardlehane/mscfb v1.0.3 // indirect github.com/richardlehane/msoleps v1.0.1 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect - github.com/sergi/go-diff v1.2.0 // indirect + github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect github.com/stretchr/objx v0.5.2 // indirect github.com/vbatts/tar-split v0.11.5 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect diff --git a/go.sum b/go.sum index 3df2dfff02..ad80d462f2 100644 --- a/go.sum +++ b/go.sum @@ -100,8 +100,8 @@ github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERo github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= github.com/Microsoft/hcsshim v0.11.7 h1:vl/nj3Bar/CvJSYo7gIQPyRWc9f3c6IeSNavBTSZNZQ= github.com/Microsoft/hcsshim v0.11.7/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU= -github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= -github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/ProtonMail/go-crypto v1.1.3 h1:nRBOetoydLeUb4nHajyO2bKqMLfWQ/ZPwkXqXxPxCFk= +github.com/ProtonMail/go-crypto v1.1.3/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= @@ -195,7 +195,6 @@ github.com/buildpacks/imgutil v0.0.0-20230919143643-4ec9360d5f02 h1:Ac/FoFzAhz34 github.com/buildpacks/imgutil v0.0.0-20230919143643-4ec9360d5f02/go.mod h1:Ade+4Q1OovFw6Zdzd+/UVaqWptZSlpnZ8n/vlkgS7M8= github.com/buildpacks/lifecycle v0.18.5 h1:lfoUX8jYCUZ2/Tr2AopaRjinqDivkNkcTChzysQTo00= github.com/buildpacks/lifecycle v0.18.5/go.mod h1:Kvuu9IWABPLXc6yHCMtbdmgrGEi7QEiVzi5GGtcAkW0= -github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -209,8 +208,8 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudevents/sdk-go/v2 v2.15.2 h1:54+I5xQEnI73RBhWHxbI1XJcqOFOVJN85vb41+8mHUc= github.com/cloudevents/sdk-go/v2 v2.15.2/go.mod h1:lL7kSWAE/V8VI4Wh0jbL2v/jvqsm6tjmaQBSvxcv4uE= -github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= -github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= +github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= @@ -301,8 +300,8 @@ github.com/getsentry/sentry-go v0.26.0 h1:IX3++sF6/4B5JcevhdZfdKIHfyvMmAq/UnqcyT github.com/getsentry/sentry-go v0.26.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= -github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= -github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= +github.com/gliderlabs/ssh v0.3.7 h1:iV3Bqi942d9huXnzEF2Mt+CY9gLu8DNM4Obd+8bODRE= +github.com/gliderlabs/ssh v0.3.7/go.mod h1:zpHEXBstFnQYtGnB8k8kQLol82umzn/2/snG7alWVD8= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= @@ -313,8 +312,8 @@ github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+ github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= -github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= +github.com/go-git/go-git/v5 v5.12.0 h1:7Md+ndsjrzZxbddRDZjF14qK+NN56sy6wkqaVrjZtys= +github.com/go-git/go-git/v5 v5.12.0/go.mod h1:FTM9VKtnI2m65hNI/TenDDDnUf2Q9FHnXYjuz9i5OEY= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -842,8 +841,8 @@ github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8= github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= -github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= -github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/shirou/gopsutil/v3 v3.23.12 h1:z90NtUkp3bMtmICZKpC4+WaknU1eXtp5vtbQ11DgpE4= github.com/shirou/gopsutil/v3 v3.23.12/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM= github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= @@ -857,8 +856,8 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= -github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= +github.com/skeema/knownhosts v1.2.2 h1:Iug2P4fLmDw9f41PB6thxUkNUkJzB5i+1/exaj40L3A= +github.com/skeema/knownhosts v1.2.2/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= @@ -1006,8 +1005,6 @@ golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1046,7 +1043,6 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1091,9 +1087,6 @@ golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1116,7 +1109,6 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1176,9 +1168,6 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1189,9 +1178,6 @@ golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXR golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1203,9 +1189,6 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -1264,7 +1247,6 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -1397,8 +1379,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= -helm.sh/helm/v3 v3.14.2 h1:V71fv+NGZv0icBlr+in1MJXuUIHCiPG1hW9gEBISTIA= -helm.sh/helm/v3 v3.14.2/go.mod h1:2itvvDv2WSZXTllknfQo6j7u3VVgMAvm8POCDgYH424= +helm.sh/helm/v3 v3.14.4 h1:6FSpEfqyDalHq3kUr4gOMThhgY55kXUEjdQoyODYnrM= +helm.sh/helm/v3 v3.14.4/go.mod h1:Tje7LL4gprZpuBNTbG34d1Xn5NmRT3OWfBRwpOSer9I= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/integration/testdata/TestGolangIntegration/golang-project1/go.mod b/integration/testdata/TestGolangIntegration/golang-project1/go.mod index abe4430d88..c538e6fc76 100644 --- a/integration/testdata/TestGolangIntegration/golang-project1/go.mod +++ b/integration/testdata/TestGolangIntegration/golang-project1/go.mod @@ -1,5 +1,5 @@ module github.com/example/golang-app -go 1.22.4 +go 1.23.4 require github.com/gorilla/mux v1.8.0 diff --git a/integration/testdata/TestGolangIntegration/golang-project2/go.mod b/integration/testdata/TestGolangIntegration/golang-project2/go.mod index e0e21c40a1..d07e0384a1 100644 --- a/integration/testdata/TestGolangIntegration/golang-project2/go.mod +++ b/integration/testdata/TestGolangIntegration/golang-project2/go.mod @@ -1,3 +1,3 @@ module github.com/example/golang-app -go 1.22.4 +go 1.23.4 diff --git a/pkg/abap/build/bfw.go b/pkg/abap/build/bfw.go index 56801927d8..8ea81cb9d3 100644 --- a/pkg/abap/build/bfw.go +++ b/pkg/abap/build/bfw.go @@ -18,14 +18,14 @@ import ( // RunState : Current Status of the Build type RunState string -type resultState string +type ResultState string type msgty string const ( - successful resultState = "SUCCESSFUL" - warning resultState = "WARNING" - erroneous resultState = "ERRONEOUS" - aborted resultState = "ABORTED" + Successful ResultState = "SUCCESSFUL" + Warning ResultState = "WARNING" + Erroneous ResultState = "ERRONEOUS" + Aborted ResultState = "ABORTED" Initializing RunState = "INITIALIZING" // Initializing : Build Framework prepared Accepted RunState = "ACCEPTED" // Accepted : Build Framework triggered @@ -46,7 +46,7 @@ type jsonBuild struct { Build struct { BuildID string `json:"build_id"` RunState RunState `json:"run_state"` - ResultState resultState `json:"result_state"` + ResultState ResultState `json:"result_state"` Phase string `json:"phase"` Entitytype string `json:"entitytype"` Startedby string `json:"startedby"` @@ -68,7 +68,7 @@ type jsonTask struct { PluginClass string `json:"plugin_class"` StartedAt string `json:"started_at"` FinishedAt string `json:"finished_at"` - ResultState resultState `json:"result_state"` + ResultState ResultState `json:"result_state"` } type jsonLogs struct { @@ -96,7 +96,7 @@ type Build struct { Connector Connector BuildID string `json:"build_id"` RunState RunState `json:"run_state"` - ResultState resultState `json:"result_state"` + ResultState ResultState `json:"result_state"` Phase string `json:"phase"` Entitytype string `json:"entitytype"` Startedby string `json:"startedby"` @@ -114,7 +114,7 @@ type task struct { PluginClass string `json:"plugin_class"` StartedAt string `json:"started_at"` FinishedAt string `json:"finished_at"` - ResultState resultState `json:"result_state"` + ResultState ResultState `json:"result_state"` Logs []logStruct Results []Result } @@ -221,11 +221,11 @@ func (b *Build) EvaluteIfBuildSuccessful(treatWarningsAsError bool) error { if b.RunState == Failed { return errors.Errorf("Build ended with runState failed") } - if treatWarningsAsError && b.ResultState == warning { - return errors.Errorf("Build ended with resultState warning, setting to failed as configured") + if treatWarningsAsError && b.ResultState == Warning { + return errors.Errorf("Build ended with ResultState warning, setting to failed as configured") } - if (b.ResultState == aborted) || (b.ResultState == erroneous) { - return errors.Errorf("Build ended with resultState %s", b.ResultState) + if (b.ResultState == Aborted) || (b.ResultState == Erroneous) { + return errors.Errorf("Build ended with ResultState %s", b.ResultState) } return nil } diff --git a/pkg/abap/build/bfw_test.go b/pkg/abap/build/bfw_test.go index 25dc9888e3..6e455a34cb 100644 --- a/pkg/abap/build/bfw_test.go +++ b/pkg/abap/build/bfw_test.go @@ -193,7 +193,7 @@ func TestEvaluteIfBuildSuccessful(t *testing.T) { t.Run("No error", func(t *testing.T) { //arrange build.RunState = Finished - build.ResultState = successful + build.ResultState = Successful //act err := build.EvaluteIfBuildSuccessful(treatWarningsAsError) //assert @@ -210,7 +210,7 @@ func TestEvaluteIfBuildSuccessful(t *testing.T) { t.Run("ResultState aborted => Error", func(t *testing.T) { //arrange build.RunState = Finished - build.ResultState = aborted + build.ResultState = Aborted //act err := build.EvaluteIfBuildSuccessful(treatWarningsAsError) //assert @@ -219,7 +219,7 @@ func TestEvaluteIfBuildSuccessful(t *testing.T) { t.Run("ResultState erroneous => Error", func(t *testing.T) { //arrange build.RunState = Finished - build.ResultState = erroneous + build.ResultState = Erroneous //act err := build.EvaluteIfBuildSuccessful(treatWarningsAsError) //assert @@ -228,7 +228,7 @@ func TestEvaluteIfBuildSuccessful(t *testing.T) { t.Run("ResultState warning, treatWarningsAsError false => No error", func(t *testing.T) { //arrange build.RunState = Finished - build.ResultState = warning + build.ResultState = Warning //act err := build.EvaluteIfBuildSuccessful(treatWarningsAsError) //assert @@ -237,7 +237,7 @@ func TestEvaluteIfBuildSuccessful(t *testing.T) { t.Run("ResultState warning, treatWarningsAsError true => error", func(t *testing.T) { //arrange build.RunState = Finished - build.ResultState = warning + build.ResultState = Warning treatWarningsAsError = true //act err := build.EvaluteIfBuildSuccessful(treatWarningsAsError) diff --git a/pkg/blackduck/reporting.go b/pkg/blackduck/reporting.go index 960c0c3357..a1faa41f90 100644 --- a/pkg/blackduck/reporting.go +++ b/pkg/blackduck/reporting.go @@ -6,6 +6,7 @@ import ( "fmt" "path/filepath" "runtime" + "slices" "strings" "github.com/SAP/jenkins-library/pkg/format" @@ -89,12 +90,12 @@ func CreateSarifResultFile(vulns *Vulnerabilities, projectName, projectVersion, results = append(results, result) // append taxonomies - if len(v.VulnerabilityWithRemediation.CweID) > 0 && !piperutils.ContainsString(cweIdsForTaxonomies, v.VulnerabilityWithRemediation.CweID) { + if len(v.VulnerabilityWithRemediation.CweID) > 0 && !slices.Contains(cweIdsForTaxonomies, v.VulnerabilityWithRemediation.CweID) { cweIdsForTaxonomies = append(cweIdsForTaxonomies, v.VulnerabilityWithRemediation.CweID) } // only create rule on new CVE - if !piperutils.ContainsString(collectedRules, result.RuleID) { + if !slices.Contains(collectedRules, result.RuleID) { collectedRules = append(collectedRules, result.RuleID) // set information about BlackDuck project diff --git a/pkg/blackduck/reporting_test.go b/pkg/blackduck/reporting_test.go index e0c86bc35e..6e29d3c952 100644 --- a/pkg/blackduck/reporting_test.go +++ b/pkg/blackduck/reporting_test.go @@ -6,6 +6,7 @@ package blackduck import ( "fmt" "path/filepath" + "slices" "testing" "github.com/SAP/jenkins-library/pkg/format" @@ -132,13 +133,13 @@ func TestCreateSarifResultFile(t *testing.T) { collectedRules := []string{} for _, rule := range sarif.Runs[0].Tool.Driver.Rules { - piperutils.ContainsString(vulnerabilities, rule.ID) + slices.Contains(vulnerabilities, rule.ID) collectedRules = append(collectedRules, rule.ID) } collectedResults := []string{} for _, result := range sarif.Runs[0].Results { - piperutils.ContainsString(vulnerabilities, result.RuleID) + slices.Contains(vulnerabilities, result.RuleID) collectedResults = append(collectedResults, result.RuleID) } diff --git a/pkg/checkmarx/checkmarx.go b/pkg/checkmarx/checkmarx.go index e8c4c552df..bccc87a463 100644 --- a/pkg/checkmarx/checkmarx.go +++ b/pkg/checkmarx/checkmarx.go @@ -7,6 +7,7 @@ import ( "io" "net/http" "net/url" + "slices" "strconv" "strings" "time" @@ -15,7 +16,6 @@ import ( piperHttp "github.com/SAP/jenkins-library/pkg/http" "github.com/SAP/jenkins-library/pkg/log" - "github.com/SAP/jenkins-library/pkg/piperutils" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -301,7 +301,7 @@ func sendRequestInternal(sys *SystemInstance, method, url string, body io.Reader defer closer.Close() } response, err := sys.client.SendRequest(method, fmt.Sprintf("%v/cxrestapi%v", sys.serverURL, url), requestBody, header, nil) - if err != nil && (response == nil || !piperutils.ContainsInt(acceptedErrorCodes, response.StatusCode)) { + if err != nil && (response == nil || !slices.Contains(acceptedErrorCodes, response.StatusCode)) { sys.recordRequestDetailsInErrorCase(requestBodyCopy, response) sys.logger.Errorf("HTTP request failed with error: %s", err) return nil, err diff --git a/pkg/checkmarxone/checkmarxone.go b/pkg/checkmarxone/checkmarxone.go index 705aea76da..7f52275dda 100644 --- a/pkg/checkmarxone/checkmarxone.go +++ b/pkg/checkmarxone/checkmarxone.go @@ -8,13 +8,13 @@ import ( "net/http" "net/url" "os" + "slices" "strconv" "strings" "time" piperHttp "github.com/SAP/jenkins-library/pkg/http" "github.com/SAP/jenkins-library/pkg/log" - "github.com/SAP/jenkins-library/pkg/piperutils" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -410,7 +410,7 @@ func sendRequestInternal(sys *SystemInstance, method, url string, body io.Reader //header.Set("User-Agent", "Project-Piper.io cicd pipeline") // currently this causes some requests to fail due to unknown UA validation in the backend. response, err := sys.client.SendRequest(method, url, requestBody, header, nil) - if err != nil && (response == nil || !piperutils.ContainsInt(acceptedErrorCodes, response.StatusCode)) { + if err != nil && (response == nil || !slices.Contains(acceptedErrorCodes, response.StatusCode)) { var resBodyBytes []byte if response != nil && response.Body != nil { @@ -759,7 +759,7 @@ func (sys *SystemInstance) GetProjectsByName(projectName string) ([]Project, err var err error body := url.Values{} - body.Add("name", projectName) + body.Add("names", projectName) data, err = sendRequest(sys, http.MethodGet, fmt.Sprintf("/projects/?%v", body.Encode()), nil, header, []int{404}) @@ -1376,6 +1376,17 @@ func (sys *SystemInstance) RequestNewReportV2(scanID, reportType string) (string }, "filters": map[string][]string{ "scanners": {"sast"}, + "severities": { + "high", + "medium", + "low", + }, + "states": { + "to-verify", + "confirmed", + "urgent", + "proposed-not-exploitable", + }, }, "reportType": "ui", "fileFormat": reportType, diff --git a/pkg/checkmarxone/cxjson_to_sarif.go b/pkg/checkmarxone/cxjson_to_sarif.go index 7560eaebe5..345924ad56 100644 --- a/pkg/checkmarxone/cxjson_to_sarif.go +++ b/pkg/checkmarxone/cxjson_to_sarif.go @@ -67,6 +67,10 @@ func ConvertCxJSONToSarif(sys System, serverURL string, scanResults *[]ScanResul for k := 0; k < len(r.Data.Nodes); k++ { loc := *new(format.Location) loc.PhysicalLocation.ArtifactLocation.URI = r.Data.Nodes[0].FileName + // remove absolute path of file name (coming from JSON format) + if len(r.Data.Nodes[0].FileName) > 0 && r.Data.Nodes[0].FileName[0:1] == "/" { + loc.PhysicalLocation.ArtifactLocation.URI = r.Data.Nodes[0].FileName[1:] + } loc.PhysicalLocation.Region.StartLine = r.Data.Nodes[k].Line loc.PhysicalLocation.Region.EndLine = r.Data.Nodes[k].Line loc.PhysicalLocation.Region.StartColumn = r.Data.Nodes[k].Column @@ -91,6 +95,10 @@ func ConvertCxJSONToSarif(sys System, serverURL string, scanResults *[]ScanResul threadFlowLocation := *new(format.Locations) tfloc := new(format.Location) tfloc.PhysicalLocation.ArtifactLocation.URI = r.Data.Nodes[0].FileName + // remove absolute path of file name (coming from JSON format) + if len(r.Data.Nodes[0].FileName) > 0 && r.Data.Nodes[0].FileName[0:1] == "/" { + loc.PhysicalLocation.ArtifactLocation.URI = r.Data.Nodes[0].FileName[1:] + } tfloc.PhysicalLocation.Region.StartLine = r.Data.Nodes[k].Line tfloc.PhysicalLocation.Region.EndLine = r.Data.Nodes[k].Line tfloc.PhysicalLocation.Region.StartColumn = r.Data.Nodes[k].Column @@ -244,7 +252,7 @@ func ConvertCxJSONToSarif(sys System, serverURL string, scanResults *[]ScanResul log.Entry().Debug("[SARIF] Now handling driver object.") tool := *new(format.Tool) tool.Driver = *new(format.Driver) - tool.Driver.Name = "CheckmarxOne SCA" + tool.Driver.Name = "Checkmarx One" // TODO: a way to fetch/store the version tool.Driver.Version = "1" //strings.Split(cxxml.CheckmarxVersion, "V ") diff --git a/pkg/config/config.go b/pkg/config/config.go index c031b70fd0..99e7dda7be 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -11,7 +11,7 @@ import ( "regexp" "strings" - "github.com/SAP/jenkins-library/pkg/trustengine" + "github.com/SAP/jenkins-library/pkg/systemtrust" piperhttp "github.com/SAP/jenkins-library/pkg/http" "github.com/SAP/jenkins-library/pkg/log" @@ -33,7 +33,7 @@ type Config struct { accessTokens map[string]string openFile func(s string, t map[string]string) (io.ReadCloser, error) vaultCredentials VaultCredentials - trustEngineConfiguration trustengine.Configuration + systemTrustConfiguration systemtrust.Configuration } // StepConfig defines the structure for merged step configuration @@ -72,6 +72,10 @@ func (c *Config) ApplyAliasConfig(parameters []StepParameters, secrets []StepSec if c.Steps[stepName] != nil { c.Steps[stepName] = setParamValueFromAlias(stepName, c.Steps[stepName], filters.Steps, p.Name, p.Aliases) } + //copy stage configuration with Build name + if centralBuild, ok := c.Stages["Central Build"]; ok { + c.Stages["Build"] = centralBuild + } } for _, s := range secrets { c.General = setParamValueFromAlias(stepName, c.General, filters.General, s.Name, s.Aliases) @@ -81,6 +85,10 @@ func (c *Config) ApplyAliasConfig(parameters []StepParameters, secrets []StepSec if c.Steps[stepName] != nil { c.Steps[stepName] = setParamValueFromAlias(stepName, c.Steps[stepName], filters.Steps, s.Name, s.Aliases) } + //copy stage secrets configuration with Build name + if centralBuild, ok := c.Stages["Central Build"]; ok { + c.Stages["Build"] = centralBuild + } } } @@ -287,12 +295,12 @@ func (c *Config) GetStepConfig(flagValues map[string]interface{}, paramJSON stri } // hooks need to have been loaded from the defaults before the server URL is known - err = c.setTrustEngineConfiguration(stepConfig.HookConfig) + err = c.setSystemTrustConfiguration(stepConfig.HookConfig) if err != nil { - log.Entry().WithError(err).Debug("Trust Engine lookup skipped due to missing or incorrect configuration") + log.Entry().WithError(err).Debug("System Trust lookup skipped due to missing or incorrect configuration") } else { - trustengineClient := trustengine.PrepareClient(&piperhttp.Client{}, c.trustEngineConfiguration) - resolveAllTrustEngineReferences(&stepConfig, append(parameters, ReportingParameters.Parameters...), c.trustEngineConfiguration, trustengineClient) + systemTrustClient := systemtrust.PrepareClient(&piperhttp.Client{}, c.systemTrustConfiguration) + resolveAllSystemTrustReferences(&stepConfig, append(parameters, ReportingParameters.Parameters...), c.systemTrustConfiguration, systemTrustClient) } // finally do the condition evaluation post processing diff --git a/pkg/config/evaluation.go b/pkg/config/evaluation.go index 4482a2d296..af90ac9059 100644 --- a/pkg/config/evaluation.go +++ b/pkg/config/evaluation.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "path" + "slices" "strings" "github.com/pkg/errors" @@ -49,7 +50,7 @@ func (r *RunConfigV1) evaluateConditionsV1(config *Config, utils piperutils.File stepConfigCache := make(map[string]StepConfig, len(stage.Steps)) for _, step := range stage.Steps { // Consider only orchestrator-specific steps if the orchestrator limitation is set. - if len(step.Orchestrators) > 0 && !piperutils.ContainsString(step.Orchestrators, currentOrchestrator) { + if len(step.Orchestrators) > 0 && !slices.Contains(step.Orchestrators, currentOrchestrator) { continue } diff --git a/pkg/config/systemtrust.go b/pkg/config/systemtrust.go new file mode 100644 index 0000000000..fb333d6f29 --- /dev/null +++ b/pkg/config/systemtrust.go @@ -0,0 +1,66 @@ +package config + +import ( + "errors" + + piperhttp "github.com/SAP/jenkins-library/pkg/http" + "github.com/SAP/jenkins-library/pkg/log" + "github.com/SAP/jenkins-library/pkg/systemtrust" +) + +const RefTypeSystemTrustSecret = "systemTrustSecret" + +// resolveAllSystemTrustReferences retrieves all the step's secrets from the System Trust +func resolveAllSystemTrustReferences(config *StepConfig, params []StepParameters, systemTrustConfiguration systemtrust.Configuration, client *piperhttp.Client) { + for _, param := range params { + if ref := param.GetReference(RefTypeSystemTrustSecret); ref != nil { + if config.Config[param.Name] == "" { + log.Entry().Infof("Getting '%s' from System Trust", param.Name) + token, err := systemtrust.GetToken(ref.Default, client, systemTrustConfiguration) + if err != nil { + log.Entry().Info(" failed") + log.Entry().WithError(err).Debugf("Couldn't get '%s' token from System Trust", ref.Default) + continue + } + log.RegisterSecret(token) + config.Config[param.Name] = token + log.Entry().Info(" succeeded") + } else { + log.Entry().Debugf("Skipping retrieval of '%s' from System Trust: parameter already set", param.Name) + } + } + } +} + +// setSystemTrustConfiguration sets the server URL for the System Trust by taking it from the hooks +func (c *Config) setSystemTrustConfiguration(hookConfig map[string]interface{}) error { + systemTrustHook, ok := hookConfig["systemtrust"].(map[string]interface{}) + if !ok { + return errors.New("no System Trust hook configuration found") + } + if serverURL, ok := systemTrustHook["serverURL"].(string); ok { + c.systemTrustConfiguration.ServerURL = serverURL + } else { + return errors.New("no System Trust server URL found") + } + if tokenEndPoint, ok := systemTrustHook["tokenEndPoint"].(string); ok { + c.systemTrustConfiguration.TokenEndPoint = tokenEndPoint + } else { + return errors.New("no System Trust service endpoint found") + } + if tokenQueryParamName, ok := systemTrustHook["tokenQueryParamName"].(string); ok { + c.systemTrustConfiguration.TokenQueryParamName = tokenQueryParamName + } else { + return errors.New("no System Trust query parameter name found") + } + + if len(c.systemTrustConfiguration.Token) == 0 { + return errors.New("no System Trust token found and envvar is empty") + } + return nil +} + +// SetSystemTrustToken sets the token for the System Trust +func (c *Config) SetSystemTrustToken(token string) { + c.systemTrustConfiguration.Token = token +} diff --git a/pkg/config/trustengine_test.go b/pkg/config/systemtrust_test.go similarity index 71% rename from pkg/config/trustengine_test.go rename to pkg/config/systemtrust_test.go index c475a9e8b2..cd74b560fa 100644 --- a/pkg/config/trustengine_test.go +++ b/pkg/config/systemtrust_test.go @@ -5,17 +5,18 @@ package config import ( "fmt" - piperhttp "github.com/SAP/jenkins-library/pkg/http" - "github.com/SAP/jenkins-library/pkg/trustengine" - "github.com/jarcoal/httpmock" "net/http" "testing" + piperhttp "github.com/SAP/jenkins-library/pkg/http" + "github.com/SAP/jenkins-library/pkg/systemtrust" + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" ) const secretName = "sonar" -const secretNameInTrustEngine = "sonarTrustengineSecretName" +const secretNameInSystemTrust = "sonarSystemtrustSecretName" const testServerURL = "https://www.project-piper.io" const testTokenEndPoint = "tokens" const testTokenQueryParamName = "systems" @@ -24,14 +25,14 @@ const mockSonarToken = "mockSonarToken" var testFullURL = fmt.Sprintf("%s/%s?%s=", testServerURL, testTokenEndPoint, testTokenQueryParamName) var mockSingleTokenResponse = fmt.Sprintf("{\"sonar\": \"%s\"}", mockSonarToken) -func TestTrustEngineConfig(t *testing.T) { +func TestSystemTrustConfig(t *testing.T) { httpmock.Activate() defer httpmock.DeactivateAndReset() httpmock.RegisterResponder(http.MethodGet, testFullURL+"sonar", httpmock.NewStringResponder(200, mockSingleTokenResponse)) - stepParams := []StepParameters{createStepParam(secretName, RefTypeTrustengineSecret, secretNameInTrustEngine, secretName)} + stepParams := []StepParameters{createStepParam(secretName, RefTypeSystemTrustSecret, secretNameInSystemTrust, secretName)} - var trustEngineConfiguration = trustengine.Configuration{ + var systemTrustConfiguration = systemtrust.Configuration{ Token: "testToken", ServerURL: testServerURL, TokenEndPoint: testTokenEndPoint, @@ -40,33 +41,33 @@ func TestTrustEngineConfig(t *testing.T) { client := &piperhttp.Client{} client.SetOptions(piperhttp.ClientOptions{MaxRetries: -1, UseDefaultTransport: true}) - t.Run("Load secret from Trust Engine - secret not set yet by Vault or config.yml", func(t *testing.T) { + t.Run("Load secret from System Trust - secret not set yet by Vault or config.yml", func(t *testing.T) { stepConfig := &StepConfig{Config: map[string]interface{}{ secretName: "", }} - resolveAllTrustEngineReferences(stepConfig, stepParams, trustEngineConfiguration, client) + resolveAllSystemTrustReferences(stepConfig, stepParams, systemTrustConfiguration, client) assert.Equal(t, mockSonarToken, stepConfig.Config[secretName]) }) - t.Run("Load secret from Trust Engine - secret already by Vault or config.yml", func(t *testing.T) { + t.Run("Load secret from System Trust - secret already by Vault or config.yml", func(t *testing.T) { stepConfig := &StepConfig{Config: map[string]interface{}{ secretName: "aMockTokenFromVault", }} - resolveAllTrustEngineReferences(stepConfig, stepParams, trustEngineConfiguration, client) + resolveAllSystemTrustReferences(stepConfig, stepParams, systemTrustConfiguration, client) assert.NotEqual(t, mockSonarToken, stepConfig.Config[secretName]) }) } -func createStepParam(name, refType, trustengineSecretNameProperty, defaultSecretNameName string) StepParameters { +func createStepParam(name, refType, systemTrustSecretNameProperty, defaultSecretNameName string) StepParameters { return StepParameters{ Name: name, Aliases: []Alias{}, ResourceRef: []ResourceReference{ { Type: refType, - Name: trustengineSecretNameProperty, + Name: systemTrustSecretNameProperty, Default: defaultSecretNameName, }, }, diff --git a/pkg/config/trustengine.go b/pkg/config/trustengine.go deleted file mode 100644 index 144804c18c..0000000000 --- a/pkg/config/trustengine.go +++ /dev/null @@ -1,67 +0,0 @@ -package config - -import ( - "errors" - - piperhttp "github.com/SAP/jenkins-library/pkg/http" - "github.com/SAP/jenkins-library/pkg/log" - "github.com/SAP/jenkins-library/pkg/trustengine" -) - -// const RefTypeTrustengineSecretFile = "trustengineSecretFile" -const RefTypeTrustengineSecret = "trustengineSecret" - -// resolveAllTrustEngineReferences retrieves all the step's secrets from the Trust Engine -func resolveAllTrustEngineReferences(config *StepConfig, params []StepParameters, trustEngineConfiguration trustengine.Configuration, client *piperhttp.Client) { - for _, param := range params { - if ref := param.GetReference(RefTypeTrustengineSecret); ref != nil { - if config.Config[param.Name] == "" { - log.Entry().Infof("Getting '%s' from Trust Engine", param.Name) - token, err := trustengine.GetToken(ref.Default, client, trustEngineConfiguration) - if err != nil { - log.Entry().Info(" failed") - log.Entry().WithError(err).Debugf("Couldn't get '%s' token from Trust Engine", ref.Default) - continue - } - log.RegisterSecret(token) - config.Config[param.Name] = token - log.Entry().Info(" succeeded") - } else { - log.Entry().Debugf("Skipping retrieval of '%s' from Trust Engine: parameter already set", param.Name) - } - } - } -} - -// setTrustEngineConfiguration sets the server URL for the Trust Engine by taking it from the hooks -func (c *Config) setTrustEngineConfiguration(hookConfig map[string]interface{}) error { - trustEngineHook, ok := hookConfig["trustengine"].(map[string]interface{}) - if !ok { - return errors.New("no Trust Engine hook configuration found") - } - if serverURL, ok := trustEngineHook["serverURL"].(string); ok { - c.trustEngineConfiguration.ServerURL = serverURL - } else { - return errors.New("no Trust Engine server URL found") - } - if tokenEndPoint, ok := trustEngineHook["tokenEndPoint"].(string); ok { - c.trustEngineConfiguration.TokenEndPoint = tokenEndPoint - } else { - return errors.New("no Trust Engine service endpoint found") - } - if tokenQueryParamName, ok := trustEngineHook["tokenQueryParamName"].(string); ok { - c.trustEngineConfiguration.TokenQueryParamName = tokenQueryParamName - } else { - return errors.New("no Trust Engine query parameter name found") - } - - if len(c.trustEngineConfiguration.Token) == 0 { - log.Entry().Debug("no Trust Engine token found") - } - return nil -} - -// SetTrustEngineToken sets the token for the Trust Engine -func (c *Config) SetTrustEngineToken(token string) { - c.trustEngineConfiguration.Token = token -} diff --git a/pkg/docker/docker.go b/pkg/docker/docker.go index d4f757e00c..30e287abf4 100644 --- a/pkg/docker/docker.go +++ b/pkg/docker/docker.go @@ -9,6 +9,7 @@ import ( "path" "path/filepath" "regexp" + "slices" "strings" "github.com/docker/cli/cli/config" @@ -306,7 +307,7 @@ func ImageListWithFilePath(imageName string, excludes []string, trimDir string, // ToDo: needs rework // dockerfilePath = strings.ReplaceAll(dockerfilePath, cwd, ".") - if piperutils.ContainsString(excludes, dockerfilePath) { + if slices.Contains(excludes, dockerfilePath) { log.Entry().Infof("Discard %v since it is in the exclude list %v", dockerfilePath, excludes) continue } diff --git a/pkg/documentation/generator.go b/pkg/documentation/generator.go index 7f595aeb63..5e601068a4 100644 --- a/pkg/documentation/generator.go +++ b/pkg/documentation/generator.go @@ -32,12 +32,13 @@ func main() { var docTemplatePath string var customLibraryStepFile string var customDefaultFiles sliceFlags - var includeAzure bool + var includeAzure, includeGHA bool flag.StringVar(&metadataPath, "metadataDir", "./resources/metadata", "The directory containing the step metadata. Default points to \\'resources/metadata\\'.") flag.StringVar(&docTemplatePath, "docuDir", "./documentation/docs/steps/", "The directory containing the docu stubs. Default points to \\'documentation/docs/steps/\\'.") flag.StringVar(&customLibraryStepFile, "customLibraryStepFile", "", "") flag.Var(&customDefaultFiles, "customDefaultFile", "Path to a custom default configuration file.") flag.BoolVar(&includeAzure, "includeAzure", false, "Include Azure-specifics in step documentation.") + flag.BoolVar(&includeGHA, "includeGHA", false, "Include GitHub Actions-specifics in step documentation.") // flags for stage documentation var generateStageConfig bool @@ -85,7 +86,7 @@ func main() { OpenDocTemplateFile: openDocTemplateFile, DocFileWriter: writeFile, OpenFile: openFile, - }, includeAzure) + }, includeAzure, includeGHA) checkError(err) } } diff --git a/pkg/documentation/generator/description.go b/pkg/documentation/generator/description.go index 9d2301cedd..022833caae 100644 --- a/pkg/documentation/generator/description.go +++ b/pkg/documentation/generator/description.go @@ -13,7 +13,8 @@ const ( headlineUsage = "## Usage\n\n" headlineJenkinsPipeline = " === \"Jenkins\"\n\n" headlineCommandLine = " === \"Command Line\"\n\n" - headlineAzure = " === \"Azure\"\n\n" + headlineAzure = " === \"Azure DevOps\"\n\n" + headlineGHA = " === \"GitHub Actions\"\n\n" spacingTabBox = " " ) @@ -28,10 +29,10 @@ var CustomLibrarySteps = []CustomLibrary{} // CustomLibrary represents a custom library with it's custom step names, binary name and library name. type CustomLibrary struct { - Name string `yaml: "name,omitempty"` - BinaryName string `yaml: "binaryName,omitempty"` - LibraryName string `yaml: "libraryName,omitempty"` - Steps []string `yaml: "steps,omitempty"` + Name string `yaml:"name,omitempty"` + BinaryName string `yaml:"binaryName,omitempty"` + LibraryName string `yaml:"libraryName,omitempty"` + Steps []string `yaml:"steps,omitempty"` } // Replaces the StepName placeholder with the content from the yaml @@ -64,6 +65,20 @@ func createDescriptionSection(stepData *config.StepData) string { description += fmt.Sprintf("%v name: %v\n", spacingTabBox, stepData.Metadata.Name) description += fmt.Sprintf("%v inputs:\n", spacingTabBox) description += fmt.Sprintf("%v stepName: %v\n", spacingTabBox, stepData.Metadata.Name) + description += fmt.Sprintf("%v flags: --anyStepParameter\n", spacingTabBox) + description += fmt.Sprintf("%v```\n\n", spacingTabBox) + } + + // add GiHub Actions specific information if activated + if includeGHA { + description += headlineGHA + description += fmt.Sprintf("%v```\n", spacingTabBox) + description += fmt.Sprintf("%vsteps:\n", spacingTabBox) + description += fmt.Sprintf("%v - uses: SAP/project-piper-action@releaseCommitSHA\n", spacingTabBox) + description += fmt.Sprintf("%v name: %v\n", spacingTabBox, stepData.Metadata.Name) + description += fmt.Sprintf("%v with:\n", spacingTabBox) + description += fmt.Sprintf("%v step-name: %v\n", spacingTabBox, stepData.Metadata.Name) + description += fmt.Sprintf("%v flags: --anyStepParameter\n", spacingTabBox) description += fmt.Sprintf("%v```\n\n", spacingTabBox) } diff --git a/pkg/documentation/generator/main.go b/pkg/documentation/generator/main.go index 77328c2392..067ffd3cc7 100644 --- a/pkg/documentation/generator/main.go +++ b/pkg/documentation/generator/main.go @@ -25,7 +25,7 @@ type DocuHelperData struct { } var stepParameterNames []string -var includeAzure bool +var includeAzure, includeGHA bool func readStepConfiguration(stepMetadata config.StepData, customDefaultFiles []string, docuHelperData DocuHelperData) config.StepConfig { filters := stepMetadata.GetParameterFilters() @@ -58,8 +58,9 @@ func readStepConfiguration(stepMetadata config.StepData, customDefaultFiles []st } // GenerateStepDocumentation generates step coding based on step configuration provided in yaml files -func GenerateStepDocumentation(metadataFiles []string, customDefaultFiles []string, docuHelperData DocuHelperData, azure bool) error { +func GenerateStepDocumentation(metadataFiles []string, customDefaultFiles []string, docuHelperData DocuHelperData, azure bool, githubAction bool) error { includeAzure = azure + includeGHA = githubAction for key := range metadataFiles { stepMetadata := readStepMetadata(metadataFiles[key], docuHelperData) diff --git a/pkg/documentation/generator/parameters.go b/pkg/documentation/generator/parameters.go index 1c9e9f6848..734cab1128 100644 --- a/pkg/documentation/generator/parameters.go +++ b/pkg/documentation/generator/parameters.go @@ -13,10 +13,12 @@ const ( vaultBadge = "![Vault](https://img.shields.io/badge/-Vault-lightgrey)" jenkinsOnlyBadge = "![Jenkins only](https://img.shields.io/badge/-Jenkins%20only-yellowgreen)" secretBadge = "![Secret](https://img.shields.io/badge/-Secret-yellowgreen)" - trustengineBadge = "![Trust Engine](https://img.shields.io/badge/-Trust%20Engine-lightblue)" + systemTrustBadge = "![System Trust](https://img.shields.io/badge/-System%20Trust-lightblue)" deprecatedBadge = "![deprecated](https://img.shields.io/badge/-deprecated-red)" ) +var jenkinsParams = []string{"containerCommand", "containerName", "containerShell", "dockerVolumeBind", "dockerWorkspace", "sidecarReadyCommand", "sidecarWorkspace", "stashContent"} + // Replaces the Parameters placeholder with the content from the yaml func createParametersSection(stepData *config.StepData) string { @@ -97,7 +99,6 @@ func parameterFurtherInfo(paramName string, stepData *config.StepData, execution } // handle non-step parameters (e.g. Jenkins-specific parameters as well as execution environment parameters) - jenkinsParams := []string{"containerCommand", "containerName", "containerShell", "dockerVolumeBind", "dockerWorkspace", "sidecarReadyCommand", "sidecarWorkspace", "stashContent"} if !contains(stepParameterNames, paramName) { for _, secret := range stepData.Spec.Inputs.Secrets { if paramName == secret.Name && secret.Type == "jenkins" { @@ -121,9 +122,9 @@ func parameterFurtherInfo(paramName string, stepData *config.StepData, execution secretInfo := fmt.Sprintf("%s pass via ENV or Jenkins credentials", secretBadge) isVaultSecret := param.GetReference("vaultSecret") != nil || param.GetReference("vaultSecretFile") != nil - isTrustengineSecret := param.GetReference(config.RefTypeTrustengineSecret) != nil - if isVaultSecret && isTrustengineSecret { - secretInfo = fmt.Sprintf(" %s %s %s pass via ENV, Vault, Trust Engine or Jenkins credentials", vaultBadge, trustengineBadge, secretBadge) + isSystemTrustSecret := param.GetReference(config.RefTypeSystemTrustSecret) != nil + if isVaultSecret && isSystemTrustSecret { + secretInfo = fmt.Sprintf(" %s %s %s pass via ENV, Vault, System Trust or Jenkins credentials", vaultBadge, systemTrustBadge, secretBadge) } else if isVaultSecret { secretInfo = fmt.Sprintf(" %s %s pass via ENV, Vault or Jenkins credentials", vaultBadge, secretBadge) } @@ -161,7 +162,7 @@ func createParameterDetails(stepData *config.StepData) string { for _, param := range stepData.Spec.Inputs.Parameters { details += fmt.Sprintf("#### %v\n\n", param.Name) - if !contains(stepParameterNames, param.Name) { + if !contains(stepParameterNames, param.Name) && contains(jenkinsParams, param.Name) { details += "**Jenkins-specific:** Used for proper environment setup.\n\n" } @@ -200,7 +201,7 @@ func createParameterDetails(stepData *config.StepData) string { for _, secret := range stepData.Spec.Inputs.Secrets { details += fmt.Sprintf("#### %v\n\n", secret.Name) - if !contains(stepParameterNames, secret.Name) { + if !contains(stepParameterNames, secret.Name) && contains(jenkinsParams, secret.Name) { details += "**Jenkins-specific:** Used for proper environment setup. See *[using credentials](https://www.jenkins.io/doc/book/using/using-credentials/)* for details.\n\n" } @@ -346,8 +347,8 @@ func resourceReferenceDetails(resourceRef []config.ResourceReference) string { resourceDetails = addVaultResourceDetails(resource, resourceDetails) continue } - if resource.Type == config.RefTypeTrustengineSecret { - resourceDetails = addTrustEngineResourceDetails(resource, resourceDetails) + if resource.Type == config.RefTypeSystemTrustSecret { + resourceDetails = addSystemTrustResourceDetails(resource, resourceDetails) } } @@ -368,8 +369,8 @@ func addVaultResourceDetails(resource config.ResourceReference, resourceDetails return resourceDetails } -func addTrustEngineResourceDetails(resource config.ResourceReference, resourceDetails string) string { - resourceDetails += "
Trust Engine resource:
" +func addSystemTrustResourceDetails(resource config.ResourceReference, resourceDetails string) string { + resourceDetails += "
System Trust resource:
" resourceDetails += fmt.Sprintf("  name: `%v`
", resource.Name) resourceDetails += fmt.Sprintf("  value: `%v`
", resource.Default) diff --git a/pkg/fortify/fortify.go b/pkg/fortify/fortify.go index 6d03e8e3fd..58952311d2 100644 --- a/pkg/fortify/fortify.go +++ b/pkg/fortify/fortify.go @@ -8,6 +8,7 @@ import ( "net/http" "net/url" "os" + "slices" "strings" "time" @@ -30,7 +31,6 @@ import ( piperHttp "github.com/SAP/jenkins-library/pkg/http" "github.com/SAP/jenkins-library/pkg/log" - "github.com/SAP/jenkins-library/pkg/piperutils" "github.com/go-openapi/runtime" "github.com/go-openapi/strfmt" @@ -529,7 +529,7 @@ func (sys *SystemInstance) ReduceIssueFilterSelectorSet(issueFilterSelectorSet * groupingList := []*models.IssueSelector{} if issueFilterSelectorSet.GroupBySet != nil { for _, group := range issueFilterSelectorSet.GroupBySet { - if piperutils.ContainsString(names, *group.DisplayName) { + if slices.Contains(names, *group.DisplayName) { log.Entry().Debugf("adding new grouping '%v' to reduced list", *group.DisplayName) groupingList = append(groupingList, group) } @@ -538,7 +538,7 @@ func (sys *SystemInstance) ReduceIssueFilterSelectorSet(issueFilterSelectorSet * filterList := []*models.IssueFilterSelector{} if issueFilterSelectorSet.FilterBySet != nil { for _, filter := range issueFilterSelectorSet.FilterBySet { - if piperutils.ContainsString(names, filter.DisplayName) { + if slices.Contains(names, filter.DisplayName) { newFilter := &models.IssueFilterSelector{} newFilter.DisplayName = filter.DisplayName newFilter.Description = filter.Description @@ -548,7 +548,7 @@ func (sys *SystemInstance) ReduceIssueFilterSelectorSet(issueFilterSelectorSet * newFilter.Value = filter.Value newFilter.SelectorOptions = []*models.SelectorOption{} for _, option := range filter.SelectorOptions { - if (nil != options && piperutils.ContainsString(options, option.DisplayName)) || options == nil || len(options) == 0 { + if (nil != options && slices.Contains(options, option.DisplayName)) || options == nil || len(options) == 0 { log.Entry().Debugf("adding selector option '%v' to list for filter selector '%v'", option.DisplayName, newFilter.DisplayName) newFilter.SelectorOptions = append(newFilter.SelectorOptions, option) } diff --git a/pkg/generator/helper/helper.go b/pkg/generator/helper/helper.go index 00301040e4..1a29d49a3c 100644 --- a/pkg/generator/helper/helper.go +++ b/pkg/generator/helper/helper.go @@ -7,11 +7,11 @@ import ( "os" "path/filepath" "reflect" + "slices" "strings" "text/template" "github.com/Masterminds/sprig" - "github.com/SAP/jenkins-library/pkg/config" "github.com/SAP/jenkins-library/pkg/piperutils" ) @@ -924,7 +924,7 @@ func mustUniqName(list []config.StepParameters) ([]config.StepParameters, error) var item config.StepParameters for i := 0; i < l; i++ { item = l2.Index(i).Interface().(config.StepParameters) - if !piperutils.ContainsString(names, item.Name) { + if !slices.Contains(names, item.Name) { names = append(names, item.Name) dest = append(dest, item) } diff --git a/pkg/maven/model.go b/pkg/maven/model.go index 2a4f9b74b2..9c5d72c273 100644 --- a/pkg/maven/model.go +++ b/pkg/maven/model.go @@ -3,8 +3,8 @@ package maven import ( "encoding/xml" "fmt" - "github.com/SAP/jenkins-library/pkg/piperutils" "path/filepath" + "slices" ) // Project describes the Maven object model. @@ -71,7 +71,7 @@ type visitUtils interface { // VisitAllMavenModules ... func VisitAllMavenModules(path string, utils visitUtils, excludes []string, callback func(info ModuleInfo) error) error { pomXMLPath := filepath.Join(path, "pom.xml") - if piperutils.ContainsString(excludes, pomXMLPath) { + if slices.Contains(excludes, pomXMLPath) { return nil } diff --git a/pkg/maven/settings.go b/pkg/maven/settings.go index 151b516ca9..880039a08a 100644 --- a/pkg/maven/settings.go +++ b/pkg/maven/settings.go @@ -218,7 +218,7 @@ func addServerTagtoProjectSettingsXML(projectSettingsFile string, altDeploymentR settingsXml, err := xml.MarshalIndent(projectSettings, "", " ") if err != nil { - fmt.Errorf("failed to marshal maven project settings xml: %w", err) + return fmt.Errorf("failed to marshal maven project settings xml: %w", err) } settingsXmlString := string(settingsXml) Replacer := strings.NewReplacer(" ", "", " ", "") @@ -226,12 +226,11 @@ func addServerTagtoProjectSettingsXML(projectSettingsFile string, altDeploymentR xmlstring := []byte(xml.Header + settingsXmlString) - err = utils.FileWrite(projectSettingsFile, xmlstring, 0777) - if err != nil { - fmt.Errorf("failed to write maven Settings xml: %w", err) + if err = utils.FileWrite(projectSettingsFile, xmlstring, 0777); err != nil { + return fmt.Errorf("failed to write maven Settings xml: %w", err) } - log.Entry().Infof("Successfully updated details in maven project settings file : '%s'", projectSettingsFile) + log.Entry().Infof("Successfully updated details in maven project settings file : '%s'", projectSettingsFile) return nil } diff --git a/pkg/mock/fileUtils.go b/pkg/mock/fileUtils.go index b8d13ff6cd..3c368aa67a 100644 --- a/pkg/mock/fileUtils.go +++ b/pkg/mock/fileUtils.go @@ -13,11 +13,11 @@ import ( "io" "os" "path/filepath" + "slices" "sort" "strings" "time" - "github.com/SAP/jenkins-library/pkg/piperutils" "github.com/bmatcuk/doublestar" ) @@ -158,13 +158,13 @@ func (f *FilesMock) HasFile(path string) bool { // HasRemovedFile returns true if the virtual file system at one point contained an entry for the given path, // and it was removed via FileRemove(). func (f *FilesMock) HasRemovedFile(path string) bool { - return piperutils.ContainsString(f.removedFiles, f.toAbsPath(path)) + return slices.Contains(f.removedFiles, f.toAbsPath(path)) } // HasWrittenFile returns true if the virtual file system at one point contained an entry for the given path, // and it was written via FileWrite(). func (f *FilesMock) HasWrittenFile(path string) bool { - return piperutils.ContainsString(f.writtenFiles, f.toAbsPath(path)) + return slices.Contains(f.writtenFiles, f.toAbsPath(path)) } // HasCopiedFile returns true if the virtual file system at one point contained an entry for the given source and destination, diff --git a/pkg/multiarch/multiarch.go b/pkg/multiarch/multiarch.go index ce9c6cfa00..be2291651f 100644 --- a/pkg/multiarch/multiarch.go +++ b/pkg/multiarch/multiarch.go @@ -3,10 +3,10 @@ package multiarch import ( "fmt" "regexp" + "slices" "strings" "github.com/SAP/jenkins-library/pkg/log" - "github.com/SAP/jenkins-library/pkg/piperutils" ) var knownGoos = []string{"aix", "android", "darwin", "dragonfly", "freebsd", "hurd", "illumos", "ios", "js", "linux", "nacl", "netbsd", "openbsd", "plan9", "solaris", "windows", "zos"} @@ -42,13 +42,13 @@ func ParsePlatformString(s string) (Platform, error) { p.OS = strings.Trim(matches[1], " ") - if !piperutils.ContainsString(knownGoos, p.OS) { + if !slices.Contains(knownGoos, p.OS) { log.Entry().Warningf("OS '%s' is unknown to us", p.OS) } p.Arch = strings.Trim(matches[2], " ") - if !piperutils.ContainsString(knownGoarch, p.Arch) { + if !slices.Contains(knownGoarch, p.Arch) { log.Entry().Warningf("Architecture '%s' is unknown to us", p.Arch) } diff --git a/pkg/npm/publish.go b/pkg/npm/publish.go index a5626281b3..212d62cf84 100644 --- a/pkg/npm/publish.go +++ b/pkg/npm/publish.go @@ -16,8 +16,8 @@ import ( ) type npmMinimalPackageDescriptor struct { - Name string `json:version` - Version string `json:version` + Name string `json:"name"` + Version string `json:"version"` } func (pd *npmMinimalPackageDescriptor) Scope() string { diff --git a/pkg/npm/publish_test.go b/pkg/npm/publish_test.go index bdbdf8b655..a08d7e7db6 100644 --- a/pkg/npm/publish_test.go +++ b/pkg/npm/publish_test.go @@ -6,11 +6,11 @@ package npm import ( "io" "path/filepath" + "slices" "testing" "github.com/SAP/jenkins-library/pkg/mock" - "github.com/SAP/jenkins-library/pkg/piperutils" "github.com/SAP/jenkins-library/pkg/versioning" "github.com/stretchr/testify/assert" ) @@ -548,12 +548,12 @@ func TestNpmPublish(t *testing.T) { assert.Equal(t, "publish", publishCmd.Params[0]) if len(test.wants.tarballPath) > 0 && assert.Contains(t, publishCmd.Params, "--tarball") { - tarballPath := publishCmd.Params[piperutils.FindString(publishCmd.Params, "--tarball")+1] + tarballPath := publishCmd.Params[slices.Index(publishCmd.Params, "--tarball")+1] assert.Equal(t, test.wants.tarballPath, filepath.ToSlash(tarballPath)) } if assert.Contains(t, publishCmd.Params, "--userconfig") { - effectivePublishConfigPath := publishCmd.Params[piperutils.FindString(publishCmd.Params, "--userconfig")+1] + effectivePublishConfigPath := publishCmd.Params[slices.Index(publishCmd.Params, "--userconfig")+1] assert.Regexp(t, test.wants.publishConfigPath, filepath.ToSlash(effectivePublishConfigPath)) diff --git a/pkg/orchestrator/jenkins.go b/pkg/orchestrator/jenkins.go index 9844e943dc..3f80a0cee0 100644 --- a/pkg/orchestrator/jenkins.go +++ b/pkg/orchestrator/jenkins.go @@ -249,6 +249,8 @@ func (j *jenkinsConfigProvider) GitReference() string { return ref } else if strings.Contains(ref, "PR") { return "refs/pull/" + strings.Split(ref, "-")[1] + "/head" + } else if strings.HasPrefix(ref, "refs/") { + return ref } else { return "refs/heads/" + ref } diff --git a/pkg/orchestrator/jenkins_test.go b/pkg/orchestrator/jenkins_test.go index 15da691553..d9bd7d2cae 100644 --- a/pkg/orchestrator/jenkins_test.go +++ b/pkg/orchestrator/jenkins_test.go @@ -6,14 +6,13 @@ package orchestrator import ( "encoding/json" "fmt" + "net/http" "os" "testing" "time" "github.com/pkg/errors" - "net/http" - piperhttp "github.com/SAP/jenkins-library/pkg/http" "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" @@ -40,6 +39,26 @@ func TestJenkins(t *testing.T) { assert.Equal(t, "Jenkins", p.OrchestratorType()) }) + t.Run("TagBuild", func(t *testing.T) { + defer resetEnv(os.Environ()) + os.Clearenv() + os.Setenv("JENKINS_URL", "FOO BAR BAZ") + os.Setenv("BUILD_URL", "https://jaas.url/job/foo/job/bar/job/main/1234/") + os.Setenv("BRANCH_NAME", "refs/tags/rel-1.0.0") + os.Setenv("GIT_COMMIT", "abcdef42713") + os.Setenv("GIT_URL", "github.com/foo/bar") + + p := &jenkinsConfigProvider{} + + assert.False(t, p.IsPullRequest()) + assert.Equal(t, "https://jaas.url/job/foo/job/bar/job/main/1234/", p.BuildURL()) + assert.Equal(t, "refs/tags/rel-1.0.0", p.Branch()) + assert.Equal(t, "refs/tags/rel-1.0.0", p.GitReference()) + assert.Equal(t, "abcdef42713", p.CommitSHA()) + assert.Equal(t, "github.com/foo/bar", p.RepoURL()) + assert.Equal(t, "Jenkins", p.OrchestratorType()) + }) + t.Run("PR", func(t *testing.T) { defer resetEnv(os.Environ()) os.Clearenv() diff --git a/pkg/piperutils/maps_test.go b/pkg/piperutils/maps_test.go index f36ab43f5c..af8472ecb0 100644 --- a/pkg/piperutils/maps_test.go +++ b/pkg/piperutils/maps_test.go @@ -4,6 +4,7 @@ package piperutils import ( + "slices" "testing" "github.com/stretchr/testify/assert" @@ -15,10 +16,10 @@ func TestKeys(t *testing.T) { intList := Keys(intStringMap) assert.Equal(t, 4, len(intList)) - assert.Equal(t, true, ContainsInt(intList, 1)) - assert.Equal(t, true, ContainsInt(intList, 2)) - assert.Equal(t, true, ContainsInt(intList, 3)) - assert.Equal(t, true, ContainsInt(intList, 4)) + assert.Equal(t, true, slices.Contains(intList, 1)) + assert.Equal(t, true, slices.Contains(intList, 2)) + assert.Equal(t, true, slices.Contains(intList, 3)) + assert.Equal(t, true, slices.Contains(intList, 4)) } func TestValues(t *testing.T) { @@ -27,8 +28,8 @@ func TestValues(t *testing.T) { intList := Values(intStringMap) assert.Equal(t, 4, len(intList)) - assert.Equal(t, true, ContainsString(intList, "eins")) - assert.Equal(t, true, ContainsString(intList, "zwei")) - assert.Equal(t, true, ContainsString(intList, "drei")) - assert.Equal(t, true, ContainsString(intList, "vier")) + assert.Equal(t, true, slices.Contains(intList, "eins")) + assert.Equal(t, true, slices.Contains(intList, "zwei")) + assert.Equal(t, true, slices.Contains(intList, "drei")) + assert.Equal(t, true, slices.Contains(intList, "vier")) } diff --git a/pkg/piperutils/slices.go b/pkg/piperutils/slices.go index 5b7ea72131..c5f7bbf49b 100644 --- a/pkg/piperutils/slices.go +++ b/pkg/piperutils/slices.go @@ -5,32 +5,6 @@ import ( "strings" ) -// ContainsInt checks whether the element is part of the slice -func ContainsInt(s []int, e int) bool { - for _, a := range s { - if a == e { - return true - } - } - return false -} - -// ContainsString checks whether the element is part of the slice -func ContainsString(s []string, e string) bool { - return FindString(s, e) >= 0 -} - -// FindString returns the position of element e in the given slice or -1 if it's not in -func FindString(s []string, e string) int { - for i, a := range s { - if a == e { - return i - } - } - - return -1 -} - // ContainsStringPart checks whether the element is contained as part of one of the elements of the slice func ContainsStringPart(s []string, part string) bool { for _, a := range s { @@ -43,14 +17,14 @@ func ContainsStringPart(s []string, part string) bool { // RemoveAll removes all instances of element from the slice and returns a truncated slice as well as // a boolean to indicate whether at least one element was found and removed. -func RemoveAll(s []string, e string) ([]string, bool) { - var r []string - for _, a := range s { - if a != e { - r = append(r, a) +func RemoveAll(arr []string, item string) ([]string, bool) { + res := make([]string, 0, len(arr)) + for _, a := range arr { + if a != item { + res = append(res, a) } } - return r, len(s) != len(r) + return res, len(arr) != len(res) } // Prefix adds a prefix to each element of the slice diff --git a/pkg/piperutils/slices_test.go b/pkg/piperutils/slices_test.go index bd10429153..fd156ad019 100644 --- a/pkg/piperutils/slices_test.go +++ b/pkg/piperutils/slices_test.go @@ -9,41 +9,6 @@ import ( "github.com/stretchr/testify/assert" ) -func TestContainsInt(t *testing.T) { - var intList []int - assert.Equal(t, false, ContainsInt(intList, 4)) - - intList = append(intList, 1, 2, 3, 4, 5, 6, 20) - assert.Equal(t, true, ContainsInt(intList, 20)) - assert.Equal(t, true, ContainsInt(intList, 1)) - assert.Equal(t, true, ContainsInt(intList, 4)) - assert.Equal(t, false, ContainsInt(intList, 13)) -} - -func TestContainsString(t *testing.T) { - var stringList []string - assert.False(t, ContainsString(stringList, "test")) - assert.False(t, ContainsString(stringList, "")) - - stringList = append(stringList, "", "foo", "bar", "foo") - assert.True(t, ContainsString(stringList, "")) - assert.True(t, ContainsString(stringList, "bar")) - assert.True(t, ContainsString(stringList, "foo")) - assert.False(t, ContainsString(stringList, "baz")) -} - -func TestFindString(t *testing.T) { - var stringList []string - assert.Equal(t, -1, FindString(stringList, "test")) - assert.Equal(t, -1, FindString(stringList, "")) - - stringList = append(stringList, "", "foo", "bar", "foo") - assert.Equal(t, 0, FindString(stringList, "")) - assert.Equal(t, 2, FindString(stringList, "bar")) - assert.Equal(t, 1, FindString(stringList, "foo")) - assert.Equal(t, -1, FindString(stringList, "baz")) -} - func TestRemoveAll(t *testing.T) { t.Parallel() t.Run("empty array", func(t *testing.T) { diff --git a/pkg/trustengine/trustengine.go b/pkg/systemtrust/systemtrust.go similarity index 58% rename from pkg/trustengine/trustengine.go rename to pkg/systemtrust/systemtrust.go index 99caf500ae..637fa598f3 100644 --- a/pkg/trustengine/trustengine.go +++ b/pkg/systemtrust/systemtrust.go @@ -1,4 +1,4 @@ -package trustengine +package systemtrust import ( "encoding/json" @@ -32,30 +32,30 @@ type Configuration struct { } // GetToken requests a single token -func GetToken(refName string, client *piperhttp.Client, trustEngineConfiguration Configuration) (string, error) { - secrets, err := GetSecrets([]string{refName}, client, trustEngineConfiguration) +func GetToken(refName string, client *piperhttp.Client, systemTrustConfiguration Configuration) (string, error) { + secrets, err := getSecrets([]string{refName}, client, systemTrustConfiguration) if err != nil { - return "", errors.Wrap(err, "couldn't get token from trust engine") + return "", errors.Wrap(err, "couldn't get token from System Trust") } for _, s := range secrets { if s.System == refName { return s.Token, nil } } - return "", errors.New("could not find token in trust engine response") + return "", errors.New("could not find token in System Trust response") } -// GetSecrets transforms the trust engine JSON response into trust engine secrets, and can be used to request multiple tokens -func GetSecrets(refNames []string, client *piperhttp.Client, trustEngineConfiguration Configuration) ([]Secret, error) { +// getSecrets transforms the System Trust JSON response into System Trust secrets, and can be used to request multiple tokens +func getSecrets(refNames []string, client *piperhttp.Client, systemTrustConfiguration Configuration) ([]Secret, error) { var secrets []Secret query := url.Values{ - trustEngineConfiguration.TokenQueryParamName: { + systemTrustConfiguration.TokenQueryParamName: { strings.Join(refNames, ","), }, } - response, err := getResponse(trustEngineConfiguration.ServerURL, trustEngineConfiguration.TokenEndPoint, query, client) + response, err := getResponse(systemTrustConfiguration.ServerURL, systemTrustConfiguration.TokenEndPoint, query, client) if err != nil { - return secrets, errors.Wrap(err, "getting secrets from trust engine failed") + return secrets, errors.Wrap(err, "getting secrets from System Trust failed") } for k, v := range response { secrets = append(secrets, Secret{ @@ -66,13 +66,13 @@ func GetSecrets(refNames []string, client *piperhttp.Client, trustEngineConfigur return secrets, nil } -// getResponse returns a map of the JSON response that the trust engine puts out +// getResponse returns a map of the JSON response that the System Trust puts out func getResponse(serverURL, endpoint string, query url.Values, client *piperhttp.Client) (map[string]string, error) { var secrets map[string]string rawURL, err := parseURL(serverURL, endpoint, query) if err != nil { - return secrets, errors.Wrap(err, "parsing trust engine url failed") + return secrets, errors.Wrap(err, "parsing System Trust url failed") } header := make(http.Header) header.Add("Accept", "application/json") @@ -88,39 +88,39 @@ func getResponse(serverURL, endpoint string, query url.Values, client *piperhttp err = errors.Wrap(err, string(bodyBytes)) } } - return secrets, errors.Wrap(err, "getting response from trust engine failed") + return secrets, errors.Wrap(err, "getting response from System Trust failed") } defer response.Body.Close() err = json.NewDecoder(response.Body).Decode(&secrets) if err != nil { - return secrets, errors.Wrap(err, "getting response from trust engine failed") + return secrets, errors.Wrap(err, "getting response from System Trust failed") } return secrets, nil } -// parseURL creates the full URL for a Trust Engine GET request +// parseURL creates the full URL for a System Trust GET request func parseURL(serverURL, endpoint string, query url.Values) (string, error) { rawFullEndpoint, err := url.JoinPath(serverURL, endpoint) if err != nil { - return "", errors.New("error parsing trust engine URL") + return "", errors.New("error parsing System Trust URL") } fullURL, err := url.Parse(rawFullEndpoint) if err != nil { - return "", errors.New("error parsing trust engine URL") + return "", errors.New("error parsing System Trust URL") } - // commas and spaces shouldn't be escaped since the Trust Engine won't accept it + // commas and spaces shouldn't be escaped since the System Trust won't accept it unescapedRawQuery, err := url.QueryUnescape(query.Encode()) if err != nil { - return "", errors.New("error parsing trust engine URL") + return "", errors.New("error parsing System Trust URL") } fullURL.RawQuery = unescapedRawQuery return fullURL.String(), nil } -// PrepareClient adds the Trust Engine authentication token to the client -func PrepareClient(client *piperhttp.Client, trustEngineConfiguration Configuration) *piperhttp.Client { +// PrepareClient adds the System Trust authentication token to the client +func PrepareClient(client *piperhttp.Client, systemTrustConfiguration Configuration) *piperhttp.Client { var logEntry *logrus.Entry if logrus.GetLevel() < logrus.DebugLevel { logger := logrus.New() @@ -128,7 +128,7 @@ func PrepareClient(client *piperhttp.Client, trustEngineConfiguration Configurat logEntry = logrus.NewEntry(logger) } client.SetOptions(piperhttp.ClientOptions{ - Token: fmt.Sprintf("Bearer %s", trustEngineConfiguration.Token), + Token: fmt.Sprintf("Bearer %s", systemTrustConfiguration.Token), Logger: logEntry, }) return client diff --git a/pkg/trustengine/trustengine_test.go b/pkg/systemtrust/systemtrust_test.go similarity index 87% rename from pkg/trustengine/trustengine_test.go rename to pkg/systemtrust/systemtrust_test.go index d1ca1b1793..e01534b8d8 100644 --- a/pkg/trustengine/trustengine_test.go +++ b/pkg/systemtrust/systemtrust_test.go @@ -1,7 +1,7 @@ //go:build unit // +build unit -package trustengine +package systemtrust import ( "fmt" @@ -23,14 +23,14 @@ const errorMsg403 = "unauthorized to request token" var testFullURL = fmt.Sprintf("%s/%s?%s=", testServerURL, testTokenEndPoint, testTokenQueryParamName) var mockSingleTokenResponse = fmt.Sprintf("{\"sonar\": \"%s\"}", mockSonarToken) var mockTwoTokensResponse = fmt.Sprintf("{\"sonar\": \"%s\", \"blackduck\": \"%s\"}", mockSonarToken, mockblackduckToken) -var trustEngineConfiguration = Configuration{ +var systemTrustConfiguration = Configuration{ Token: "testToken", ServerURL: testServerURL, TokenEndPoint: testTokenEndPoint, TokenQueryParamName: testTokenQueryParamName, } -func TestTrustEngine(t *testing.T) { +func TestSystemTrust(t *testing.T) { httpmock.Activate() defer httpmock.DeactivateAndReset() @@ -40,7 +40,7 @@ func TestTrustEngine(t *testing.T) { client := &piperhttp.Client{} client.SetOptions(piperhttp.ClientOptions{MaxRetries: -1, UseDefaultTransport: true}) - token, err := GetToken("sonar", client, trustEngineConfiguration) + token, err := GetToken("sonar", client, systemTrustConfiguration) assert.NoError(t, err) assert.Equal(t, mockSonarToken, token) }) @@ -51,7 +51,7 @@ func TestTrustEngine(t *testing.T) { client := &piperhttp.Client{} client.SetOptions(piperhttp.ClientOptions{MaxRetries: -1, UseDefaultTransport: true}) - secrets, err := GetSecrets([]string{"sonar", "blackduck"}, client, trustEngineConfiguration) + secrets, err := getSecrets([]string{"sonar", "blackduck"}, client, systemTrustConfiguration) assert.NoError(t, err) assert.Len(t, secrets, 2) @@ -73,7 +73,7 @@ func TestTrustEngine(t *testing.T) { client := &piperhttp.Client{} client.SetOptions(piperhttp.ClientOptions{MaxRetries: -1, UseDefaultTransport: true}) - _, err := GetToken("sonar", client, trustEngineConfiguration) + _, err := GetToken("sonar", client, systemTrustConfiguration) assert.Error(t, err) }) diff --git a/pkg/whitesource/reporting.go b/pkg/whitesource/reporting.go index 56e5cefa0d..03c956f32f 100644 --- a/pkg/whitesource/reporting.go +++ b/pkg/whitesource/reporting.go @@ -8,6 +8,7 @@ import ( "fmt" "path/filepath" "runtime" + "slices" "sort" "strings" "time" @@ -217,7 +218,7 @@ func CreateSarifResultFile(scan *Scan, alerts *[]Alert) *format.SARIF { sarif.Runs[0].Results = append(sarif.Runs[0].Results, result) // only create rule on new CVE - if !piperutils.ContainsString(collectedRules, ruleId) { + if !slices.Contains(collectedRules, ruleId) { collectedRules = append(collectedRules, ruleId) sarifRule := *new(format.SarifRule) diff --git a/resources/com.sap.piper/pipeline/stashSettings.yml b/resources/com.sap.piper/pipeline/stashSettings.yml index e41cad8eca..8460d5b2b3 100644 --- a/resources/com.sap.piper/pipeline/stashSettings.yml +++ b/resources/com.sap.piper/pipeline/stashSettings.yml @@ -31,6 +31,7 @@ Acceptance: Compliance: unstash: - source + - classFiles stashes: [] Performance: diff --git a/resources/metadata/abapEnvironmentCheckoutBranch.yaml b/resources/metadata/abapEnvironmentCheckoutBranch.yaml index 663cc6b4fe..b282e10e92 100644 --- a/resources/metadata/abapEnvironmentCheckoutBranch.yaml +++ b/resources/metadata/abapEnvironmentCheckoutBranch.yaml @@ -82,6 +82,7 @@ spec: - PARAMETERS - STAGES - STEPS + - GENERAL possibleValues: - ZIP - STANDARD diff --git a/resources/metadata/abapEnvironmentCloneGitRepo.yaml b/resources/metadata/abapEnvironmentCloneGitRepo.yaml index c4c5829087..07e0057467 100644 --- a/resources/metadata/abapEnvironmentCloneGitRepo.yaml +++ b/resources/metadata/abapEnvironmentCloneGitRepo.yaml @@ -125,6 +125,7 @@ spec: - PARAMETERS - STAGES - STEPS + - GENERAL possibleValues: - ZIP - STANDARD diff --git a/resources/metadata/abapEnvironmentPullGitRepo.yaml b/resources/metadata/abapEnvironmentPullGitRepo.yaml index 7bf272a82e..de2f70ced9 100644 --- a/resources/metadata/abapEnvironmentPullGitRepo.yaml +++ b/resources/metadata/abapEnvironmentPullGitRepo.yaml @@ -89,6 +89,7 @@ spec: - PARAMETERS - STAGES - STEPS + - GENERAL possibleValues: - ZIP - STANDARD diff --git a/resources/metadata/cloudFoundryDeploy.yaml b/resources/metadata/cloudFoundryDeploy.yaml index c49a5c5a30..921000fdd5 100644 --- a/resources/metadata/cloudFoundryDeploy.yaml +++ b/resources/metadata/cloudFoundryDeploy.yaml @@ -370,6 +370,11 @@ spec: containers: - name: cfDeploy image: ppiper/cf-cli:latest + options: + - name: --ulimit + value: "stack=67108864:67108864" # Stack Size (in bytes). 64mb + - name: --ulimit + value: "nofile=65536:65536" # Number of Open Files outputs: resources: - name: influx diff --git a/resources/metadata/cnbBuild.yaml b/resources/metadata/cnbBuild.yaml index 744035e14d..679ac58569 100644 --- a/resources/metadata/cnbBuild.yaml +++ b/resources/metadata/cnbBuild.yaml @@ -192,7 +192,7 @@ spec: default: docker-config - name: dockerConfigJSONCPE type: string - description: This property is intended only for reading the `dockerConfigJSON` from the Common Pipeline Environment. If you want to provide your own credentials, please refer to the [dockerConfigJSON](#dockerConfigJSON) property. If both properties are set, the config files will be merged, with the [dockerConfigJSON](#dockerConfigJSON) having higher priority. + description: This property is intended only for reading the `dockerConfigJSON` from the Common Pipeline Environment. If you want to provide your own credentials, please refer to the [dockerConfigJSON](#dockerconfigjson) property. If both properties are set, the config files will be merged, with the [dockerConfigJSON](#dockerconfigjson) having higher priority. secret: true resourceRef: - name: commonPipelineEnvironment diff --git a/resources/metadata/detectExecuteScan.yaml b/resources/metadata/detectExecuteScan.yaml index 138a1e5e19..8f77741ad5 100644 --- a/resources/metadata/detectExecuteScan.yaml +++ b/resources/metadata/detectExecuteScan.yaml @@ -204,7 +204,7 @@ spec: type: string description: "A custom version used along with the uploaded scan results." longDescription: |- - Defines a custom version for the Detect scan which deviates from the typical versioning pattern using [`version`](#version) and [`versioningModel`](#versioningModel). + Defines a custom version for the Detect scan which deviates from the typical versioning pattern using [`version`](#version) and [`versioningModel`](#versioningmodel). It allows to set non-numeric versions as well and supersedes the value of [`version`](#version) which is calculated automatically. The parameter is also used by other scan steps (e.g. Fortify, Sonar, WhiteSource) and thus allows a common custom version across scan tools. scope: [GENERAL, STAGES, STEPS, PARAMETERS] diff --git a/resources/metadata/fortifyExecuteScan.yaml b/resources/metadata/fortifyExecuteScan.yaml index eea893381c..8386225d61 100644 --- a/resources/metadata/fortifyExecuteScan.yaml +++ b/resources/metadata/fortifyExecuteScan.yaml @@ -86,7 +86,7 @@ spec: type: string description: Custom version of the Fortify project used as source. longDescription: |- - Defines a custom version for the Fortify scan which deviates from the typical versioning pattern using [`version`](#version) and [`versioningModel`](#versioningModel). + Defines a custom version for the Fortify scan which deviates from the typical versioning pattern using [`version`](#version) and [`versioningModel`](#versioningmodel). It allows to set non-numeric versions as well and supersedes the value of [`version`](#version) which is calculated automatically. The parameter is also used by other scan steps (e.g. Detect, Sonar, WhiteSource) and thus allows a common custom version across scan tools. scope: @@ -198,9 +198,9 @@ spec: - name: fortifyProjectVersion deprecated: true type: string - description: Version used in conjunction with [`versioningModel`](#versioningModel) to identify the Fortify project to be created and used for results aggregation. + description: Version used in conjunction with [`versioningModel`](#versioningmodel) to identify the Fortify project to be created and used for results aggregation. longDescription: |- - Version used in conjunction with [`versioningModel`](#versioningModel) to identify the Fortify project to be created and used for results aggregation. + Version used in conjunction with [`versioningModel`](#versioningmodel) to identify the Fortify project to be created and used for results aggregation. This is usually determined automatically based on the information in the buildTool specific build descriptor file. scope: - GENERAL diff --git a/resources/metadata/npmExecuteTests.yaml b/resources/metadata/npmExecuteTests.yaml new file mode 100644 index 0000000000..84a633123d --- /dev/null +++ b/resources/metadata/npmExecuteTests.yaml @@ -0,0 +1,159 @@ +metadata: + name: npmExecuteTests + description: Executes end-to-end tests using npm + longDescription: | + This step executes end-to-end tests in a Docker environment using npm. + + The step spins up a Docker container based on the specified `dockerImage` and executes the `installScript` and `runScript` from `package.json`. + + The application URLs and credentials can be specified in `appUrls` and `credentialsId` respectively. If `wdi5` is set to `true`, the step uses `wdi5_username` and `wdi5_password` for authentication. + + The tests can be restricted to run only on the productive branch by setting `onlyRunInProductiveBranch` to `true`. + +spec: + inputs: + params: + - name: installCommand + type: string + description: Command to be executed for installation`. + scope: + - PARAMETERS + - STAGES + - STEPS + default: "npm ci" + - name: runCommand + type: string + description: Command to be executed for running tests`. + scope: + - PARAMETERS + - STAGES + - STEPS + mandatory: true + default: "npm run wdi5" + - name: vaultURLs + type: "[]map[string]interface{}" + description: | + An array of objects, each representing an application URL with associated credentials. + Each object must have the following properties: + - `url`: The URL of the application. + - `username`: The username for accessing the application. + - `password`: The password for accessing the application. + scope: + - PARAMETERS + - STAGES + - STEPS + resourceRef: + - type: vaultSecret + default: appMetadata + name: appMetadataVaultSecretName + - name: vaultUsername + type: "string" + description: The base URL username. + scope: + - PARAMETERS + - STAGES + - STEPS + resourceRef: + - type: vaultSecret + default: appMetadata + name: appMetadataVaultSecretName + - name: vaultPassword + type: "string" + description: The base URL password. + scope: + - PARAMETERS + - STAGES + - STEPS + resourceRef: + - type: vaultSecret + default: appMetadata + name: appMetadataVaultSecretName + - name: baseUrl + type: string + default: "http://localhost:8080/index.html" + description: Base URL of the application to be tested. + scope: + - PARAMETERS + - STAGES + - STEPS + - name: usernameEnvVar + type: string + default: "wdi5_username" + description: Env var for username. + scope: + - PARAMETERS + - STAGES + - STEPS + - name: passwordEnvVar + type: string + default: "wdi5_password" + description: Env var for password. + scope: + - PARAMETERS + - STAGES + - STEPS + - name: urlOptionPrefix + type: string + description: | + If you want to specify an extra option that the tested url it appended to. + For example if the test URL is `http://localhost` and urlOptionPrefix is `--base-url=`, + we'll add `--base-url=http://localhost` to your runScript. + scope: + - PARAMETERS + - STAGES + - STEPS + - name: envs + type: "[]string" + description: List of environment variables to be set + scope: + - PARAMETERS + - STAGES + - STEPS + - name: paths + type: "[]string" + description: List of paths to be added to $PATH + scope: + - PARAMETERS + - STAGES + - STEPS + - name: workingDirectory + type: string + default: "." + description: Directory where your tests are located relative to the root of your project + scope: + - PARAMETERS + - STAGES + - STEPS + outputs: + resources: + - name: reports + type: reports + params: + - filePattern: "**/e2e-results.xml" + type: end-to-end-test + containers: + - name: node + image: node:lts-bookworm + env: + - name: BASE_URL + value: ${{params.baseUrl}} + - name: CREDENTIALS_ID + value: ${{params.credentialsId}} + - name: no_proxy + value: localhost,selenium,$no_proxy + - name: NO_PROXY + value: localhost,selenium,$NO_PROXY + workingDir: /home/node + sidecars: + - image: selenium/standalone-chrome + name: selenium + securityContext: + privileged: true + volumeMounts: + - mountPath: /dev/shm + name: dev-shm + env: + - name: "NO_PROXY" + value: "localhost,selenium,$NO_PROXY" + - name: "no_proxy" + value: "localhost,selenium,$no_proxy" diff --git a/resources/metadata/protecodeExecuteScan.yaml b/resources/metadata/protecodeExecuteScan.yaml index 3c13c97ed0..653b271209 100644 --- a/resources/metadata/protecodeExecuteScan.yaml +++ b/resources/metadata/protecodeExecuteScan.yaml @@ -260,7 +260,7 @@ spec: type: string description: "A custom version used along with the uploaded scan results." longDescription: |- - Defines a custom version for the BDBA scan which deviates from the typical versioning pattern using [`version`](#version) and [`versioningModel`](#versioningModel). + Defines a custom version for the BDBA scan which deviates from the typical versioning pattern using [`version`](#version) and [`versioningModel`](#versioningmodel). It allows to set non-numeric versions as well and supersedes the value of [`version`](#version) which is calculated automatically. The parameter is also used by other scan steps (e.g. Fortify, Sonar, WhiteSource) and thus allows a common custom version across scan tools. scope: [GENERAL, STAGES, STEPS, PARAMETERS] diff --git a/resources/metadata/sonarExecuteScan.yaml b/resources/metadata/sonarExecuteScan.yaml index db0e37e33c..b542da8a08 100644 --- a/resources/metadata/sonarExecuteScan.yaml +++ b/resources/metadata/sonarExecuteScan.yaml @@ -53,8 +53,8 @@ spec: default: sonar - name: sonarTokenCredentialsId type: secret - - type: trustengineSecret - name: sonarTrustengineSecretName + - type: systemTrustSecret + name: sonarSystemtrustSecretName default: sonar aliases: - name: sonarToken @@ -108,7 +108,7 @@ spec: type: string description: "A custom version used along with the uploaded scan results." longDescription: |- - Defines a custom version for the Sonar scan which deviates from the typical versioning pattern using [`version`](#version) and [`versioningModel`](#versioningModel). + Defines a custom version for the Sonar scan which deviates from the typical versioning pattern using [`version`](#version) and [`versioningModel`](#versioningmodel). It allows to set non-numeric versions as well and supersedes the value of [`version`](#version) which is calculated automatically. The parameter is also used by other scan steps (e.g. Detect, Fortify, WhiteSource) and thus allows a common custom version across scan tools. scope: [GENERAL, STAGES, STEPS, PARAMETERS] diff --git a/resources/metadata/whitesourceExecuteScan.yaml b/resources/metadata/whitesourceExecuteScan.yaml index 85298d9c76..4b52fed5e1 100644 --- a/resources/metadata/whitesourceExecuteScan.yaml +++ b/resources/metadata/whitesourceExecuteScan.yaml @@ -177,7 +177,7 @@ spec: type: string description: Custom version of the WhiteSource project used as source. longDescription: |- - Defines a custom version for the WhiteSource scan which deviates from the typical versioning pattern using [`version`](#version) and [`versioningModel`](#versioningModel). + Defines a custom version for the WhiteSource scan which deviates from the typical versioning pattern using [`version`](#version) and [`versioningModel`](#versioningmodel). It allows to set non-numeric versions as well and supersedes the value of [`version`](#version) which is calculated automatically. The parameter is also used by other scan steps (e.g. Detect, Fortify, Sonar) and thus allows a common custom version across scan tools. scope: diff --git a/src/com/sap/piper/ConfigurationHelper.groovy b/src/com/sap/piper/ConfigurationHelper.groovy index b6b1558ddf..2eeaaf0e6f 100644 --- a/src/com/sap/piper/ConfigurationHelper.groovy +++ b/src/com/sap/piper/ConfigurationHelper.groovy @@ -10,9 +10,6 @@ class ConfigurationHelper implements Serializable { } ConfigurationHelper loadStepDefaults(Map compatibleParameters = [:], String stageName = step.env.STAGE_NAME) { - if (stageName == 'Central Build'){ - stageName = 'Build' - } DefaultValueCache.prepare(step) this.config = ConfigurationLoader.defaultGeneralConfiguration() mixin(ConfigurationLoader.defaultGeneralConfiguration(), null, compatibleParameters) diff --git a/src/com/sap/piper/PiperGoUtils.groovy b/src/com/sap/piper/PiperGoUtils.groovy index 1206647d0d..f4765de7da 100644 --- a/src/com/sap/piper/PiperGoUtils.groovy +++ b/src/com/sap/piper/PiperGoUtils.groovy @@ -30,7 +30,7 @@ class PiperGoUtils implements Serializable { if (steps.env.REPOSITORY_UNDER_TEST && steps.env.LIBRARY_VERSION_UNDER_TEST) { steps.echo("Running in a consumer test, building unit-under-test binary for verification.") - steps.dockerExecute(script: steps, dockerImage: 'golang:1.22.4', dockerOptions: '-u 0', dockerEnvVars: [ + steps.dockerExecute(script: steps, dockerImage: 'golang:1.23.4', dockerOptions: '-u 0', dockerEnvVars: [ REPOSITORY_UNDER_TEST: steps.env.REPOSITORY_UNDER_TEST, LIBRARY_VERSION_UNDER_TEST: steps.env.LIBRARY_VERSION_UNDER_TEST ]) { @@ -83,7 +83,7 @@ class PiperGoUtils implements Serializable { private boolean downloadGoBinary(url) { try { - def httpStatus = steps.sh(returnStdout: true, script: "curl --insecure --silent --retry 5 --retry-max-time 240 --location --write-out '%{http_code}' --output ${piperExecutable} '${url}'") + def httpStatus = steps.sh(returnStdout: true, script: "curl --silent --retry 5 --retry-max-time 240 --location --write-out '%{http_code}' --output ${piperExecutable} '${url}'") if (httpStatus == '200') { steps.sh(script: "chmod +x ${piperExecutable}") diff --git a/src/com/sap/piper/StageNameProvider.groovy b/src/com/sap/piper/StageNameProvider.groovy index cd2fa71f06..ceb7967629 100644 --- a/src/com/sap/piper/StageNameProvider.groovy +++ b/src/com/sap/piper/StageNameProvider.groovy @@ -3,8 +3,6 @@ package com.sap.piper @Singleton class StageNameProvider implements Serializable { static final long serialVersionUID = 1L - static final String CENTRAL_BUILD = "Central Build"; - static final String BUILD = "Build"; /** Stores a feature toggle for defaulting to technical names in stages */ boolean useTechnicalStageNames = false @@ -12,9 +10,7 @@ class StageNameProvider implements Serializable { String getStageName(Script script, Map parameters, Script step) { String stageName = null if (parameters.stageName in CharSequence) { - stageName = parameters.stageName - stageName = replaceCentralBuild(stageName); - return stageName + return parameters.stageName } if (this.useTechnicalStageNames) { String technicalStageName = getTechnicalStageName(step) @@ -22,15 +18,7 @@ class StageNameProvider implements Serializable { return technicalStageName } } - if (stageName == null) { - stageName = script.env.STAGE_NAME - stageName = replaceCentralBuild(stageName); - } - return stageName - } - - private String replaceCentralBuild(String stageName) { - return CENTRAL_BUILD.equals(stageName) ? BUILD : stageName; + return script.env.STAGE_NAME } static String getTechnicalStageName(Script step) { diff --git a/test/groovy/SetupCommonPipelineEnvironmentTest.groovy b/test/groovy/SetupCommonPipelineEnvironmentTest.groovy index ecb15c3c31..06fbacd276 100644 --- a/test/groovy/SetupCommonPipelineEnvironmentTest.groovy +++ b/test/groovy/SetupCommonPipelineEnvironmentTest.groovy @@ -374,6 +374,25 @@ class SetupCommonPipelineEnvironmentTest extends BasePiperTest { assertThat(nullScript.commonPipelineEnvironment.gitRef, is('refs/heads/testbranch/001')) } + @Test + void "Set scmInfo parameter sets git reference for tag"() { + + def GitUtils gitUtils = new GitUtils() { + boolean isMergeCommit(){ + return false + } + } + + helper.registerAllowedMethod("fileExists", [String], { String path -> + return path.endsWith('.pipeline/config.yml') + }) + + def dummyScmInfo = [GIT_COMMIT: 'dummy_git_commit_id', GIT_BRANCH: 'refs/tags/tag-1.0.0'] + + stepRule.step.setupCommonPipelineEnvironment(script: nullScript, utils: utilsMock, scmInfo: dummyScmInfo, gitUtils: gitUtils) + assertThat(nullScript.commonPipelineEnvironment.gitRef, is('refs/tags/tag-1.0.0')) + } + @Test void "sets gitReference and gitRemoteCommit for pull request, head strategy"() { diff --git a/test/groovy/com/sap/piper/PiperGoUtilsTest.groovy b/test/groovy/com/sap/piper/PiperGoUtilsTest.groovy index 94d49b55ed..42e63a74a3 100644 --- a/test/groovy/com/sap/piper/PiperGoUtilsTest.groovy +++ b/test/groovy/com/sap/piper/PiperGoUtilsTest.groovy @@ -63,11 +63,11 @@ class PiperGoUtilsTest extends BasePiperTest { }) shellCallRule.setReturnValue('[ -x ./piper ]', 1) - shellCallRule.setReturnValue('curl --insecure --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/latest/download/piper\'', '200') + shellCallRule.setReturnValue('curl --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/latest/download/piper\'', '200') piperGoUtils.unstashPiperBin() assertThat(shellCallRule.shell.size(), is(4)) - assertThat(shellCallRule.shell[1].toString(), is('curl --insecure --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/latest/download/piper\'')) + assertThat(shellCallRule.shell[1].toString(), is('curl --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/latest/download/piper\'')) assertThat(shellCallRule.shell[2].toString(), is('chmod +x piper')) assertThat(shellCallRule.shell[3].toString(), is('./piper version')) } @@ -84,11 +84,11 @@ class PiperGoUtilsTest extends BasePiperTest { }) shellCallRule.setReturnValue('[ -x ./piper ]', 1) - shellCallRule.setReturnValue('curl --insecure --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/download/testTag/piper\'', '200') + shellCallRule.setReturnValue('curl --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/download/testTag/piper\'', '200') piperGoUtils.unstashPiperBin() assertThat(shellCallRule.shell.size(), is(4)) - assertThat(shellCallRule.shell[1].toString(), is('curl --insecure --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/download/testTag/piper\'')) + assertThat(shellCallRule.shell[1].toString(), is('curl --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/download/testTag/piper\'')) assertThat(shellCallRule.shell[2].toString(), is('chmod +x piper')) assertThat(shellCallRule.shell[3].toString(), is('./piper version')) } @@ -101,8 +101,8 @@ class PiperGoUtilsTest extends BasePiperTest { shellCallRule.setReturnValue('[ -x ./piper ]', 1) shellCallRule.setReturnValue('./piper version', "1.2.3") - shellCallRule.setReturnValue('curl --insecure --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/download/notAvailable/piper\'', '404') - shellCallRule.setReturnValue('curl --insecure --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/latest/download/piper\'', '200') + shellCallRule.setReturnValue('curl --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/download/notAvailable/piper\'', '404') + shellCallRule.setReturnValue('curl --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/latest/download/piper\'', '200') // this mocks utils.unstash - mimic stash not existing helper.registerAllowedMethod("unstash", [String.class], { stashFileName -> @@ -112,8 +112,8 @@ class PiperGoUtilsTest extends BasePiperTest { piperGoUtils.unstashPiperBin() assertThat(shellCallRule.shell.size(), is(5)) assertThat(shellCallRule.shell[0].toString(), is('[ -x ./piper ]')) - assertThat(shellCallRule.shell[1].toString(), is('curl --insecure --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/download/notAvailable/piper\'')) - assertThat(shellCallRule.shell[2].toString(), is('curl --insecure --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/latest/download/piper\'')) + assertThat(shellCallRule.shell[1].toString(), is('curl --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/download/notAvailable/piper\'')) + assertThat(shellCallRule.shell[2].toString(), is('curl --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/latest/download/piper\'')) assertThat(shellCallRule.shell[3].toString(), is('chmod +x piper')) assertThat(shellCallRule.shell[4].toString(), is ('./piper version')) } @@ -124,8 +124,8 @@ class PiperGoUtilsTest extends BasePiperTest { piperGoUtils.metaClass.getLibrariesInfo = {-> return [[name: 'piper-lib-os', version: 'notAvailable']]} shellCallRule.setReturnValue('[ -x ./piper ]', 1) - shellCallRule.setReturnValue('curl --insecure --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/download/notAvailable/piper\'', '404') - shellCallRule.setReturnValue('curl --insecure --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/latest/download/piper\'', '500') + shellCallRule.setReturnValue('curl --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/download/notAvailable/piper\'', '404') + shellCallRule.setReturnValue('curl --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/latest/download/piper\'', '500') helper.registerAllowedMethod("unstash", [String.class], { stashFileName -> return [] @@ -141,8 +141,8 @@ class PiperGoUtilsTest extends BasePiperTest { piperGoUtils.metaClass.getLibrariesInfo = {-> return [[name: 'piper-lib-os', version: 'notAvailable']]} shellCallRule.setReturnValue('[ -x ./piper ]', 1) - shellCallRule.setReturnValue('curl --insecure --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/download/notAvailable/piper\'', '404') - shellCallRule.setReturnValue('curl --insecure --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/latest/download/piper\'', '500') + shellCallRule.setReturnValue('curl --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/download/notAvailable/piper\'', '404') + shellCallRule.setReturnValue('curl --silent --retry 5 --retry-max-time 240 --location --write-out \'%{http_code}\' --output piper \'https://github.com/SAP/jenkins-library/releases/latest/download/piper\'', '500') helper.registerAllowedMethod("unstash", [String.class], { stashFileName -> return [] diff --git a/vars/npmExecuteTests.groovy b/vars/npmExecuteTests.groovy new file mode 100644 index 0000000000..bb34499c22 --- /dev/null +++ b/vars/npmExecuteTests.groovy @@ -0,0 +1,15 @@ +import groovy.transform.Field + +@Field String STEP_NAME = getClass().getName() +@Field String METADATA_FILE = 'metadata/npmExecuteTests.yaml' + +@Field Set GENERAL_CONFIG_KEYS = [] + +@Field Set STEP_CONFIG_KEYS = [] + +@Field Set PARAMETER_KEYS = [] + +void call(Map parameters = [:]) { + List credentials = [] + piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials) +} diff --git a/vars/piperExecuteBin.groovy b/vars/piperExecuteBin.groovy index 311242c81a..08dec74004 100644 --- a/vars/piperExecuteBin.groovy +++ b/vars/piperExecuteBin.groovy @@ -78,6 +78,11 @@ void call(Map parameters = [:], String stepName, String metadataFile, List crede try { try { credentialWrapper(config, credentialInfo) { + if (config.verbose) { // need to be set on step config + echo "[DEBUG] Current environment limits:" + sh "ulimit -a" + } + sh "${piperGoPath} ${stepName}${defaultConfigArgs}${customConfigArg}" } } finally { diff --git a/vars/setupCommonPipelineEnvironment.groovy b/vars/setupCommonPipelineEnvironment.groovy index d7a3676d3f..43a61ed80a 100644 --- a/vars/setupCommonPipelineEnvironment.groovy +++ b/vars/setupCommonPipelineEnvironment.groovy @@ -272,7 +272,11 @@ private void setGitRefOnCommonPipelineEnvironment(script, String gitCommit, Stri } if (!gitBranch.contains("PR")) { - script.commonPipelineEnvironment.setGitRef("refs/heads/" + gitBranch) + if (gitBranch.startsWith("refs/") ){ + script.commonPipelineEnvironment.setGitRef(gitBranch) + } else { + script.commonPipelineEnvironment.setGitRef("refs/heads/" + gitBranch) + } script.commonPipelineEnvironment.setGitRemoteCommitId(gitCommit) return }