github.com/jfrog/jfrog-cli-core/v2@v2.52.0/general/cisetup/pipelinesconfig.go (about)

     1  package cisetup
     2  
     3  import (
     4  	"strings"
     5  
     6  	"github.com/jfrog/jfrog-cli-core/v2/utils/config"
     7  	"github.com/jfrog/jfrog-cli-core/v2/utils/coreutils"
     8  	"github.com/jfrog/jfrog-client-go/artifactory"
     9  	clientConfig "github.com/jfrog/jfrog-client-go/config"
    10  	"github.com/jfrog/jfrog-client-go/pipelines"
    11  	"github.com/jfrog/jfrog-client-go/pipelines/services"
    12  	"github.com/jfrog/jfrog-client-go/utils/errorutils"
    13  	"github.com/jfrog/jfrog-client-go/utils/log"
    14  )
    15  
    16  const (
    17  	PipelinesYamlName = "pipelines.yml"
    18  )
    19  
    20  type JFrogPipelinesConfigurator struct {
    21  	SetupData      *CiSetupData
    22  	PipelinesToken string
    23  }
    24  
    25  func (pc *JFrogPipelinesConfigurator) Config() (vcsIntName, rtIntName string, err error) {
    26  	log.Info("Configuring JFrog Pipelines...")
    27  	serviceDetails, err := config.GetSpecificConfig(ConfigServerId, false, false)
    28  	if err != nil {
    29  		return "", "", err
    30  	}
    31  
    32  	psm, err := pc.createPipelinesServiceManager(serviceDetails)
    33  	if err != nil {
    34  		return "", "", err
    35  	}
    36  
    37  	vcsIntName, vcsIntId, err := pc.createVcsIntegration(psm)
    38  	if err != nil {
    39  		return "", "", err
    40  	}
    41  
    42  	rtIntName, err = pc.createArtifactoryIntegration(psm, serviceDetails)
    43  	if err != nil {
    44  		return "", "", err
    45  	}
    46  
    47  	err = pc.doAddPipelineSource(psm, vcsIntId)
    48  	if err != nil {
    49  		return "", "", err
    50  	}
    51  	return vcsIntName, rtIntName, nil
    52  }
    53  
    54  func (pc *JFrogPipelinesConfigurator) doAddPipelineSource(psm *pipelines.PipelinesServicesManager, projectIntegrationId int) (err error) {
    55  	_, err = psm.AddPipelineSource(projectIntegrationId, pc.SetupData.GetRepoFullName(), pc.SetupData.GitBranch, PipelinesYamlName)
    56  	// If source already exists, ignore error.
    57  	if _, ok := err.(*services.SourceAlreadyExistsError); ok {
    58  		log.Debug("Pipeline Source for repo '" + pc.SetupData.GetRepoFullName() + "' and branch '" + pc.SetupData.GitBranch + "' already exists and will be used.")
    59  		err = nil
    60  	}
    61  	return
    62  }
    63  
    64  func (pc *JFrogPipelinesConfigurator) createPipelinesServiceManager(details *config.ServerDetails) (*pipelines.PipelinesServicesManager, error) {
    65  	// Create new details with pipelines token.
    66  	pipelinesDetails := *details
    67  	pipelinesDetails.AccessToken = pc.PipelinesToken
    68  	pipelinesDetails.User = ""
    69  	pipelinesDetails.Password = ""
    70  
    71  	certsPath, err := coreutils.GetJfrogCertsDir()
    72  	if err != nil {
    73  		return nil, err
    74  	}
    75  	pAuth, err := pipelinesDetails.CreatePipelinesAuthConfig()
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	serviceConfig, err := clientConfig.NewConfigBuilder().
    80  		SetServiceDetails(pAuth).
    81  		SetCertificatesPath(certsPath).
    82  		SetInsecureTls(pipelinesDetails.InsecureTls).
    83  		SetDryRun(false).
    84  		Build()
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  	return pipelines.New(serviceConfig)
    89  }
    90  
    91  func (pc *JFrogPipelinesConfigurator) createVcsIntegration(psm *pipelines.PipelinesServicesManager) (integrationName string, integrationId int, err error) {
    92  	switch pc.SetupData.GitProvider {
    93  	case Github:
    94  		integrationName = pc.createIntegrationName(services.GithubName)
    95  		integrationId, err = psm.CreateGithubIntegration(integrationName, pc.SetupData.VcsCredentials.AccessToken)
    96  	case GithubEnterprise:
    97  		integrationName = pc.createIntegrationName(services.GithubEnterpriseName)
    98  		integrationId, err = psm.CreateGithubEnterpriseIntegration(integrationName, pc.SetupData.VcsBaseUrl, pc.SetupData.VcsCredentials.AccessToken)
    99  	case Bitbucket:
   100  		integrationName = pc.createIntegrationName(services.BitbucketName)
   101  		integrationId, err = psm.CreateBitbucketIntegration(integrationName, pc.SetupData.VcsCredentials.User, pc.SetupData.VcsCredentials.AccessToken)
   102  	case BitbucketServer:
   103  		integrationName = pc.createIntegrationName(services.BitbucketServerName)
   104  		cred := pc.SetupData.VcsCredentials.AccessToken
   105  		if cred == "" {
   106  			cred = pc.SetupData.VcsCredentials.Password
   107  		}
   108  		integrationId, err = psm.CreateBitbucketServerIntegration(integrationName, pc.SetupData.VcsBaseUrl, pc.SetupData.VcsCredentials.User, cred)
   109  	case Gitlab:
   110  		integrationName = pc.createIntegrationName(services.GitlabName)
   111  		integrationId, err = psm.CreateGitlabIntegration(integrationName, pc.SetupData.VcsBaseUrl, pc.SetupData.VcsCredentials.AccessToken)
   112  	default:
   113  		return "", -1, errorutils.CheckErrorf("vcs type is not supported at the moment")
   114  	}
   115  	if _, ok := err.(*services.IntegrationAlreadyExistsError); ok {
   116  		// If integration already exists, get the id from pipelines.
   117  		log.Debug("Integration '" + integrationName + "' already exists and will be used. Fetching id from pipelines...")
   118  		var integration *services.Integration
   119  		integration, err = psm.GetIntegrationByName(integrationName)
   120  		if err != nil {
   121  			return
   122  		}
   123  		integrationId = integration.Id
   124  	}
   125  	return
   126  }
   127  
   128  func (pc *JFrogPipelinesConfigurator) createArtifactoryIntegration(psm *pipelines.PipelinesServicesManager, details *config.ServerDetails) (string, error) {
   129  	integrationName := pc.createIntegrationName("rt")
   130  	apiKey, err := pc.getApiKey(details)
   131  	if err != nil {
   132  		return "", err
   133  	}
   134  	user := details.User
   135  	_, err = psm.CreateArtifactoryIntegration(integrationName, details.ArtifactoryUrl, user, apiKey)
   136  	// If integration already exists, ignore error.
   137  	if _, ok := err.(*services.IntegrationAlreadyExistsError); ok {
   138  		log.Debug("Integration '" + integrationName + "' already exists and will be used.")
   139  		err = nil
   140  	}
   141  	return integrationName, err
   142  }
   143  
   144  // Get API Key if exists, generate one if needed.
   145  func (pc *JFrogPipelinesConfigurator) getApiKey(details *config.ServerDetails) (string, error) {
   146  	// Try getting API Key for the user if exists.
   147  	asm, err := pc.createRtServiceManager(details)
   148  	if err != nil {
   149  		return "", err
   150  	}
   151  	apiKey, err := asm.GetAPIKey()
   152  	if err != nil || apiKey != "" {
   153  		return apiKey, err
   154  	}
   155  
   156  	// Generate API Key for the user.
   157  	return asm.CreateAPIKey()
   158  }
   159  
   160  func (pc *JFrogPipelinesConfigurator) createIntegrationName(intType string) string {
   161  	return intType + "_" + createPipelinesSuitableName(pc.SetupData, "integration")
   162  }
   163  
   164  func (pc *JFrogPipelinesConfigurator) createRtServiceManager(artDetails *config.ServerDetails) (artifactory.ArtifactoryServicesManager, error) {
   165  	certsPath, err := coreutils.GetJfrogCertsDir()
   166  	if err != nil {
   167  		return nil, err
   168  	}
   169  	artAuth, err := artDetails.CreateArtAuthConfig()
   170  	if err != nil {
   171  		return nil, err
   172  	}
   173  	serviceConfig, err := clientConfig.NewConfigBuilder().
   174  		SetServiceDetails(artAuth).
   175  		SetCertificatesPath(certsPath).
   176  		SetInsecureTls(artDetails.InsecureTls).
   177  		SetDryRun(false).
   178  		Build()
   179  	if err != nil {
   180  		return nil, err
   181  	}
   182  	return artifactory.New(serviceConfig)
   183  }
   184  
   185  func createPipelinesSuitableName(data *CiSetupData, suffix string) string {
   186  	name := strings.Join([]string{data.ProjectDomain, data.RepositoryName, suffix}, "_")
   187  	// Pipelines does not allow "-" which might exist in repo names.
   188  	return strings.ReplaceAll(name, "-", "_")
   189  }