github.com/jaylevin/jenkins-library@v1.230.4/cmd/mavenBuild.go (about) 1 package cmd 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path" 7 "path/filepath" 8 "strings" 9 10 "github.com/SAP/jenkins-library/pkg/buildsettings" 11 "github.com/SAP/jenkins-library/pkg/command" 12 "github.com/SAP/jenkins-library/pkg/log" 13 "github.com/SAP/jenkins-library/pkg/maven" 14 "github.com/SAP/jenkins-library/pkg/piperutils" 15 "github.com/SAP/jenkins-library/pkg/telemetry" 16 "github.com/pkg/errors" 17 18 piperhttp "github.com/SAP/jenkins-library/pkg/http" 19 ) 20 21 func mavenBuild(config mavenBuildOptions, telemetryData *telemetry.CustomData, commonPipelineEnvironment *mavenBuildCommonPipelineEnvironment) { 22 utils := maven.NewUtilsBundle() 23 24 err := runMavenBuild(&config, telemetryData, utils, commonPipelineEnvironment) 25 if err != nil { 26 log.Entry().WithError(err).Fatal("step execution failed") 27 } 28 } 29 30 func runMavenBuild(config *mavenBuildOptions, telemetryData *telemetry.CustomData, utils maven.Utils, commonPipelineEnvironment *mavenBuildCommonPipelineEnvironment) error { 31 32 var flags = []string{"-update-snapshots", "--batch-mode"} 33 34 if len(config.Profiles) > 0 { 35 flags = append(flags, "--activate-profiles", strings.Join(config.Profiles, ",")) 36 } 37 38 exists, _ := utils.FileExists("integration-tests/pom.xml") 39 if exists { 40 flags = append(flags, "-pl", "!integration-tests") 41 } 42 43 var defines []string 44 var goals []string 45 46 if config.Flatten { 47 goals = append(goals, "flatten:flatten") 48 defines = append(defines, "-Dflatten.mode=resolveCiFriendliesOnly", "-DupdatePomFile=true") 49 } 50 51 if config.CreateBOM { 52 goals = append(goals, "org.cyclonedx:cyclonedx-maven-plugin:makeAggregateBom") 53 createBOMConfig := []string{ 54 "-DschemaVersion=1.2", 55 "-DincludeBomSerialNumber=true", 56 "-DincludeCompileScope=true", 57 "-DincludeProvidedScope=true", 58 "-DincludeRuntimeScope=true", 59 "-DincludeSystemScope=true", 60 "-DincludeTestScope=false", 61 "-DincludeLicenseText=false", 62 "-DoutputFormat=xml", 63 } 64 defines = append(defines, createBOMConfig...) 65 } 66 67 goals = append(goals, "org.jacoco:jacoco-maven-plugin:prepare-agent") 68 69 if config.Verify { 70 goals = append(goals, "verify") 71 } else { 72 goals = append(goals, "install") 73 } 74 75 mavenOptions := maven.ExecuteOptions{ 76 Flags: flags, 77 Goals: goals, 78 Defines: defines, 79 PomPath: config.PomPath, 80 ProjectSettingsFile: config.ProjectSettingsFile, 81 GlobalSettingsFile: config.GlobalSettingsFile, 82 M2Path: config.M2Path, 83 LogSuccessfulMavenTransfers: config.LogSuccessfulMavenTransfers, 84 } 85 86 _, err := maven.Execute(&mavenOptions, utils) 87 88 if err != nil { 89 return errors.Wrapf(err, "failed to execute maven build for goal(s) '%v'", goals) 90 } 91 92 log.Entry().Debugf("creating build settings information...") 93 stepName := "mavenBuild" 94 dockerImage, err := GetDockerImageValue(stepName) 95 if err != nil { 96 return err 97 } 98 99 mavenConfig := buildsettings.BuildOptions{ 100 Profiles: config.Profiles, 101 GlobalSettingsFile: config.GlobalSettingsFile, 102 LogSuccessfulMavenTransfers: config.LogSuccessfulMavenTransfers, 103 CreateBOM: config.CreateBOM, 104 Publish: config.Publish, 105 BuildSettingsInfo: config.BuildSettingsInfo, 106 DockerImage: dockerImage, 107 } 108 buildSettingsInfo, err := buildsettings.CreateBuildSettingsInfo(&mavenConfig, stepName) 109 if err != nil { 110 log.Entry().Warnf("failed to create build settings info: %v", err) 111 } 112 commonPipelineEnvironment.custom.buildSettingsInfo = buildSettingsInfo 113 114 if err == nil { 115 if config.Publish && !config.Verify { 116 log.Entry().Infof("publish detected, running mvn deploy") 117 118 if (len(config.AltDeploymentRepositoryID) > 0) && (len(config.AltDeploymentRepositoryPassword) > 0) && (len(config.AltDeploymentRepositoryUser) > 0) { 119 projectSettingsFilePath, err := createOrUpdateProjectSettingsXML(config.ProjectSettingsFile, config.AltDeploymentRepositoryID, config.AltDeploymentRepositoryUser, config.AltDeploymentRepositoryPassword, utils) 120 if err != nil { 121 return errors.Wrap(err, "Could not create or update project settings xml") 122 } 123 mavenOptions.ProjectSettingsFile = projectSettingsFilePath 124 } 125 126 deployFlags := []string{"-Dmaven.main.skip=true", "-Dmaven.test.skip=true", "-Dmaven.install.skip=true"} 127 if (len(config.AltDeploymentRepositoryID) > 0) && (len(config.AltDeploymentRepositoryURL) > 0) { 128 deployFlags = append(deployFlags, "-DaltDeploymentRepository="+config.AltDeploymentRepositoryID+"::default::"+config.AltDeploymentRepositoryURL) 129 } 130 131 downloadClient := &piperhttp.Client{} 132 runner := &command.Command{} 133 fileUtils := &piperutils.Files{} 134 if len(config.CustomTLSCertificateLinks) > 0 { 135 if err := loadRemoteRepoCertificates(config.CustomTLSCertificateLinks, downloadClient, &deployFlags, runner, fileUtils, config.JavaCaCertFilePath); err != nil { 136 log.SetErrorCategory(log.ErrorInfrastructure) 137 return err 138 } 139 } 140 141 mavenOptions.Flags = deployFlags 142 mavenOptions.Goals = []string{"deploy"} 143 mavenOptions.Defines = []string{} 144 _, err := maven.Execute(&mavenOptions, utils) 145 return err 146 } else { 147 log.Entry().Infof("publish not detected, ignoring maven deploy") 148 } 149 } 150 151 return err 152 } 153 154 func createOrUpdateProjectSettingsXML(projectSettingsFile string, altDeploymentRepositoryID string, altDeploymentRepositoryUser string, altDeploymentRepositoryPassword string, utils maven.Utils) (string, error) { 155 if len(projectSettingsFile) > 0 { 156 projectSettingsFilePath, err := maven.UpdateProjectSettingsXML(projectSettingsFile, altDeploymentRepositoryID, altDeploymentRepositoryUser, altDeploymentRepositoryPassword, utils) 157 if err != nil { 158 return "", errors.Wrap(err, "Could not update settings xml") 159 } 160 return projectSettingsFilePath, nil 161 } else { 162 projectSettingsFilePath, err := maven.CreateNewProjectSettingsXML(altDeploymentRepositoryID, altDeploymentRepositoryUser, altDeploymentRepositoryPassword, utils) 163 if err != nil { 164 return "", errors.Wrap(err, "Could not create settings xml") 165 } 166 return projectSettingsFilePath, nil 167 } 168 } 169 170 func loadRemoteRepoCertificates(certificateList []string, client piperhttp.Downloader, flags *[]string, runner command.ExecRunner, fileUtils piperutils.FileUtils, javaCaCertFilePath string) error { 171 //TODO: make use of java/keytool package 172 existingJavaCaCerts := filepath.Join(os.Getenv("JAVA_HOME"), "jre", "lib", "security", "cacerts") 173 174 if len(javaCaCertFilePath) > 0 { 175 existingJavaCaCerts = javaCaCertFilePath 176 } 177 178 exists, err := fileUtils.FileExists(existingJavaCaCerts) 179 180 if err != nil { 181 return errors.Wrap(err, "Could not find the existing java cacerts") 182 } 183 184 if !exists { 185 return errors.Wrap(err, "Could not find the existing java cacerts") 186 } 187 188 trustStore := filepath.Join(".pipeline", "mavenCaCerts") 189 190 log.Entry().Infof("copying java cacerts : %s to new cacerts : %s", existingJavaCaCerts, trustStore) 191 _, fileUtilserr := fileUtils.Copy(existingJavaCaCerts, trustStore) 192 193 if fileUtilserr != nil { 194 return errors.Wrap(err, "Could not copy existing cacerts into new cacerts location ") 195 } 196 197 if err := fileUtils.Chmod(trustStore, 0666); err != nil { 198 return errors.Wrap(err, "unable to provide correct permission to trust store") 199 } 200 201 log.Entry().Infof("using trust store %s", trustStore) 202 203 if exists, _ := fileUtils.FileExists(trustStore); exists { 204 maven_opts := "-Djavax.net.ssl.trustStore=.pipeline/mavenCaCerts -Djavax.net.ssl.trustStorePassword=changeit" 205 err := os.Setenv("MAVEN_OPTS", maven_opts) 206 if err != nil { 207 return errors.Wrap(err, "Could not create MAVEN_OPTS environment variable ") 208 } 209 log.Entry().WithField("trust store", trustStore).Info("Using local trust store") 210 } 211 212 if len(certificateList) > 0 { 213 keytoolOptions := []string{ 214 "-import", 215 "-noprompt", 216 "-storepass", "changeit", 217 "-keystore", trustStore, 218 } 219 tmpFolder := getTempDirForCertFile() 220 defer os.RemoveAll(tmpFolder) // clean up 221 222 for _, certificate := range certificateList { 223 filename := path.Base(certificate) // decode? 224 target := filepath.Join(tmpFolder, filename) 225 226 log.Entry().WithField("source", certificate).WithField("target", target).Info("Downloading TLS certificate") 227 // download certificate 228 if err := client.DownloadFile(certificate, target, nil, nil); err != nil { 229 return errors.Wrapf(err, "Download of TLS certificate failed") 230 } 231 options := append(keytoolOptions, "-file", target) 232 options = append(options, "-alias", filename) 233 // add certificate to keystore 234 if err := runner.RunExecutable("keytool", options...); err != nil { 235 return errors.Wrap(err, "Adding certificate to keystore failed") 236 } 237 } 238 log.Entry().Infof("custom tls certificates successfully added to the trust store %s", trustStore) 239 } else { 240 log.Entry().Debug("Download of TLS certificates skipped") 241 } 242 return nil 243 } 244 245 func getTempDirForCertFile() string { 246 tmpFolder, err := ioutil.TempDir(".", "temp-") 247 if err != nil { 248 log.Entry().WithError(err).WithField("path", tmpFolder).Debug("Creating temp directory failed") 249 } 250 return tmpFolder 251 }