2020-02-25 15:17:00 +02:00
|
|
|
package maven
|
|
|
|
|
|
|
|
import (
|
2021-06-01 09:24:36 +02:00
|
|
|
"encoding/xml"
|
2020-02-25 15:17:00 +02:00
|
|
|
"fmt"
|
2020-07-30 10:35:46 +02:00
|
|
|
"net/http"
|
2020-02-25 15:17:00 +02:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
2021-06-01 09:24:36 +02:00
|
|
|
|
|
|
|
"github.com/SAP/jenkins-library/pkg/log"
|
2020-02-25 15:17:00 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
var getenv = os.Getenv
|
|
|
|
|
2020-11-10 18:14:55 +02:00
|
|
|
// SettingsDownloadUtils defines an interface for downloading and storing maven settings files.
|
2020-07-30 10:35:46 +02:00
|
|
|
type SettingsDownloadUtils interface {
|
|
|
|
DownloadFile(url, filename string, header http.Header, cookies []*http.Cookie) error
|
2020-10-27 15:29:22 +02:00
|
|
|
FileExists(filename string) (bool, error)
|
|
|
|
Copy(src, dest string) (int64, error)
|
|
|
|
MkdirAll(path string, perm os.FileMode) error
|
2021-06-01 09:24:36 +02:00
|
|
|
FileWrite(path string, content []byte, perm os.FileMode) error
|
|
|
|
FileRead(path string) ([]byte, error)
|
2020-10-27 15:29:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// DownloadAndGetMavenParameters downloads the global or project settings file if the strings contain URLs.
|
|
|
|
// It then constructs the arguments that need to be passed to maven in order to point to use these settings files.
|
2020-11-10 18:14:55 +02:00
|
|
|
func DownloadAndGetMavenParameters(globalSettingsFile string, projectSettingsFile string, utils SettingsDownloadUtils) ([]string, error) {
|
2020-07-30 10:35:46 +02:00
|
|
|
mavenArgs := []string{}
|
|
|
|
if len(globalSettingsFile) > 0 {
|
2020-11-10 18:14:55 +02:00
|
|
|
globalSettingsFileName, err := downloadSettingsIfURL(globalSettingsFile, ".pipeline/mavenGlobalSettings.xml", utils, false)
|
2020-07-30 10:35:46 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
mavenArgs = append(mavenArgs, "--global-settings", globalSettingsFileName)
|
|
|
|
} else {
|
2020-02-25 15:17:00 +02:00
|
|
|
|
2020-07-30 10:35:46 +02:00
|
|
|
log.Entry().Debugf("Global settings file not provided via configuration.")
|
|
|
|
}
|
2020-02-25 15:17:00 +02:00
|
|
|
|
2020-07-30 10:35:46 +02:00
|
|
|
if len(projectSettingsFile) > 0 {
|
2020-11-10 18:14:55 +02:00
|
|
|
projectSettingsFileName, err := downloadSettingsIfURL(projectSettingsFile, ".pipeline/mavenProjectSettings.xml", utils, false)
|
2020-07-30 10:35:46 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
mavenArgs = append(mavenArgs, "--settings", projectSettingsFileName)
|
|
|
|
} else {
|
2020-02-25 15:17:00 +02:00
|
|
|
|
2020-07-30 10:35:46 +02:00
|
|
|
log.Entry().Debugf("Project settings file not provided via configuration.")
|
2020-02-25 15:17:00 +02:00
|
|
|
}
|
2020-07-30 10:35:46 +02:00
|
|
|
return mavenArgs, nil
|
|
|
|
}
|
2020-02-25 15:17:00 +02:00
|
|
|
|
2020-10-27 15:29:22 +02:00
|
|
|
// DownloadAndCopySettingsFiles downloads the global or project settings file if the strings contain URLs.
|
|
|
|
// It copies the given files to either the locations specified in the environment variables M2_HOME and HOME
|
|
|
|
// or the default locations where maven expects them.
|
2020-11-10 18:14:55 +02:00
|
|
|
func DownloadAndCopySettingsFiles(globalSettingsFile string, projectSettingsFile string, utils SettingsDownloadUtils) error {
|
2020-07-30 10:35:46 +02:00
|
|
|
if len(projectSettingsFile) > 0 {
|
|
|
|
destination, err := getProjectSettingsFileDest()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-11-10 18:14:55 +02:00
|
|
|
if err := downloadAndCopySettingsFile(projectSettingsFile, destination, utils); err != nil {
|
2020-07-30 10:35:46 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
|
|
|
|
log.Entry().Debugf("Project settings file not provided via configuration.")
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(globalSettingsFile) > 0 {
|
|
|
|
destination, err := getGlobalSettingsFileDest()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-11-10 18:14:55 +02:00
|
|
|
if err := downloadAndCopySettingsFile(globalSettingsFile, destination, utils); err != nil {
|
2020-07-30 10:35:46 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
|
|
|
|
log.Entry().Debugf("Global settings file not provided via configuration.")
|
2020-02-25 15:17:00 +02:00
|
|
|
}
|
|
|
|
|
2020-07-30 10:35:46 +02:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-09-23 15:33:30 +02:00
|
|
|
func UpdateActiveProfileInSettingsXML(newActiveProfiles []string, utils SettingsDownloadUtils) error {
|
|
|
|
settingsFile, err := getGlobalSettingsFileDest()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
settingsXMLContent, err := utils.FileRead(settingsFile)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("error reading global settings xml file at %v , continuing without active profile update", settingsFile)
|
|
|
|
}
|
|
|
|
|
|
|
|
var projectSettings Settings
|
|
|
|
err = xml.Unmarshal([]byte(settingsXMLContent), &projectSettings)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to unmarshal settings xml file '%v': %w", settingsFile, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(projectSettings.ActiveProfiles.ActiveProfile) == 0 {
|
|
|
|
log.Entry().Warnf("no active profile found to replace in settings xml %v , continuing without file edit", settingsFile)
|
|
|
|
} else {
|
|
|
|
projectSettings.Xsi = "http://www.w3.org/2001/XMLSchema-instance"
|
|
|
|
projectSettings.SchemaLocation = "http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd"
|
|
|
|
|
|
|
|
projectSettings.ActiveProfiles.ActiveProfile = []string{}
|
|
|
|
projectSettings.ActiveProfiles.ActiveProfile = append(projectSettings.ActiveProfiles.ActiveProfile, newActiveProfiles...)
|
|
|
|
|
|
|
|
settingsXml, err := xml.MarshalIndent(projectSettings, "", " ")
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to marshal maven project settings xml: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
settingsXmlString := string(settingsXml)
|
|
|
|
Replacer := strings.NewReplacer("
", "", "	", "")
|
|
|
|
settingsXmlString = Replacer.Replace(settingsXmlString)
|
|
|
|
xmlstring := []byte(xml.Header + settingsXmlString)
|
|
|
|
|
|
|
|
err = utils.FileWrite(settingsFile, xmlstring, 0777)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to write maven Settings during <activeProfile> update xml: %w", err)
|
|
|
|
}
|
|
|
|
log.Entry().Infof("Successfully updated <acitveProfile> details in maven settings file : '%s'", settingsFile)
|
|
|
|
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-06-01 09:24:36 +02:00
|
|
|
func CreateNewProjectSettingsXML(altDeploymentRepositoryID string, altDeploymentRepositoryUser string, altDeploymentRepositoryPassword string, utils SettingsDownloadUtils) (string, error) {
|
|
|
|
settingsXML := Settings{
|
|
|
|
XMLName: xml.Name{Local: "settings"},
|
|
|
|
Xsi: "http://www.w3.org/2001/XMLSchema-instance",
|
|
|
|
SchemaLocation: "http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd",
|
|
|
|
Servers: ServersType{
|
|
|
|
ServerType: []Server{
|
|
|
|
{
|
|
|
|
ID: altDeploymentRepositoryID,
|
|
|
|
Username: altDeploymentRepositoryUser,
|
|
|
|
Password: altDeploymentRepositoryPassword,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
xmlstring, err := xml.MarshalIndent(settingsXML, "", " ")
|
|
|
|
if err != nil {
|
|
|
|
return "", fmt.Errorf("failed to marshal Settings.xml: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
xmlstring = []byte(xml.Header + string(xmlstring))
|
|
|
|
|
|
|
|
err = utils.FileWrite(".pipeline/mavenProjectSettings.xml", xmlstring, 0777)
|
|
|
|
if err != nil {
|
|
|
|
return "", fmt.Errorf("failed to write maven Project Settings xml: %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Entry().Infof("Successfully created maven project settings with <server> details at .pipeline/mavenProjectSettings.xml")
|
|
|
|
|
|
|
|
return ".pipeline/mavenProjectSettings.xml", nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func UpdateProjectSettingsXML(projectSettingsFile string, altDeploymentRepositoryID string, altDeploymentRepositoryUser string, altDeploymentRepositoryPassword string, utils SettingsDownloadUtils) (string, error) {
|
|
|
|
projectSettingsFileDestination := ".pipeline/mavenProjectSettings"
|
|
|
|
if exists, _ := utils.FileExists(projectSettingsFile); exists {
|
|
|
|
projectSettingsFileDestination = projectSettingsFile
|
|
|
|
addServerTagtoProjectSettingsXML(projectSettingsFile, altDeploymentRepositoryID, altDeploymentRepositoryUser, altDeploymentRepositoryPassword, utils)
|
|
|
|
} else {
|
|
|
|
addServerTagtoProjectSettingsXML(".pipeline/mavenProjectSettings", altDeploymentRepositoryID, altDeploymentRepositoryUser, altDeploymentRepositoryPassword, utils)
|
|
|
|
}
|
|
|
|
return projectSettingsFileDestination, nil
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
func addServerTagtoProjectSettingsXML(projectSettingsFile string, altDeploymentRepositoryID string, altDeploymentRepositoryUser string, altDeploymentRepositoryPassword string, utils SettingsDownloadUtils) error {
|
|
|
|
var projectSettings Settings
|
|
|
|
settingsXMLContent, err := utils.FileRead(projectSettingsFile)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to read file '%v': %w", projectSettingsFile, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
err = xml.Unmarshal([]byte(settingsXMLContent), &projectSettings)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to unmarshal settings xml file '%v': %w", projectSettingsFile, err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(projectSettings.Servers.ServerType) == 0 {
|
|
|
|
projectSettings.Xsi = "http://www.w3.org/2001/XMLSchema-instance"
|
|
|
|
projectSettings.SchemaLocation = "http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd"
|
|
|
|
projectSettings.Servers.ServerType = []Server{
|
|
|
|
{
|
|
|
|
ID: altDeploymentRepositoryID,
|
|
|
|
Username: altDeploymentRepositoryUser,
|
|
|
|
Password: altDeploymentRepositoryPassword,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
} else if len(projectSettings.Servers.ServerType) > 0 { // if <server> tag is present then add the staging server tag
|
|
|
|
stagingServer := Server{
|
|
|
|
ID: altDeploymentRepositoryID,
|
|
|
|
Username: altDeploymentRepositoryUser,
|
|
|
|
Password: altDeploymentRepositoryPassword,
|
|
|
|
}
|
|
|
|
projectSettings.Servers.ServerType = append(projectSettings.Servers.ServerType, stagingServer)
|
|
|
|
}
|
|
|
|
|
|
|
|
settingsXml, err := xml.MarshalIndent(projectSettings, "", " ")
|
|
|
|
if err != nil {
|
|
|
|
fmt.Errorf("failed to marshal maven project settings xml: %w", err)
|
|
|
|
}
|
|
|
|
settingsXmlString := string(settingsXml)
|
|
|
|
Replacer := strings.NewReplacer("
", "", "	", "")
|
|
|
|
settingsXmlString = Replacer.Replace(settingsXmlString)
|
|
|
|
|
|
|
|
xmlstring := []byte(xml.Header + settingsXmlString)
|
|
|
|
|
|
|
|
err = utils.FileWrite(projectSettingsFile, xmlstring, 0777)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Errorf("failed to write maven Settings xml: %w", err)
|
|
|
|
}
|
|
|
|
log.Entry().Infof("Successfully updated <server> details in maven project settings file : '%s'", projectSettingsFile)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-11-10 18:14:55 +02:00
|
|
|
func downloadAndCopySettingsFile(src string, dest string, utils SettingsDownloadUtils) error {
|
2020-02-25 15:17:00 +02:00
|
|
|
if len(src) == 0 {
|
|
|
|
return fmt.Errorf("Settings file source location not provided")
|
|
|
|
}
|
|
|
|
|
2020-07-30 10:35:46 +02:00
|
|
|
if len(dest) == 0 {
|
|
|
|
return fmt.Errorf("Settings file destination location not provided")
|
|
|
|
}
|
|
|
|
|
2020-02-25 15:17:00 +02:00
|
|
|
log.Entry().Debugf("Copying file \"%s\" to \"%s\"", src, dest)
|
|
|
|
|
|
|
|
if strings.HasPrefix(src, "http:") || strings.HasPrefix(src, "https:") {
|
2020-11-10 18:14:55 +02:00
|
|
|
err := downloadSettingsFromURL(src, dest, utils, true)
|
2020-07-30 10:35:46 +02:00
|
|
|
if err != nil {
|
2020-02-25 15:17:00 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
|
2020-04-24 10:41:49 +02:00
|
|
|
// for sake os symmetry it would be better to use a file protocol prefix here (file:)
|
2020-02-25 15:17:00 +02:00
|
|
|
|
|
|
|
parent := filepath.Dir(dest)
|
|
|
|
|
2020-11-10 18:14:55 +02:00
|
|
|
parentFolderExists, err := utils.FileExists(parent)
|
2020-02-25 15:17:00 +02:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
if !parentFolderExists {
|
2020-11-10 18:14:55 +02:00
|
|
|
if err = utils.MkdirAll(parent, 0775); err != nil {
|
2020-02-25 15:17:00 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-10 18:14:55 +02:00
|
|
|
if _, err := utils.Copy(src, dest); err != nil {
|
2020-02-25 15:17:00 +02:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-11-10 18:14:55 +02:00
|
|
|
func downloadSettingsIfURL(settingsFileOption, settingsFile string, utils SettingsDownloadUtils, overwrite bool) (string, error) {
|
2020-07-30 10:35:46 +02:00
|
|
|
result := settingsFileOption
|
|
|
|
if strings.HasPrefix(settingsFileOption, "http:") || strings.HasPrefix(settingsFileOption, "https:") {
|
2020-11-10 18:14:55 +02:00
|
|
|
err := downloadSettingsFromURL(settingsFileOption, settingsFile, utils, overwrite)
|
2020-07-30 10:35:46 +02:00
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
result = settingsFile
|
|
|
|
}
|
|
|
|
return result, nil
|
|
|
|
}
|
|
|
|
|
2020-11-10 18:14:55 +02:00
|
|
|
func downloadSettingsFromURL(url, filename string, utils SettingsDownloadUtils, overwrite bool) error {
|
|
|
|
exists, _ := utils.FileExists(filename)
|
2020-07-30 10:35:46 +02:00
|
|
|
if exists && !overwrite {
|
|
|
|
log.Entry().Infof("Not downloading maven settings file, because it already exists at '%s'", filename)
|
|
|
|
return nil
|
|
|
|
}
|
2020-11-10 18:14:55 +02:00
|
|
|
err := utils.DownloadFile(url, filename, nil, nil)
|
2020-07-30 10:35:46 +02:00
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("failed to download maven settings from URL '%s' to file '%s': %w",
|
|
|
|
url, filename, err)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-02-25 15:17:00 +02:00
|
|
|
func getGlobalSettingsFileDest() (string, error) {
|
|
|
|
|
|
|
|
m2Home, err := getEnvironmentVariable("M2_HOME")
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2021-09-23 15:33:30 +02:00
|
|
|
return filepath.Join(m2Home, "conf", "settings.xml"), nil
|
2020-02-25 15:17:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func getProjectSettingsFileDest() (string, error) {
|
|
|
|
home, err := getEnvironmentVariable("HOME")
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
2021-09-23 15:33:30 +02:00
|
|
|
return filepath.Join(home, ".m2", "settings.xml"), nil
|
2020-02-25 15:17:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func getEnvironmentVariable(name string) (string, error) {
|
|
|
|
|
|
|
|
envVar := getenv(name)
|
|
|
|
|
|
|
|
if len(envVar) == 0 {
|
|
|
|
return "", fmt.Errorf("Environment variable \"%s\" not set or empty", name)
|
|
|
|
}
|
|
|
|
|
|
|
|
return envVar, nil
|
|
|
|
}
|