github.com/jfrog/jfrog-cli-core/v2@v2.51.0/common/build/buildinfoproperties.go (about)

     1  package build
     2  
     3  import (
     4  	"net"
     5  	"net/url"
     6  	"os"
     7  	"strings"
     8  
     9  	"github.com/jfrog/jfrog-cli-core/v2/utils/config"
    10  	"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
    11  
    12  	"github.com/jfrog/jfrog-cli-core/v2/common/project"
    13  
    14  	"github.com/jfrog/jfrog-client-go/auth"
    15  	"github.com/jfrog/jfrog-client-go/utils/errorutils"
    16  	"github.com/spf13/viper"
    17  )
    18  
    19  const (
    20  	HttpProxyEnvKey  = "HTTP_PROXY"
    21  	HttpsProxyEnvKey = "HTTPS_PROXY"
    22  	NoProxyEnvKey    = "NO_PROXY"
    23  )
    24  
    25  type BuildConfigMapping map[project.ProjectType][]*map[string]string
    26  
    27  var buildTypeConfigMapping = BuildConfigMapping{
    28  	project.Maven:  {&commonConfigMapping, &mavenConfigMapping},
    29  	project.Gradle: {&commonConfigMapping, &gradleConfigMapping},
    30  }
    31  
    32  // For key/value binding
    33  const BuildName = "build.name"
    34  const BuildNumber = "build.number"
    35  const BuildProject = "build.project"
    36  const BuildTimestamp = "build.timestamp"
    37  const GeneratedBuildInfo = "buildInfo.generated"
    38  const DeployableArtifacts = "deployable.artifacts.map"
    39  const InsecureTls = "insecureTls"
    40  
    41  const ResolverPrefix = "resolver."
    42  const DeployerPrefix = "deployer."
    43  
    44  const Repo = "repo"
    45  const SnapshotRepo = "snapshotRepo"
    46  const ReleaseRepo = "releaseRepo"
    47  
    48  const ServerId = "serverId"
    49  const Url = "url"
    50  const Username = "username"
    51  const Password = "password"
    52  const DeployArtifacts = "artifacts"
    53  
    54  const MavenDescriptor = "deployMavenDescriptors"
    55  const IvyDescriptor = "deployIvyDescriptors"
    56  const IvyPattern = "ivyPattern"
    57  const ArtifactPattern = "artifactPattern"
    58  const ForkCount = "forkCount"
    59  
    60  const IncludePatterns = "includePatterns"
    61  const ExcludePatterns = "excludePatterns"
    62  const FilterExcludedArtifactsFromBuild = "filterExcludedArtifactsFromBuild"
    63  
    64  // For path and temp files
    65  const PropertiesTempPath = "jfrog/properties/"
    66  
    67  const httpProxy = "proxy."
    68  const NoProxy = "noProxy"
    69  const Host = "host"
    70  const Port = "port"
    71  const httpsProxy = httpProxy + "https."
    72  
    73  // Config mapping are used to create buildInfo properties file to be used by BuildInfo extractors.
    74  // Build config provided by the user may contain other properties that will not be included in the properties file.
    75  var defaultPropertiesValues = map[string]string{
    76  	"publish.artifacts":                                 "true",
    77  	"publish.buildInfo":                                 "false",
    78  	"publish.unstable":                                  "false",
    79  	"publish.maven":                                     "false",
    80  	"publish.ivy":                                       "false",
    81  	"buildInfoConfig.includeEnvVars":                    "false",
    82  	"buildInfoConfig.envVarsExcludePatterns":            "*password*,*psw*,*secret*,*key*,*token*,*auth*",
    83  	"buildInfo.agent.name":                              coreutils.GetClientAgentName() + "/" + coreutils.GetClientAgentVersion(),
    84  	"org.jfrog.build.extractor.maven.recorder.activate": "true",
    85  	"buildInfo.env.extractor.used":                      "true",
    86  	"publish.forkCount":                                 "3",
    87  	"publish.filterExcludedArtifactsFromBuild":          "true",
    88  }
    89  
    90  var commonConfigMapping = map[string]string{
    91  	"publish.buildInfo":                      "",
    92  	"publish.unstable":                       "",
    93  	"buildInfoConfig.includeEnvVars":         "",
    94  	"buildInfoConfig.envVarsExcludePatterns": "",
    95  	"buildInfo.agent.name":                   "",
    96  	"resolve.contextUrl":                     ResolverPrefix + Url,
    97  	"resolve.username":                       ResolverPrefix + Username,
    98  	"resolve.password":                       ResolverPrefix + Password,
    99  	"publish.contextUrl":                     DeployerPrefix + Url,
   100  	"publish.username":                       DeployerPrefix + Username,
   101  	"publish.password":                       DeployerPrefix + Password,
   102  	"publish.artifacts":                      DeployerPrefix + DeployArtifacts,
   103  	"deploy.build.name":                      BuildName,
   104  	"deploy.build.number":                    BuildNumber,
   105  	"deploy.build.project":                   BuildProject,
   106  	"deploy.build.timestamp":                 BuildTimestamp,
   107  	"buildInfo.generated.build.info":         GeneratedBuildInfo,
   108  	"buildInfo.deployable.artifacts.map":     DeployableArtifacts,
   109  	"proxy.host":                             httpProxy + Host,
   110  	"proxy.port":                             httpProxy + Port,
   111  	"proxy.username":                         httpProxy + Username,
   112  	"proxy.password":                         httpProxy + Password,
   113  	"proxy.noProxy":                          httpProxy + NoProxy,
   114  	"proxy.https.host":                       httpsProxy + Host,
   115  	"proxy.https.port":                       httpsProxy + Port,
   116  	"proxy.https.username":                   httpsProxy + Username,
   117  	"publish.forkCount":                      ForkCount,
   118  	"insecureTls":                            InsecureTls,
   119  }
   120  
   121  var mavenConfigMapping = map[string]string{
   122  	"org.jfrog.build.extractor.maven.recorder.activate": "",
   123  	"buildInfoConfig.artifactoryResolutionEnabled":      "buildInfoConfig.artifactoryResolutionEnabled",
   124  	"resolve.repoKey":                          ResolverPrefix + ReleaseRepo,
   125  	"resolve.downSnapshotRepoKey":              ResolverPrefix + SnapshotRepo,
   126  	"publish.repoKey":                          DeployerPrefix + ReleaseRepo,
   127  	"publish.snapshot.repoKey":                 DeployerPrefix + SnapshotRepo,
   128  	"publish.includePatterns":                  DeployerPrefix + IncludePatterns,
   129  	"publish.excludePatterns":                  DeployerPrefix + ExcludePatterns,
   130  	"publish.filterExcludedArtifactsFromBuild": DeployerPrefix + FilterExcludedArtifactsFromBuild,
   131  }
   132  
   133  var gradleConfigMapping = map[string]string{
   134  	"buildInfo.env.extractor.used":                      "",
   135  	"org.jfrog.build.extractor.maven.recorder.activate": "",
   136  	"resolve.repoKey":                                   ResolverPrefix + Repo,
   137  	"resolve.downSnapshotRepoKey":                       ResolverPrefix + Repo,
   138  	"publish.repoKey":                                   DeployerPrefix + Repo,
   139  	"publish.snapshot.repoKey":                          DeployerPrefix + Repo,
   140  	"publish.maven":                                     DeployerPrefix + MavenDescriptor,
   141  	"publish.ivy":                                       DeployerPrefix + IvyDescriptor,
   142  	"publish.ivy.ivyPattern":                            DeployerPrefix + IvyPattern,
   143  	"publish.ivy.artPattern":                            DeployerPrefix + ArtifactPattern,
   144  }
   145  
   146  func ReadMavenConfig(path string, mvnProps map[string]any) (config *viper.Viper, err error) {
   147  	if path == "" {
   148  		config = createDefaultConfigWithParams(project.YAML, project.Maven.String(), mvnProps)
   149  	} else {
   150  		config, err = project.ReadConfigFile(path, project.YAML)
   151  	}
   152  	return
   153  }
   154  
   155  func createDefaultConfigWithParams(configType project.ConfigType, technology string, params map[string]any) *viper.Viper {
   156  	vConfig := viper.New()
   157  	vConfig.SetConfigType(string(configType))
   158  	vConfig.Set("type", technology)
   159  	for key, value := range params {
   160  		vConfig.Set(key, value)
   161  	}
   162  	return vConfig
   163  }
   164  
   165  // Returns the Artifactory details
   166  // Checks first for the deployer information if exists and if not, checks for the resolver information.
   167  func GetServerDetails(vConfig *viper.Viper) (*config.ServerDetails, error) {
   168  	if vConfig.IsSet(DeployerPrefix + ServerId) {
   169  		serverId := vConfig.GetString(DeployerPrefix + ServerId)
   170  		return config.GetSpecificConfig(serverId, true, true)
   171  	}
   172  
   173  	if vConfig.IsSet(ResolverPrefix + ServerId) {
   174  		serverId := vConfig.GetString(ResolverPrefix + ServerId)
   175  		return config.GetSpecificConfig(serverId, true, true)
   176  	}
   177  	return nil, nil
   178  }
   179  
   180  func CreateBuildInfoProps(buildArtifactsDetailsFile string, config *viper.Viper, projectType project.ProjectType) (map[string]string, error) {
   181  	if config.GetString("type") != projectType.String() {
   182  		return nil, errorutils.CheckErrorf("Incompatible build config, expected: " + projectType.String() + " got: " + config.GetString("type"))
   183  	}
   184  	if err := setServerDetailsToConfig(ResolverPrefix, config); err != nil {
   185  		return nil, err
   186  	}
   187  	if err := setServerDetailsToConfig(DeployerPrefix, config); err != nil {
   188  		return nil, err
   189  	}
   190  	if err := setProxyIfDefined(config); err != nil {
   191  		return nil, err
   192  	}
   193  	if buildArtifactsDetailsFile != "" {
   194  		config.Set(DeployableArtifacts, buildArtifactsDetailsFile)
   195  	}
   196  	return createProps(config, projectType), nil
   197  }
   198  
   199  func createProps(config *viper.Viper, projectType project.ProjectType) map[string]string {
   200  	props := make(map[string]string)
   201  	// Iterate over all the required properties keys according to the buildType and create properties file.
   202  	// If a value is provided by the build config file write it,
   203  	// otherwise use the default value from defaultPropertiesValues map.
   204  	for _, partialMapping := range buildTypeConfigMapping[projectType] {
   205  		for propKey, configKey := range *partialMapping {
   206  			var value string
   207  			if config.IsSet(configKey) {
   208  				value = config.GetString(configKey)
   209  			} else if defaultVal, ok := defaultPropertiesValues[propKey]; ok {
   210  				value = defaultVal
   211  			}
   212  			if value != "" {
   213  				props[propKey] = value
   214  				// Properties that have the 'artifactory.' prefix are deprecated.
   215  				// For backward compatibility reasons, both will be added to the props map.
   216  				if !strings.HasPrefix(propKey, "artifactory.") {
   217  					props["artifactory."+propKey] = value
   218  				}
   219  			}
   220  		}
   221  	}
   222  	return props
   223  }
   224  
   225  // If one of the HTTP_PROXY, HTTPS_PROXY or No_PROXY environment variables are set, add to the config proxy details.
   226  func setProxyIfDefined(config *viper.Viper) error {
   227  	setNoProxyIfDefined(config)
   228  	if err := setHttpProxy(config); err != nil {
   229  		return err
   230  	}
   231  	return setHttpsProxy(config)
   232  }
   233  
   234  func setHttpProxy(config *viper.Viper) error {
   235  	var proxyConfig string
   236  	if proxyConfig = os.Getenv(HttpProxyEnvKey); proxyConfig == "" {
   237  		return nil
   238  	}
   239  	host, port, username, password, err := parseProxy(proxyConfig)
   240  	if err != nil {
   241  		return err
   242  	}
   243  	config.Set(httpProxy+Host, host)
   244  	config.Set(httpProxy+Port, port)
   245  	config.Set(httpProxy+Username, username)
   246  	return os.Setenv(httpProxy+Password, password)
   247  }
   248  
   249  func setHttpsProxy(config *viper.Viper) error {
   250  	var proxyConfig string
   251  	if proxyConfig = os.Getenv(HttpsProxyEnvKey); proxyConfig == "" {
   252  		return nil
   253  	}
   254  	host, port, username, password, err := parseProxy(proxyConfig)
   255  	if err != nil {
   256  		return err
   257  	}
   258  	config.Set(httpsProxy+Host, host)
   259  	config.Set(httpsProxy+Port, port)
   260  	config.Set(httpsProxy+Username, username)
   261  	return os.Setenv(httpsProxy+Password, password)
   262  }
   263  
   264  func setNoProxyIfDefined(config *viper.Viper) {
   265  	noProxy := os.Getenv(NoProxyEnvKey)
   266  	if noProxy != "" {
   267  		config.Set(httpProxy+NoProxy, noProxy)
   268  	}
   269  }
   270  
   271  func parseProxy(proxy string) (host string, port string, username string, password string, err error) {
   272  	url, err := url.Parse(proxy)
   273  	if err != nil {
   274  		err = errorutils.CheckError(err)
   275  		return
   276  	}
   277  	host, port, err = net.SplitHostPort(url.Host)
   278  	if err != nil {
   279  		err = errorutils.CheckError(err)
   280  		return
   281  	}
   282  	password, _ = url.User.Password()
   283  	username = url.User.Username()
   284  	return
   285  }
   286  
   287  func setServerDetailsToConfig(contextPrefix string, vConfig *viper.Viper) error {
   288  	if !vConfig.IsSet(contextPrefix + ServerId) {
   289  		return nil
   290  	}
   291  
   292  	serverId := vConfig.GetString(contextPrefix + ServerId)
   293  	artDetails, err := config.GetSpecificConfig(serverId, true, true)
   294  	if err != nil {
   295  		return err
   296  	}
   297  	if artDetails.GetArtifactoryUrl() == "" {
   298  		return errorutils.CheckErrorf("Server ID " + serverId + ": URL is required.")
   299  	}
   300  	vConfig.Set(contextPrefix+Url, artDetails.GetArtifactoryUrl())
   301  
   302  	username := artDetails.GetUser()
   303  	password := artDetails.GetPassword()
   304  	if artDetails.GetAccessToken() != "" {
   305  		if username == "" {
   306  			username = auth.ExtractUsernameFromAccessToken(artDetails.GetAccessToken())
   307  		}
   308  		password = artDetails.GetAccessToken()
   309  	}
   310  	vConfig.Set(contextPrefix+Username, username)
   311  	vConfig.Set(contextPrefix+Password, password)
   312  	return nil
   313  }