1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-09-16 09:26:22 +02:00

refactor(orchestrator): Use singleton in orchestrator package and rename methods (#4639)

* rename interface, types and methods.
some type changes and refactor

* update dependent methods and variables

* fix unit tests

* a bit more refactor and fix

* concurrent safe singleton

* return old Options struct

* refactor creating config provider and fix nil pointer derefernce

* fix unit test and linter errors

* introduce resetting config provider (for unit tests)

* fix annoying error message when config provider is not configured

---------

Co-authored-by: Gulom Alimov <gulomjon.alimov@sap.com>
Co-authored-by: Muhammadali Nazarov <muhammadalinazarov@gmail.com>
This commit is contained in:
Googlom
2024-01-09 16:01:15 +05:00
committed by GitHub
parent a5ea24dfb0
commit ac5cf17317
27 changed files with 472 additions and 528 deletions

1
.gitignore vendored
View File

@@ -32,6 +32,7 @@ debug.test
/piper_master.exe
/jenkins-library
/jenkins-library.exe
node_modules/
# piper binary outputs
.pipeline/commonPipelineEnvironment/

View File

@@ -66,7 +66,7 @@ type artifactPrepareVersionUtils interface {
FileRead(path string) ([]byte, error)
FileRemove(path string) error
NewOrchestratorSpecificConfigProvider() (orchestrator.OrchestratorSpecificConfigProviding, error)
GetConfigProvider() (orchestrator.ConfigProvider, error)
}
type artifactPrepareVersionUtilsBundle struct {
@@ -75,8 +75,8 @@ type artifactPrepareVersionUtilsBundle struct {
*piperhttp.Client
}
func (a *artifactPrepareVersionUtilsBundle) NewOrchestratorSpecificConfigProvider() (orchestrator.OrchestratorSpecificConfigProviding, error) {
return orchestrator.NewOrchestratorSpecificConfigProvider()
func (a *artifactPrepareVersionUtilsBundle) GetConfigProvider() (orchestrator.ConfigProvider, error) {
return orchestrator.GetOrchestratorConfigProvider(nil)
}
func newArtifactPrepareVersionUtilsBundle() artifactPrepareVersionUtils {
@@ -160,7 +160,7 @@ func runArtifactPrepareVersion(config *artifactPrepareVersionOptions, telemetryD
if config.VersioningType == "cloud" || config.VersioningType == "cloud_noTag" {
// make sure that versioning does not create tags (when set to "cloud")
// for PR pipelines, optimized pipelines (= no build)
provider, err := utils.NewOrchestratorSpecificConfigProvider()
provider, err := utils.GetConfigProvider()
if err != nil {
log.Entry().WithError(err).Warning("Cannot infer config from CI environment")
}

View File

@@ -192,7 +192,7 @@ func (a *artifactPrepareVersionMockUtils) DownloadFile(url, filename string, hea
return nil
}
func (a *artifactPrepareVersionMockUtils) NewOrchestratorSpecificConfigProvider() (orchestrator.OrchestratorSpecificConfigProviding, error) {
func (a *artifactPrepareVersionMockUtils) GetConfigProvider() (orchestrator.ConfigProvider, error) {
return &orchestrator.UnknownOrchestratorConfigProvider{}, nil
}

View File

@@ -130,20 +130,20 @@ func initGitInfo(config *codeqlExecuteScanOptions) (codeql.RepoInfo, error) {
repoInfo.Ref = config.AnalyzedRef
repoInfo.CommitId = config.CommitID
provider, err := orchestrator.NewOrchestratorSpecificConfigProvider()
provider, err := orchestrator.GetOrchestratorConfigProvider(nil)
if err != nil {
log.Entry().Warn("No orchestrator found. We assume piper is running locally.")
} else {
if repoInfo.Ref == "" {
repoInfo.Ref = provider.GetReference()
repoInfo.Ref = provider.GitReference()
}
if repoInfo.CommitId == "" || repoInfo.CommitId == "NA" {
repoInfo.CommitId = provider.GetCommit()
repoInfo.CommitId = provider.CommitSHA()
}
if repoInfo.ServerUrl == "" {
err = getGitRepoInfo(provider.GetRepoURL(), &repoInfo)
err = getGitRepoInfo(provider.RepoURL(), &repoInfo)
if err != nil {
log.Entry().Error(err)
}

View File

@@ -249,7 +249,7 @@ func TestInitGitInfo(t *testing.T) {
config := codeqlExecuteScanOptions{Repository: "https://github.hello.test", AnalyzedRef: "refs/head/branch", CommitID: "abcd1234"}
repoInfo, err := initGitInfo(&config)
assert.NoError(t, err)
_, err = orchestrator.NewOrchestratorSpecificConfigProvider()
_, err = orchestrator.GetOrchestratorConfigProvider(nil)
assert.Equal(t, "abcd1234", repoInfo.CommitId)
assert.Equal(t, "refs/head/branch", repoInfo.Ref)
if err != nil {

View File

@@ -42,14 +42,14 @@ func newCDUtils() credentialdiggerUtils {
func credentialdiggerScan(config credentialdiggerScanOptions, telemetryData *telemetry.CustomData) error {
utils := newCDUtils()
// 0: Get attributes from orchestrator
provider, prov_err := orchestrator.NewOrchestratorSpecificConfigProvider()
provider, prov_err := orchestrator.GetOrchestratorConfigProvider(nil)
if prov_err != nil {
log.Entry().WithError(prov_err).Error(
"credentialdiggerScan: unable to load orchestrator specific configuration.")
}
if config.Repository == "" {
// Get current repository from orchestrator
repoUrlOrchestrator := provider.GetRepoURL()
repoUrlOrchestrator := provider.RepoURL()
if repoUrlOrchestrator == "n/a" {
// Jenkins configuration error
log.Entry().WithError(errors.New(
@@ -61,7 +61,7 @@ func credentialdiggerScan(config credentialdiggerScanOptions, telemetryData *tel
}
if provider.IsPullRequest() {
// set the pr number
config.PrNumber, _ = strconv.Atoi(provider.GetPullRequestConfig().Key)
config.PrNumber, _ = strconv.Atoi(provider.PullRequestConfig().Key)
log.Entry().Debug("Scan the current pull request: number ", config.PrNumber)
}

View File

@@ -46,7 +46,7 @@ type detectUtils interface {
GetIssueService() *github.IssuesService
GetSearchService() *github.SearchService
GetProvider() orchestrator.OrchestratorSpecificConfigProviding
GetProvider() orchestrator.ConfigProvider
}
type detectUtilsBundle struct {
@@ -55,7 +55,7 @@ type detectUtilsBundle struct {
*piperhttp.Client
issues *github.IssuesService
search *github.SearchService
provider orchestrator.OrchestratorSpecificConfigProviding
provider orchestrator.ConfigProvider
}
func (d *detectUtilsBundle) GetIssueService() *github.IssuesService {
@@ -66,7 +66,7 @@ func (d *detectUtilsBundle) GetSearchService() *github.SearchService {
return d.search
}
func (d *detectUtilsBundle) GetProvider() orchestrator.OrchestratorSpecificConfigProviding {
func (d *detectUtilsBundle) GetProvider() orchestrator.ConfigProvider {
return d.provider
}
@@ -112,7 +112,7 @@ func newDetectUtils(client *github.Client) detectUtils {
utils.Stdout(log.Writer())
utils.Stderr(log.Writer())
provider, err := orchestrator.NewOrchestratorSpecificConfigProvider()
provider, err := orchestrator.GetOrchestratorConfigProvider(nil)
if err != nil {
log.Entry().WithError(err).Warning(err)
provider = &orchestrator.UnknownOrchestratorConfigProvider{}
@@ -568,9 +568,9 @@ func isMajorVulnerability(v bd.Vulnerability) bool {
}
func postScanChecksAndReporting(ctx context.Context, config detectExecuteScanOptions, influx *detectExecuteScanInflux, utils detectUtils, sys *blackduckSystem) error {
if utils.GetProvider().IsPullRequest() {
issueNumber, err := strconv.Atoi(utils.GetProvider().GetPullRequestConfig().Key)
provider := utils.GetProvider()
if provider.IsPullRequest() {
issueNumber, err := strconv.Atoi(provider.PullRequestConfig().Key)
if err != nil {
log.Entry().Warning("Can not get issue number ", err)
return nil

View File

@@ -33,7 +33,7 @@ type detectTestUtilsBundle struct {
orchestrator *orchestratorConfigProviderMock
}
func (d *detectTestUtilsBundle) GetProvider() orchestrator.OrchestratorSpecificConfigProviding {
func (d *detectTestUtilsBundle) GetProvider() orchestrator.ConfigProvider {
return d.orchestrator
}

View File

@@ -212,16 +212,13 @@ func Execute() {
}
func addRootFlags(rootCmd *cobra.Command) {
var provider orchestrator.OrchestratorSpecificConfigProviding
var err error
provider, err = orchestrator.NewOrchestratorSpecificConfigProvider()
provider, err := orchestrator.GetOrchestratorConfigProvider(nil)
if err != nil {
log.Entry().Error(err)
provider = &orchestrator.UnknownOrchestratorConfigProvider{}
}
rootCmd.PersistentFlags().StringVar(&GeneralConfig.CorrelationID, "correlationID", provider.GetBuildURL(), "ID for unique identification of a pipeline run")
rootCmd.PersistentFlags().StringVar(&GeneralConfig.CorrelationID, "correlationID", provider.BuildURL(), "ID for unique identification of a pipeline run")
rootCmd.PersistentFlags().StringVar(&GeneralConfig.CustomConfig, "customConfig", ".pipeline/config.yml", "Path to the pipeline configuration file")
rootCmd.PersistentFlags().StringSliceVar(&GeneralConfig.GitHubTokens, "gitHubTokens", AccessTokensFromEnvJSON(os.Getenv("PIPER_gitHubTokens")), "List of entries in form of <hostname>:<token> to allow GitHub token authentication for downloading config / defaults")
rootCmd.PersistentFlags().StringSliceVar(&GeneralConfig.DefaultConfig, "defaultConfig", []string{".pipeline/defaults.yaml"}, "Default configurations, passed as path to yaml file")
@@ -290,12 +287,12 @@ func initStageName(outputToLog bool) {
}
// Use stageName from ENV as fall-back, for when extracting it from parametersJSON fails below
provider, err := orchestrator.NewOrchestratorSpecificConfigProvider()
provider, err := orchestrator.GetOrchestratorConfigProvider(nil)
if err != nil {
log.Entry().WithError(err).Warning("Cannot infer stage name from CI environment")
} else {
stageNameSource = "env variable"
GeneralConfig.StageName = provider.GetStageName()
GeneralConfig.StageName = provider.StageName()
}
if len(GeneralConfig.ParametersJSON) == 0 {

View File

@@ -7,6 +7,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"github.com/SAP/jenkins-library/pkg/orchestrator"
"os"
"path/filepath"
"strings"
@@ -62,6 +63,7 @@ func TestAdoptStageNameFromParametersJSON(t *testing.T) {
// init
defer resetEnv(os.Environ())
os.Clearenv()
orchestrator.ResetConfigProvider()
//mock Jenkins env
os.Setenv("JENKINS_HOME", "anything")

View File

@@ -477,14 +477,14 @@ func getTempDir() string {
// Fetches parameters from environment variables and updates the options accordingly (only if not already set)
func detectParametersFromCI(options *sonarExecuteScanOptions) {
provider, err := orchestrator.NewOrchestratorSpecificConfigProvider()
provider, err := orchestrator.GetOrchestratorConfigProvider(nil)
if err != nil {
log.Entry().WithError(err).Warning("Cannot infer config from CI environment")
return
}
if provider.IsPullRequest() {
config := provider.GetPullRequestConfig()
config := provider.PullRequestConfig()
if len(options.ChangeBranch) == 0 {
log.Entry().Info("Inferring parameter changeBranch from environment: " + config.Branch)
options.ChangeBranch = config.Branch
@@ -498,7 +498,7 @@ func detectParametersFromCI(options *sonarExecuteScanOptions) {
options.ChangeID = config.Key
}
} else {
branch := provider.GetBranch()
branch := provider.Branch()
if options.InferBranchName && len(options.BranchName) == 0 {
log.Entry().Info("Inferring parameter branchName from environment: " + branch)
options.BranchName = branch

View File

@@ -11,24 +11,30 @@ import (
"github.com/SAP/jenkins-library/pkg/log"
)
type AzureDevOpsConfigProvider struct {
type azureDevopsConfigProvider struct {
client piperHttp.Client
apiInformation map[string]interface{}
}
// InitOrchestratorProvider initializes http client for AzureDevopsConfigProvider
func (a *AzureDevOpsConfigProvider) InitOrchestratorProvider(settings *OrchestratorSettings) {
func newAzureDevopsConfigProvider() *azureDevopsConfigProvider {
return &azureDevopsConfigProvider{}
}
// Configure initializes http client for AzureDevopsConfigProvider
func (a *azureDevopsConfigProvider) Configure(opts *Options) error {
a.client.SetOptions(piperHttp.ClientOptions{
Username: "",
Password: settings.AzureToken,
Password: opts.AzureToken,
MaxRetries: 3,
TransportTimeout: time.Second * 10,
})
log.Entry().Debug("Successfully initialized Azure config provider")
return nil
}
// fetchAPIInformation fetches Azure API information of current build
func (a *AzureDevOpsConfigProvider) fetchAPIInformation() {
func (a *azureDevopsConfigProvider) fetchAPIInformation() {
// if apiInformation is empty fill it otherwise do nothing
if len(a.apiInformation) == 0 {
log.Entry().Debugf("apiInformation is empty, getting infos from API")
@@ -57,45 +63,45 @@ func (a *AzureDevOpsConfigProvider) fetchAPIInformation() {
}
}
func (a *AzureDevOpsConfigProvider) GetChangeSet() []ChangeSet {
log.Entry().Warn("GetChangeSet for AzureDevOps not yet implemented")
func (a *azureDevopsConfigProvider) ChangeSets() []ChangeSet {
log.Entry().Warn("ChangeSets for AzureDevOps not yet implemented")
return []ChangeSet{}
}
// getSystemCollectionURI returns the URI of the TFS collection or Azure DevOps organization e.g. https://dev.azure.com/fabrikamfiber/
func (a *AzureDevOpsConfigProvider) getSystemCollectionURI() string {
func (a *azureDevopsConfigProvider) getSystemCollectionURI() string {
return getEnv("SYSTEM_COLLECTIONURI", "n/a")
}
// getTeamProjectID is the name of the project that contains this build e.g. 123a4567-ab1c-12a1-1234-123456ab7890
func (a *AzureDevOpsConfigProvider) getTeamProjectID() string {
func (a *azureDevopsConfigProvider) getTeamProjectID() string {
return getEnv("SYSTEM_TEAMPROJECTID", "n/a")
}
// getAzureBuildID returns the id of the build, e.g. 1234
func (a *AzureDevOpsConfigProvider) getAzureBuildID() string {
func (a *azureDevopsConfigProvider) getAzureBuildID() string {
// INFO: Private function only used for API requests, buildId for e.g. reporting
// is GetBuildNumber to align with the UI of ADO
return getEnv("BUILD_BUILDID", "n/a")
}
// GetJobName returns the pipeline job name, currently org/repo
func (a *AzureDevOpsConfigProvider) GetJobName() string {
// JobName returns the pipeline job name, currently org/repo
func (a *azureDevopsConfigProvider) JobName() string {
return getEnv("BUILD_REPOSITORY_NAME", "n/a")
}
// OrchestratorVersion returns the agent version on ADO
func (a *AzureDevOpsConfigProvider) OrchestratorVersion() string {
func (a *azureDevopsConfigProvider) OrchestratorVersion() string {
return getEnv("AGENT_VERSION", "n/a")
}
// OrchestratorType returns the orchestrator name e.g. Azure/GitHubActions/Jenkins
func (a *AzureDevOpsConfigProvider) OrchestratorType() string {
func (a *azureDevopsConfigProvider) OrchestratorType() string {
return "Azure"
}
// GetBuildStatus returns status of the build. Return variables are aligned with Jenkins build statuses.
func (a *AzureDevOpsConfigProvider) GetBuildStatus() string {
// BuildStatus returns status of the build. Return variables are aligned with Jenkins build statuses.
func (a *azureDevopsConfigProvider) BuildStatus() string {
// cases to align with Jenkins: SUCCESS, FAILURE, NOT_BUILD, ABORTED
switch buildStatus := getEnv("AGENT_JOBSTATUS", "FAILURE"); buildStatus {
case "Succeeded":
@@ -108,8 +114,8 @@ func (a *AzureDevOpsConfigProvider) GetBuildStatus() string {
}
}
// GetLog returns the whole logfile for the current pipeline run
func (a *AzureDevOpsConfigProvider) GetLog() ([]byte, error) {
// FullLogs returns the whole logfile for the current pipeline run
func (a *azureDevopsConfigProvider) FullLogs() ([]byte, error) {
URL := a.getSystemCollectionURI() + a.getTeamProjectID() + "/_apis/build/builds/" + a.getAzureBuildID() + "/logs"
response, err := a.client.GetRequest(URL, nil, nil)
@@ -161,8 +167,8 @@ func (a *AzureDevOpsConfigProvider) GetLog() ([]byte, error) {
return logs, nil
}
// GetPipelineStartTime returns the pipeline start time in UTC
func (a *AzureDevOpsConfigProvider) GetPipelineStartTime() time.Time {
// PipelineStartTime returns the pipeline start time in UTC
func (a *azureDevopsConfigProvider) PipelineStartTime() time.Time {
//"2022-03-18T07:30:31.1915758Z"
a.fetchAPIInformation()
if val, ok := a.apiInformation["startTime"]; ok {
@@ -176,59 +182,59 @@ func (a *AzureDevOpsConfigProvider) GetPipelineStartTime() time.Time {
return time.Time{}.UTC()
}
// GetBuildID returns the BuildNumber displayed in the ADO UI
func (a *AzureDevOpsConfigProvider) GetBuildID() string {
// BuildID returns the BuildNumber displayed in the ADO UI
func (a *azureDevopsConfigProvider) BuildID() string {
// INFO: ADO has BUILD_ID and buildNumber, as buildNumber is used in the UI we return this value
// for the buildID used only for API requests we have a private method getAzureBuildID
// example: buildNumber: 20220318.16 buildId: 76443
return getEnv("BUILD_BUILDNUMBER", "n/a")
}
// GetStageName returns the human-readable name given to a stage. e.g. "Promote" or "Init"
func (a *AzureDevOpsConfigProvider) GetStageName() string {
// StageName returns the human-readable name given to a stage. e.g. "Promote" or "Init"
func (a *azureDevopsConfigProvider) StageName() string {
return getEnv("SYSTEM_STAGEDISPLAYNAME", "n/a")
}
// GetBranch returns the source branch name, e.g. main
func (a *AzureDevOpsConfigProvider) GetBranch() string {
// Branch returns the source branch name, e.g. main
func (a *azureDevopsConfigProvider) Branch() string {
tmp := getEnv("BUILD_SOURCEBRANCH", "n/a")
return strings.TrimPrefix(tmp, "refs/heads/")
}
// GetReference return the git reference
func (a *AzureDevOpsConfigProvider) GetReference() string {
// GitReference return the git reference
func (a *azureDevopsConfigProvider) GitReference() string {
return getEnv("BUILD_SOURCEBRANCH", "n/a")
}
// GetBuildURL returns the builds URL e.g. https://dev.azure.com/fabrikamfiber/your-repo-name/_build/results?buildId=1234
func (a *AzureDevOpsConfigProvider) GetBuildURL() string {
// BuildURL returns the builds URL e.g. https://dev.azure.com/fabrikamfiber/your-repo-name/_build/results?buildId=1234
func (a *azureDevopsConfigProvider) BuildURL() string {
return os.Getenv("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI") + os.Getenv("SYSTEM_TEAMPROJECT") + "/" + os.Getenv("SYSTEM_DEFINITIONNAME") + "/_build/results?buildId=" + a.getAzureBuildID()
}
// GetJobURL returns tje current job url e.g. https://dev.azure.com/fabrikamfiber/your-repo-name/_build?definitionId=1234
func (a *AzureDevOpsConfigProvider) GetJobURL() string {
// JobURL returns tje current job url e.g. https://dev.azure.com/fabrikamfiber/your-repo-name/_build?definitionId=1234
func (a *azureDevopsConfigProvider) JobURL() string {
// TODO: Check if this is the correct URL
return os.Getenv("SYSTEM_TEAMFOUNDATIONCOLLECTIONURI") + os.Getenv("SYSTEM_TEAMPROJECT") + "/" + os.Getenv("SYSTEM_DEFINITIONNAME") + "/_build?definitionId=" + os.Getenv("SYSTEM_DEFINITIONID")
}
// GetCommit returns commit SHA of current build
func (a *AzureDevOpsConfigProvider) GetCommit() string {
// CommitSHA returns commit SHA of current build
func (a *azureDevopsConfigProvider) CommitSHA() string {
return getEnv("BUILD_SOURCEVERSION", "n/a")
}
// GetRepoURL returns current repo URL e.g. https://github.com/SAP/jenkins-library
func (a *AzureDevOpsConfigProvider) GetRepoURL() string {
// RepoURL returns current repo URL e.g. https://github.com/SAP/jenkins-library
func (a *azureDevopsConfigProvider) RepoURL() string {
return getEnv("BUILD_REPOSITORY_URI", "n/a")
}
// GetBuildReason returns the build reason
func (a *AzureDevOpsConfigProvider) GetBuildReason() string {
// BuildReason returns the build reason
func (a *azureDevopsConfigProvider) BuildReason() string {
// https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#build-variables-devops-services
return getEnv("BUILD_REASON", "n/a")
}
// GetPullRequestConfig returns pull request configuration
func (a *AzureDevOpsConfigProvider) GetPullRequestConfig() PullRequestConfig {
// PullRequestConfig returns pull request configuration
func (a *azureDevopsConfigProvider) PullRequestConfig() PullRequestConfig {
prKey := getEnv("SYSTEM_PULLREQUEST_PULLREQUESTID", "n/a")
// This variable is populated for pull requests which have a different pull request ID and pull request number.
@@ -247,11 +253,11 @@ func (a *AzureDevOpsConfigProvider) GetPullRequestConfig() PullRequestConfig {
}
// IsPullRequest indicates whether the current build is a PR
func (a *AzureDevOpsConfigProvider) IsPullRequest() bool {
func (a *azureDevopsConfigProvider) IsPullRequest() bool {
return getEnv("BUILD_REASON", "n/a") == "PullRequest"
}
func isAzure() bool {
envVars := []string{"AZURE_HTTP_USER_AGENT"}
return areIndicatingEnvVarsSet(envVars)
return envVarsAreSet(envVars)
}

View File

@@ -30,16 +30,16 @@ func TestAzure(t *testing.T) {
os.Setenv("BUILD_REPOSITORY_URI", "github.com/foo/bar")
os.Setenv("SYSTEM_DEFINITIONNAME", "bar")
os.Setenv("SYSTEM_DEFINITIONID", "1234")
p, _ := NewOrchestratorSpecificConfigProvider()
p, _ := GetOrchestratorConfigProvider(nil)
assert.False(t, p.IsPullRequest())
assert.Equal(t, "feat/test-azure", p.GetBranch())
assert.Equal(t, "refs/heads/feat/test-azure", p.GetReference())
assert.Equal(t, "https://pogo.sap/foo/bar/_build/results?buildId=42", p.GetBuildURL())
assert.Equal(t, "abcdef42713", p.GetCommit())
assert.Equal(t, "github.com/foo/bar", p.GetRepoURL())
assert.Equal(t, "feat/test-azure", p.Branch())
assert.Equal(t, "refs/heads/feat/test-azure", p.GitReference())
assert.Equal(t, "https://pogo.sap/foo/bar/_build/results?buildId=42", p.BuildURL())
assert.Equal(t, "abcdef42713", p.CommitSHA())
assert.Equal(t, "github.com/foo/bar", p.RepoURL())
assert.Equal(t, "Azure", p.OrchestratorType())
assert.Equal(t, "https://pogo.sap/foo/bar/_build?definitionId=1234", p.GetJobURL())
assert.Equal(t, "https://pogo.sap/foo/bar/_build?definitionId=1234", p.JobURL())
})
t.Run("PR", func(t *testing.T) {
@@ -50,8 +50,8 @@ func TestAzure(t *testing.T) {
os.Setenv("SYSTEM_PULLREQUEST_PULLREQUESTID", "42")
os.Setenv("BUILD_REASON", "PullRequest")
p := AzureDevOpsConfigProvider{}
c := p.GetPullRequestConfig()
p := azureDevopsConfigProvider{}
c := p.PullRequestConfig()
assert.True(t, p.IsPullRequest())
assert.Equal(t, "feat/test-azure", c.Branch)
@@ -68,8 +68,8 @@ func TestAzure(t *testing.T) {
os.Setenv("SYSTEM_PULLREQUEST_PULLREQUESTNUMBER", "42")
os.Setenv("BUILD_REASON", "PullRequest")
p := AzureDevOpsConfigProvider{}
c := p.GetPullRequestConfig()
p := azureDevopsConfigProvider{}
c := p.PullRequestConfig()
assert.True(t, p.IsPullRequest())
assert.Equal(t, "feat/test-azure", c.Branch)
@@ -98,14 +98,14 @@ func TestAzure(t *testing.T) {
os.Setenv("BUILD_BUILDNUMBER", "20220318.16")
os.Setenv("BUILD_REPOSITORY_NAME", "repo-org/repo-name")
p := AzureDevOpsConfigProvider{}
p := azureDevopsConfigProvider{}
assert.Equal(t, "https://dev.azure.com/fabrikamfiber/", p.getSystemCollectionURI())
assert.Equal(t, "123a4567-ab1c-12a1-1234-123456ab7890", p.getTeamProjectID())
assert.Equal(t, "42", p.getAzureBuildID()) // Don't confuse getAzureBuildID and GetBuildID!
assert.Equal(t, "20220318.16", p.GetBuildID()) // buildNumber is used in the UI
assert.Equal(t, "42", p.getAzureBuildID()) // Don't confuse getAzureBuildID and provider.BuildID!
assert.Equal(t, "20220318.16", p.BuildID()) // buildNumber is used in the UI
assert.Equal(t, "2.193.0", p.OrchestratorVersion())
assert.Equal(t, "repo-org/repo-name", p.GetJobName())
assert.Equal(t, "repo-org/repo-name", p.JobName())
})
}
@@ -140,10 +140,10 @@ func TestAzureDevOpsConfigProvider_GetPipelineStartTime(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := &AzureDevOpsConfigProvider{}
a := &azureDevopsConfigProvider{}
a.apiInformation = tt.apiInformation
pipelineStartTime := a.GetPipelineStartTime()
assert.Equalf(t, tt.want, pipelineStartTime, "GetPipelineStartTime()")
pipelineStartTime := a.PipelineStartTime()
assert.Equalf(t, tt.want, pipelineStartTime, "PipelineStartTime()")
})
}
}
@@ -181,9 +181,9 @@ func TestAzureDevOpsConfigProvider_GetBuildStatus(t *testing.T) {
defer resetEnv(os.Environ())
os.Clearenv()
os.Setenv("AGENT_JOBSTATUS", tt.envVar)
a := &AzureDevOpsConfigProvider{}
a := &azureDevopsConfigProvider{}
assert.Equalf(t, tt.want, a.GetBuildStatus(), "GetBuildStatus()")
assert.Equalf(t, tt.want, a.BuildStatus(), "BuildStatus()")
})
}
}
@@ -229,7 +229,7 @@ func TestAzureDevOpsConfigProvider_getAPIInformation(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := &AzureDevOpsConfigProvider{
a := &azureDevopsConfigProvider{
apiInformation: tt.apiInformation,
}
@@ -311,7 +311,7 @@ func TestAzureDevOpsConfigProvider_GetLog(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
a := &AzureDevOpsConfigProvider{}
a := &azureDevopsConfigProvider{}
a.client.SetOptions(piperhttp.ClientOptions{
MaxRequestDuration: 5 * time.Second,
Token: "TOKEN",
@@ -355,11 +355,11 @@ func TestAzureDevOpsConfigProvider_GetLog(t *testing.T) {
})
},
)
got, err := a.GetLog()
if !tt.wantErr(t, err, fmt.Sprintf("GetLog()")) {
got, err := a.FullLogs()
if !tt.wantErr(t, err, fmt.Sprintf("FullLogs()")) {
return
}
assert.Equalf(t, tt.want, got, "GetLog()")
assert.Equalf(t, tt.want, got, "FullLogs()")
})
}
}

View File

@@ -19,7 +19,7 @@ import (
"golang.org/x/sync/errgroup"
)
type GitHubActionsConfigProvider struct {
type githubActionsConfigProvider struct {
client *github.Client
ctx context.Context
owner string
@@ -46,31 +46,37 @@ type fullLog struct {
b [][]byte
}
// InitOrchestratorProvider initializes http client for GitHubActionsDevopsConfigProvider
func (g *GitHubActionsConfigProvider) InitOrchestratorProvider(settings *OrchestratorSettings) {
var err error
g.ctx, g.client, err = piperGithub.NewClientBuilder(settings.GitHubToken, getEnv("GITHUB_API_URL", "")).Build()
if err != nil {
log.Entry().Errorf("failed to create github client: %v", err)
return
func newGithubActionsConfigProvider() *githubActionsConfigProvider {
owner, repo := getOwnerAndRepoNames()
return &githubActionsConfigProvider{
owner: owner,
repo: repo,
}
g.owner, g.repo = getOwnerAndRepoNames()
log.Entry().Debug("Successfully initialized GitHubActions config provider")
}
func (g *GitHubActionsConfigProvider) OrchestratorVersion() string {
// Configure initializes http client for GitHubActionsDevopsConfigProvider
func (g *githubActionsConfigProvider) Configure(opts *Options) error {
var err error
g.ctx, g.client, err = piperGithub.NewClientBuilder(opts.GitHubToken, getEnv("GITHUB_API_URL", "")).Build()
if err != nil {
return errors.Wrap(err, "failed to create github client")
}
log.Entry().Debug("Successfully initialized GitHubActions config provider")
return nil
}
func (g *githubActionsConfigProvider) OrchestratorVersion() string {
log.Entry().Debugf("OrchestratorVersion() for GitHub Actions is not applicable.")
return "n/a"
}
func (g *GitHubActionsConfigProvider) OrchestratorType() string {
func (g *githubActionsConfigProvider) OrchestratorType() string {
return "GitHubActions"
}
// GetBuildStatus returns current run status
func (g *GitHubActionsConfigProvider) GetBuildStatus() string {
// BuildStatus returns current run status
func (g *githubActionsConfigProvider) BuildStatus() string {
g.fetchRunData()
switch g.runData.Status {
case "success":
@@ -84,8 +90,13 @@ func (g *GitHubActionsConfigProvider) GetBuildStatus() string {
}
}
// GetLog returns the whole logfile for the current pipeline run
func (g *GitHubActionsConfigProvider) GetLog() ([]byte, error) {
// FullLogs returns the whole logfile for the current pipeline run
func (g *githubActionsConfigProvider) FullLogs() ([]byte, error) {
if g.client == nil {
log.Entry().Debug("ConfigProvider for GitHub Actions is not configured. Unable to fetch logs")
return []byte{}, nil
}
if err := g.fetchJobs(); err != nil {
return nil, err
}
@@ -129,31 +140,31 @@ func (g *GitHubActionsConfigProvider) GetLog() ([]byte, error) {
return bytes.Join(fullLogs.b, []byte("")), nil
}
// GetBuildID returns current run ID
func (g *GitHubActionsConfigProvider) GetBuildID() string {
// BuildID returns current run ID
func (g *githubActionsConfigProvider) BuildID() string {
return getEnv("GITHUB_RUN_ID", "n/a")
}
func (g *GitHubActionsConfigProvider) GetChangeSet() []ChangeSet {
log.Entry().Debug("GetChangeSet for GitHubActions not implemented")
func (g *githubActionsConfigProvider) ChangeSets() []ChangeSet {
log.Entry().Debug("ChangeSets for GitHubActions not implemented")
return []ChangeSet{}
}
// GetPipelineStartTime returns the pipeline start time in UTC
func (g *GitHubActionsConfigProvider) GetPipelineStartTime() time.Time {
// PipelineStartTime returns the pipeline start time in UTC
func (g *githubActionsConfigProvider) PipelineStartTime() time.Time {
g.fetchRunData()
return g.runData.StartedAt.UTC()
}
// GetStageName returns the human-readable name given to a stage.
func (g *GitHubActionsConfigProvider) GetStageName() string {
// StageName returns the human-readable name given to a stage.
func (g *githubActionsConfigProvider) StageName() string {
return getEnv("GITHUB_JOB", "unknown")
}
// GetBuildReason returns the reason of workflow trigger.
// BuildReason returns the reason of workflow trigger.
// BuildReasons are unified with AzureDevOps build reasons, see
// https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#build-variables-devops-services
func (g *GitHubActionsConfigProvider) GetBuildReason() string {
func (g *githubActionsConfigProvider) BuildReason() string {
switch getEnv("GITHUB_EVENT_NAME", "") {
case "workflow_dispatch":
return BuildReasonManual
@@ -170,50 +181,50 @@ func (g *GitHubActionsConfigProvider) GetBuildReason() string {
}
}
// GetBranch returns the source branch name, e.g. main
func (g *GitHubActionsConfigProvider) GetBranch() string {
// Branch returns the source branch name, e.g. main
func (g *githubActionsConfigProvider) Branch() string {
return getEnv("GITHUB_REF_NAME", "n/a")
}
// GetReference return the git reference. For example, refs/heads/your_branch_name
func (g *GitHubActionsConfigProvider) GetReference() string {
// GitReference return the git reference. For example, refs/heads/your_branch_name
func (g *githubActionsConfigProvider) GitReference() string {
return getEnv("GITHUB_REF", "n/a")
}
// GetBuildURL returns the builds URL. The URL should point to the pipeline (not to the stage)
// BuildURL returns the builds URL. The URL should point to the pipeline (not to the stage)
// that is currently being executed. For example, https://github.com/SAP/jenkins-library/actions/runs/5815297487
func (g *GitHubActionsConfigProvider) GetBuildURL() string {
return g.GetRepoURL() + "/actions/runs/" + g.GetBuildID()
func (g *githubActionsConfigProvider) BuildURL() string {
return g.RepoURL() + "/actions/runs/" + g.BuildID()
}
// GetJobURL returns the job URL. The URL should point to project’s pipelines.
// JobURL returns the job URL. The URL should point to project’s pipelines.
// For example, https://github.com/SAP/jenkins-library/actions/workflows/workflow-file-name.yaml
func (g *GitHubActionsConfigProvider) GetJobURL() string {
func (g *githubActionsConfigProvider) JobURL() string {
fileName := workflowFileName()
if fileName == "" {
return ""
}
return g.GetRepoURL() + "/actions/workflows/" + fileName
return g.RepoURL() + "/actions/workflows/" + fileName
}
// GetJobName returns the current workflow name. For example, "Piper workflow"
func (g *GitHubActionsConfigProvider) GetJobName() string {
// JobName returns the current workflow name. For example, "Piper workflow"
func (g *githubActionsConfigProvider) JobName() string {
return getEnv("GITHUB_WORKFLOW", "unknown")
}
// GetCommit returns the commit SHA that triggered the workflow. For example, ffac537e6cbbf934b08745a378932722df287a53
func (g *GitHubActionsConfigProvider) GetCommit() string {
// CommitSHA returns the commit SHA that triggered the workflow. For example, ffac537e6cbbf934b08745a378932722df287a53
func (g *githubActionsConfigProvider) CommitSHA() string {
return getEnv("GITHUB_SHA", "n/a")
}
// GetRepoURL returns full url to repository. For example, https://github.com/SAP/jenkins-library
func (g *GitHubActionsConfigProvider) GetRepoURL() string {
// RepoURL returns full url to repository. For example, https://github.com/SAP/jenkins-library
func (g *githubActionsConfigProvider) RepoURL() string {
return getEnv("GITHUB_SERVER_URL", "n/a") + "/" + getEnv("GITHUB_REPOSITORY", "n/a")
}
// GetPullRequestConfig returns pull request configuration
func (g *GitHubActionsConfigProvider) GetPullRequestConfig() PullRequestConfig {
// PullRequestConfig returns pull request configuration
func (g *githubActionsConfigProvider) PullRequestConfig() PullRequestConfig {
// See https://docs.github.com/en/enterprise-server@3.6/actions/learn-github-actions/variables#default-environment-variables
githubRef := getEnv("GITHUB_REF", "n/a")
prNumber := strings.TrimSuffix(strings.TrimPrefix(githubRef, "refs/pull/"), "/merge")
@@ -225,13 +236,13 @@ func (g *GitHubActionsConfigProvider) GetPullRequestConfig() PullRequestConfig {
}
// IsPullRequest indicates whether the current build is triggered by a PR
func (g *GitHubActionsConfigProvider) IsPullRequest() bool {
return truthy("GITHUB_HEAD_REF")
func (g *githubActionsConfigProvider) IsPullRequest() bool {
return envVarIsTrue("GITHUB_HEAD_REF")
}
func isGitHubActions() bool {
envVars := []string{"GITHUB_ACTION", "GITHUB_ACTIONS"}
return areIndicatingEnvVarsSet(envVars)
return envVarsAreSet(envVars)
}
// actionsURL returns URL to actions resource. For example,
@@ -240,7 +251,12 @@ func actionsURL() string {
return getEnv("GITHUB_API_URL", "") + "/repos/" + getEnv("GITHUB_REPOSITORY", "") + "/actions"
}
func (g *GitHubActionsConfigProvider) fetchRunData() {
func (g *githubActionsConfigProvider) fetchRunData() {
if g.client == nil {
log.Entry().Debug("ConfigProvider for GitHub Actions is not configured. Unable to fetch run data")
return
}
if g.runData.fetched {
return
}
@@ -268,7 +284,7 @@ func convertRunData(runData *github.WorkflowRun) run {
}
}
func (g *GitHubActionsConfigProvider) fetchJobs() error {
func (g *githubActionsConfigProvider) fetchJobs() error {
if g.jobsFetched {
return nil
}
@@ -304,8 +320,8 @@ func convertJobs(jobs []*github.WorkflowJob) []job {
return result
}
func (g *GitHubActionsConfigProvider) runIdInt64() (int64, error) {
strRunId := g.GetBuildID()
func (g *githubActionsConfigProvider) runIdInt64() (int64, error) {
strRunId := g.BuildID()
runId, err := strconv.ParseInt(strRunId, 10, 64)
if err != nil {
return 0, errors.Wrapf(err, "invalid GITHUB_RUN_ID value %s: %s", strRunId, err)

View File

@@ -30,10 +30,10 @@ func TestGitHubActionsConfigProvider_GetBuildStatus(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := &GitHubActionsConfigProvider{
g := &githubActionsConfigProvider{
runData: tt.runData,
}
assert.Equalf(t, tt.want, g.GetBuildStatus(), "GetBuildStatus()")
assert.Equalf(t, tt.want, g.BuildStatus(), "BuildStatus()")
})
}
}
@@ -54,10 +54,10 @@ func TestGitHubActionsConfigProvider_GetBuildReason(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := &GitHubActionsConfigProvider{}
g := &githubActionsConfigProvider{}
_ = os.Setenv("GITHUB_EVENT_NAME", tt.envGithubRef)
assert.Equalf(t, tt.want, g.GetBuildReason(), "GetBuildReason()")
assert.Equalf(t, tt.want, g.BuildReason(), "BuildReason()")
})
}
}
@@ -73,11 +73,11 @@ func TestGitHubActionsConfigProvider_GetRepoURL(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := &GitHubActionsConfigProvider{}
g := &githubActionsConfigProvider{}
_ = os.Setenv("GITHUB_SERVER_URL", tt.envServerURL)
_ = os.Setenv("GITHUB_REPOSITORY", tt.envRepo)
assert.Equalf(t, tt.want, g.GetRepoURL(), "GetRepoURL()")
assert.Equalf(t, tt.want, g.RepoURL(), "RepoURL()")
})
}
}
@@ -94,12 +94,12 @@ func TestGitHubActionsConfigProvider_GetPullRequestConfig(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := &GitHubActionsConfigProvider{}
g := &githubActionsConfigProvider{}
_ = os.Setenv("GITHUB_REF", tt.envRef)
_ = os.Setenv("GITHUB_HEAD_REF", "n/a")
_ = os.Setenv("GITHUB_BASE_REF", "n/a")
assert.Equalf(t, tt.want, g.GetPullRequestConfig(), "GetPullRequestConfig()")
assert.Equalf(t, tt.want, g.PullRequestConfig(), "PullRequestConfig()")
})
}
}
@@ -126,8 +126,8 @@ func TestGitHubActionsConfigProvider_fetchRunData(t *testing.T) {
_ = os.Setenv("GITHUB_RUN_ID", "11111")
// setup provider
g := &GitHubActionsConfigProvider{}
g.InitOrchestratorProvider(&OrchestratorSettings{})
g := newGithubActionsConfigProvider()
assert.NoError(t, g.Configure(&Options{}))
g.client = github.NewClient(http.DefaultClient)
// setup http mock
@@ -182,8 +182,8 @@ func TestGitHubActionsConfigProvider_fetchJobs(t *testing.T) {
_ = os.Setenv("GITHUB_RUN_ID", "11111")
// setup provider
g := &GitHubActionsConfigProvider{}
g.InitOrchestratorProvider(&OrchestratorSettings{})
g := newGithubActionsConfigProvider()
assert.NoError(t, g.Configure(&Options{}))
g.client = github.NewClient(http.DefaultClient)
// setup http mock
@@ -224,11 +224,11 @@ func TestGitHubActionsConfigProvider_GetLog(t *testing.T) {
_ = os.Setenv("GITHUB_REPOSITORY", "SAP/jenkins-library")
// setup provider
g := &GitHubActionsConfigProvider{
jobs: jobs,
jobsFetched: true,
}
g.InitOrchestratorProvider(&OrchestratorSettings{})
g := newGithubActionsConfigProvider()
g.jobs = jobs
g.jobsFetched = true
assert.NoError(t, g.Configure(&Options{}))
g.client = github.NewClient(http.DefaultClient)
// setup http mock
@@ -262,7 +262,7 @@ func TestGitHubActionsConfigProvider_GetLog(t *testing.T) {
)
}
// run
logs, err := g.GetLog()
logs, err := g.FullLogs()
assert.NoError(t, err)
assert.Equal(t, wantLogs, string(logs))
}
@@ -283,7 +283,7 @@ func TestGitHubActionsConfigProvider_Others(t *testing.T) {
_ = os.Setenv("GITHUB_REPOSITORY", "SAP/jenkins-library")
_ = os.Setenv("GITHUB_WORKFLOW_REF", "SAP/jenkins-library/.github/workflows/piper.yml@refs/heads/main")
p := GitHubActionsConfigProvider{}
p := githubActionsConfigProvider{}
startedAt, _ := time.Parse(time.RFC3339, "2023-08-11T07:28:24Z")
p.runData = run{
fetched: true,
@@ -293,16 +293,16 @@ func TestGitHubActionsConfigProvider_Others(t *testing.T) {
assert.Equal(t, "n/a", p.OrchestratorVersion())
assert.Equal(t, "GitHubActions", p.OrchestratorType())
assert.Equal(t, "11111", p.GetBuildID())
assert.Equal(t, []ChangeSet{}, p.GetChangeSet())
assert.Equal(t, startedAt, p.GetPipelineStartTime())
assert.Equal(t, "Build", p.GetStageName())
assert.Equal(t, "main", p.GetBranch())
assert.Equal(t, "refs/pull/42/merge", p.GetReference())
assert.Equal(t, "https://github.com/SAP/jenkins-library/actions/runs/11111", p.GetBuildURL())
assert.Equal(t, "https://github.com/SAP/jenkins-library/actions/workflows/piper.yml", p.GetJobURL())
assert.Equal(t, "Piper workflow", p.GetJobName())
assert.Equal(t, "ffac537e6cbbf934b08745a378932722df287a53", p.GetCommit())
assert.Equal(t, "11111", p.BuildID())
assert.Equal(t, []ChangeSet{}, p.ChangeSets())
assert.Equal(t, startedAt, p.PipelineStartTime())
assert.Equal(t, "Build", p.StageName())
assert.Equal(t, "main", p.Branch())
assert.Equal(t, "refs/pull/42/merge", p.GitReference())
assert.Equal(t, "https://github.com/SAP/jenkins-library/actions/runs/11111", p.BuildURL())
assert.Equal(t, "https://github.com/SAP/jenkins-library/actions/workflows/piper.yml", p.JobURL())
assert.Equal(t, "Piper workflow", p.JobName())
assert.Equal(t, "ffac537e6cbbf934b08745a378932722df287a53", p.CommitSHA())
assert.Equal(t, "https://api.github.com/repos/SAP/jenkins-library/actions", actionsURL())
assert.True(t, p.IsPullRequest())
assert.True(t, isGitHubActions())

View File

@@ -0,0 +1,40 @@
package orchestrator
import (
"github.com/SAP/jenkins-library/pkg/log"
"os"
)
// envVarsAreSet verifies if any envvar from the list has nona non-empty, non-false value
func envVarsAreSet(envVars []string) bool {
for _, v := range envVars {
if envVarIsTrue(v) {
return true
}
}
return false
}
// envVarIsTrue verifies if the variable is set and has a non-empty, non-false value.
func envVarIsTrue(key string) bool {
val, exists := os.LookupEnv(key)
if !exists {
return false
}
if len(val) == 0 || val == "no" || val == "false" || val == "off" || val == "0" {
return false
}
return true
}
// Wrapper function to read env variable and set default value
func getEnv(key, fallback string) string {
if value, found := os.LookupEnv(key); found {
log.Entry().Debugf("For: %s, found: %s", key, value)
return value
}
log.Entry().Debugf("Could not read env variable %v using fallback value %v", key, fallback)
return fallback
}

View File

@@ -4,57 +4,35 @@
package orchestrator
import (
"github.com/stretchr/testify/assert"
"os"
"testing"
"github.com/stretchr/testify/assert"
)
func TestOrchestrator(t *testing.T) {
t.Run("Not running on CI", func(t *testing.T) {
defer resetEnv(os.Environ())
os.Clearenv()
provider, err := NewOrchestratorSpecificConfigProvider()
assert.EqualError(t, err, "unable to detect a supported orchestrator (Azure DevOps, GitHub Actions, Jenkins)")
assert.Equal(t, "Unknown", provider.OrchestratorType())
})
t.Run("Test orchestrator.toString()", func(t *testing.T) {
defer resetEnv(os.Environ())
os.Clearenv()
os.Setenv("AZURE_HTTP_USER_AGENT", "FOO BAR BAZ")
o := DetectOrchestrator()
assert.Equal(t, "AzureDevOps", o.String())
})
t.Run("Test areIndicatingEnvVarsSet", func(t *testing.T) {
func Test_envVarsAreSet(t *testing.T) {
t.Run("Test envVarsAreSet", func(t *testing.T) {
defer resetEnv(os.Environ())
os.Clearenv()
envVars := []string{"GITHUB_ACTION", "GITHUB_ACTIONS"}
os.Setenv("GITHUB_ACTION", "true")
tmp := areIndicatingEnvVarsSet(envVars)
tmp := envVarsAreSet(envVars)
assert.True(t, tmp)
os.Unsetenv("GITHUB_ACTION")
os.Setenv("GITHUB_ACTIONS", "true")
tmp = areIndicatingEnvVarsSet(envVars)
tmp = envVarsAreSet(envVars)
assert.True(t, tmp)
os.Setenv("GITHUB_ACTION", "1")
os.Setenv("GITHUB_ACTIONS", "false")
tmp = areIndicatingEnvVarsSet(envVars)
tmp = envVarsAreSet(envVars)
assert.True(t, tmp)
os.Setenv("GITHUB_ACTION", "false")
os.Setenv("GITHUB_ACTIONS", "0")
tmp = areIndicatingEnvVarsSet(envVars)
tmp = envVarsAreSet(envVars)
assert.False(t, tmp)
})
}

View File

@@ -12,36 +12,42 @@ import (
"github.com/pkg/errors"
)
type JenkinsConfigProvider struct {
type jenkinsConfigProvider struct {
client piperHttp.Client
apiInformation map[string]interface{}
}
// InitOrchestratorProvider initializes the Jenkins orchestrator with credentials
func (j *JenkinsConfigProvider) InitOrchestratorProvider(settings *OrchestratorSettings) {
func newJenkinsConfigProvider() *jenkinsConfigProvider {
return &jenkinsConfigProvider{}
}
// Configure initializes the Jenkins orchestrator with credentials
func (j *jenkinsConfigProvider) Configure(opts *Options) error {
j.client.SetOptions(piperHttp.ClientOptions{
Username: settings.JenkinsUser,
Password: settings.JenkinsToken,
Username: opts.JenkinsUser,
Password: opts.JenkinsToken,
MaxRetries: 3,
TransportTimeout: time.Second * 10,
})
log.Entry().Debug("Successfully initialized Jenkins config provider")
return nil
}
// OrchestratorVersion returns the orchestrator version currently running on
func (j *JenkinsConfigProvider) OrchestratorVersion() string {
func (j *jenkinsConfigProvider) OrchestratorVersion() string {
return getEnv("JENKINS_VERSION", "n/a")
}
// OrchestratorType returns the orchestrator type Jenkins
func (j *JenkinsConfigProvider) OrchestratorType() string {
func (j *jenkinsConfigProvider) OrchestratorType() string {
return "Jenkins"
}
func (j *JenkinsConfigProvider) fetchAPIInformation() {
func (j *jenkinsConfigProvider) fetchAPIInformation() {
if len(j.apiInformation) == 0 {
log.Entry().Debugf("apiInformation is empty, getting infos from API")
URL := j.GetBuildURL() + "api/json"
URL := j.BuildURL() + "api/json"
log.Entry().Debugf("API URL: %s", URL)
response, err := j.client.GetRequest(URL, nil, nil)
if err != nil {
@@ -67,8 +73,8 @@ func (j *JenkinsConfigProvider) fetchAPIInformation() {
}
}
// GetBuildStatus returns build status of the current job
func (j *JenkinsConfigProvider) GetBuildStatus() string {
// BuildStatus returns build status of the current job
func (j *jenkinsConfigProvider) BuildStatus() string {
j.fetchAPIInformation()
if val, ok := j.apiInformation["result"]; ok {
// cases in ADO: succeeded, failed, canceled, none, partiallySucceeded
@@ -85,8 +91,8 @@ func (j *JenkinsConfigProvider) GetBuildStatus() string {
return BuildStatusFailure
}
// GetChangeSet returns the commitIds and timestamp of the changeSet of the current run
func (j *JenkinsConfigProvider) GetChangeSet() []ChangeSet {
// ChangeSet returns the commitIds and timestamp of the changeSet of the current run
func (j *jenkinsConfigProvider) ChangeSets() []ChangeSet {
j.fetchAPIInformation()
marshal, err := json.Marshal(j.apiInformation)
@@ -116,9 +122,9 @@ func (j *JenkinsConfigProvider) GetChangeSet() []ChangeSet {
return changeSetList
}
// GetLog returns the logfile from the current job as byte object
func (j *JenkinsConfigProvider) GetLog() ([]byte, error) {
URL := j.GetBuildURL() + "consoleText"
// FullLogs returns the logfile from the current job as byte object
func (j *jenkinsConfigProvider) FullLogs() ([]byte, error) {
URL := j.BuildURL() + "consoleText"
response, err := j.client.GetRequest(URL, nil, nil)
if err != nil {
@@ -135,9 +141,9 @@ func (j *JenkinsConfigProvider) GetLog() ([]byte, error) {
return logFile, nil
}
// GetPipelineStartTime returns the pipeline start time in UTC
func (j *JenkinsConfigProvider) GetPipelineStartTime() time.Time {
URL := j.GetBuildURL() + "api/json"
// PipelineStartTime returns the pipeline start time in UTC
func (j *jenkinsConfigProvider) PipelineStartTime() time.Time {
URL := j.BuildURL() + "api/json"
response, err := j.client.GetRequest(URL, nil, nil)
if err != nil {
log.Entry().WithError(err).Errorf("could not getRequest to URL %s", URL)
@@ -163,33 +169,33 @@ func (j *JenkinsConfigProvider) GetPipelineStartTime() time.Time {
return timeStamp.UTC()
}
// GetJobName returns the job name of the current job e.g. foo/bar/BRANCH
func (j *JenkinsConfigProvider) GetJobName() string {
// JobName returns the job name of the current job e.g. foo/bar/BRANCH
func (j *jenkinsConfigProvider) JobName() string {
return getEnv("JOB_NAME", "n/a")
}
// GetJobURL returns the current job URL e.g. https://jaas.url/job/foo/job/bar/job/main
func (j *JenkinsConfigProvider) GetJobURL() string {
// JobURL returns the current job URL e.g. https://jaas.url/job/foo/job/bar/job/main
func (j *jenkinsConfigProvider) JobURL() string {
return getEnv("JOB_URL", "n/a")
}
// getJenkinsHome returns the jenkins home e.g. /var/lib/jenkins
func (j *JenkinsConfigProvider) getJenkinsHome() string {
func (j *jenkinsConfigProvider) getJenkinsHome() string {
return getEnv("JENKINS_HOME", "n/a")
}
// GetBuildID returns the build ID of the current job, e.g. 1234
func (j *JenkinsConfigProvider) GetBuildID() string {
// BuildID returns the build ID of the current job, e.g. 1234
func (j *jenkinsConfigProvider) BuildID() string {
return getEnv("BUILD_ID", "n/a")
}
// GetStageName returns the stage name the job is currently in, e.g. Promote
func (j *JenkinsConfigProvider) GetStageName() string {
// StageName returns the stage name the job is currently in, e.g. Promote
func (j *jenkinsConfigProvider) StageName() string {
return getEnv("STAGE_NAME", "n/a")
}
// GetBuildReason returns the build reason of the current build
func (j *JenkinsConfigProvider) GetBuildReason() string {
// BuildReason returns the build reason of the current build
func (j *jenkinsConfigProvider) BuildReason() string {
// BuildReasons are unified with AzureDevOps build reasons,see
// https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#build-variables-devops-services
// ResourceTrigger, PullRequest, Manual, IndividualCI, Schedule
@@ -231,13 +237,13 @@ func (j *JenkinsConfigProvider) GetBuildReason() string {
return BuildReasonUnknown
}
// GetBranch returns the branch name, only works with the git plugin enabled
func (j *JenkinsConfigProvider) GetBranch() string {
// Branch returns the branch name, only works with the git plugin enabled
func (j *jenkinsConfigProvider) Branch() string {
return getEnv("BRANCH_NAME", "n/a")
}
// GetReference returns the git reference, only works with the git plugin enabled
func (j *JenkinsConfigProvider) GetReference() string {
// GitReference returns the git reference, only works with the git plugin enabled
func (j *jenkinsConfigProvider) GitReference() string {
ref := getEnv("BRANCH_NAME", "n/a")
if ref == "n/a" {
return ref
@@ -248,23 +254,23 @@ func (j *JenkinsConfigProvider) GetReference() string {
}
}
// GetBuildURL returns the build url, e.g. https://jaas.url/job/foo/job/bar/job/main/1234/
func (j *JenkinsConfigProvider) GetBuildURL() string {
// BuildURL returns the build url, e.g. https://jaas.url/job/foo/job/bar/job/main/1234/
func (j *jenkinsConfigProvider) BuildURL() string {
return getEnv("BUILD_URL", "n/a")
}
// GetCommit returns the commit SHA from the current build, only works with the git plugin enabled
func (j *JenkinsConfigProvider) GetCommit() string {
// CommitSHA returns the commit SHA from the current build, only works with the git plugin enabled
func (j *jenkinsConfigProvider) CommitSHA() string {
return getEnv("GIT_COMMIT", "n/a")
}
// GetRepoURL returns the repo URL of the current build, only works with the git plugin enabled
func (j *JenkinsConfigProvider) GetRepoURL() string {
// RepoURL returns the repo URL of the current build, only works with the git plugin enabled
func (j *jenkinsConfigProvider) RepoURL() string {
return getEnv("GIT_URL", "n/a")
}
// GetPullRequestConfig returns the pull request config
func (j *JenkinsConfigProvider) GetPullRequestConfig() PullRequestConfig {
// PullRequestConfig returns the pull request config
func (j *jenkinsConfigProvider) PullRequestConfig() PullRequestConfig {
return PullRequestConfig{
Branch: getEnv("CHANGE_BRANCH", "n/a"),
Base: getEnv("CHANGE_TARGET", "n/a"),
@@ -273,11 +279,11 @@ func (j *JenkinsConfigProvider) GetPullRequestConfig() PullRequestConfig {
}
// IsPullRequest returns boolean indicating if current job is a PR
func (j *JenkinsConfigProvider) IsPullRequest() bool {
return truthy("CHANGE_ID")
func (j *jenkinsConfigProvider) IsPullRequest() bool {
return envVarIsTrue("CHANGE_ID")
}
func isJenkins() bool {
envVars := []string{"JENKINS_HOME", "JENKINS_URL"}
return areIndicatingEnvVarsSet(envVars)
return envVarsAreSet(envVars)
}

View File

@@ -29,14 +29,14 @@ func TestJenkins(t *testing.T) {
os.Setenv("GIT_COMMIT", "abcdef42713")
os.Setenv("GIT_URL", "github.com/foo/bar")
p, _ := NewOrchestratorSpecificConfigProvider()
p := &jenkinsConfigProvider{}
assert.False(t, p.IsPullRequest())
assert.Equal(t, "https://jaas.url/job/foo/job/bar/job/main/1234/", p.GetBuildURL())
assert.Equal(t, "main", p.GetBranch())
assert.Equal(t, "refs/heads/main", p.GetReference())
assert.Equal(t, "abcdef42713", p.GetCommit())
assert.Equal(t, "github.com/foo/bar", p.GetRepoURL())
assert.Equal(t, "https://jaas.url/job/foo/job/bar/job/main/1234/", p.BuildURL())
assert.Equal(t, "main", p.Branch())
assert.Equal(t, "refs/heads/main", p.GitReference())
assert.Equal(t, "abcdef42713", p.CommitSHA())
assert.Equal(t, "github.com/foo/bar", p.RepoURL())
assert.Equal(t, "Jenkins", p.OrchestratorType())
})
@@ -48,11 +48,11 @@ func TestJenkins(t *testing.T) {
os.Setenv("CHANGE_TARGET", "main")
os.Setenv("CHANGE_ID", "42")
p := JenkinsConfigProvider{}
c := p.GetPullRequestConfig()
p := jenkinsConfigProvider{}
c := p.PullRequestConfig()
assert.True(t, p.IsPullRequest())
assert.Equal(t, "refs/pull/42/head", p.GetReference())
assert.Equal(t, "refs/pull/42/head", p.GitReference())
assert.Equal(t, "feat/test-jenkins", c.Branch)
assert.Equal(t, "main", c.Base)
assert.Equal(t, "42", c.Key)
@@ -70,16 +70,16 @@ func TestJenkins(t *testing.T) {
os.Setenv("BUILD_URL", "https://jaas.url/job/foo/job/bar/job/main/1234/")
os.Setenv("STAGE_NAME", "Promote")
p := JenkinsConfigProvider{}
p := jenkinsConfigProvider{}
assert.Equal(t, "/var/lib/jenkins", p.getJenkinsHome())
assert.Equal(t, "1234", p.GetBuildID())
assert.Equal(t, "https://jaas.url/job/foo/job/bar/job/main", p.GetJobURL())
assert.Equal(t, "1234", p.BuildID())
assert.Equal(t, "https://jaas.url/job/foo/job/bar/job/main", p.JobURL())
assert.Equal(t, "42", p.OrchestratorVersion())
assert.Equal(t, "Jenkins", p.OrchestratorType())
assert.Equal(t, "foo/bar/BRANCH", p.GetJobName())
assert.Equal(t, "Promote", p.GetStageName())
assert.Equal(t, "https://jaas.url/job/foo/job/bar/job/main/1234/", p.GetBuildURL())
assert.Equal(t, "foo/bar/BRANCH", p.JobName())
assert.Equal(t, "Promote", p.StageName())
assert.Equal(t, "https://jaas.url/job/foo/job/bar/job/main/1234/", p.BuildURL())
})
}
@@ -130,7 +130,7 @@ func TestJenkinsConfigProvider_GetPipelineStartTime(t *testing.T) {
},
}
j := &JenkinsConfigProvider{
j := &jenkinsConfigProvider{
client: piperhttp.Client{},
}
j.client.SetOptions(piperhttp.ClientOptions{
@@ -171,7 +171,7 @@ func TestJenkinsConfigProvider_GetPipelineStartTime(t *testing.T) {
},
)
assert.Equalf(t, tt.want, j.GetPipelineStartTime(), "GetPipelineStartTime()")
assert.Equalf(t, tt.want, j.PipelineStartTime(), "PipelineStartTime()")
})
}
}
@@ -228,10 +228,10 @@ func TestJenkinsConfigProvider_GetBuildStatus(t *testing.T) {
if err != nil {
t.Fatal("could not parse json:", err)
}
j := &JenkinsConfigProvider{
j := &jenkinsConfigProvider{
apiInformation: apiInformation,
}
assert.Equalf(t, tt.want, j.GetBuildStatus(), "GetBuildStatus()")
assert.Equalf(t, tt.want, j.BuildStatus(), "BuildStatus()")
})
}
}
@@ -367,9 +367,9 @@ func TestJenkinsConfigProvider_GetBuildReason(t *testing.T) {
if err != nil {
t.Fatal("could not parse json:", err)
}
j := &JenkinsConfigProvider{apiInformation: apiInformation}
j := &jenkinsConfigProvider{apiInformation: apiInformation}
assert.Equalf(t, tt.want, j.GetBuildReason(), "GetBuildReason()")
assert.Equalf(t, tt.want, j.BuildReason(), "BuildReason()")
})
}
}
@@ -415,7 +415,7 @@ func TestJenkinsConfigProvider_getAPIInformation(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
j := &JenkinsConfigProvider{
j := &jenkinsConfigProvider{
apiInformation: tt.apiInformation,
}
j.client.SetOptions(piperhttp.ClientOptions{
@@ -487,7 +487,7 @@ func TestJenkinsConfigProvider_GetLog(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
j := &JenkinsConfigProvider{}
j := &jenkinsConfigProvider{}
j.client.SetOptions(piperhttp.ClientOptions{
MaxRequestDuration: 5 * time.Second,
Token: "TOKEN",
@@ -519,33 +519,11 @@ func TestJenkinsConfigProvider_GetLog(t *testing.T) {
},
)
got, err := j.GetLog()
if !tt.wantErr(t, err, fmt.Sprintf("GetLog()")) {
got, err := j.FullLogs()
if !tt.wantErr(t, err, fmt.Sprintf("FullLogs()")) {
return
}
assert.Equalf(t, tt.want, got, "GetLog()")
})
}
}
func TestJenkinsConfigProvider_InitOrchestratorProvider(t *testing.T) {
tests := []struct {
name string
settings *OrchestratorSettings
apiInformation map[string]interface{}
}{
{
name: "Init, test empty apiInformation",
settings: &OrchestratorSettings{},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
j := &JenkinsConfigProvider{}
j.InitOrchestratorProvider(tt.settings)
var expected map[string]interface{}
assert.Equal(t, j.apiInformation, expected)
assert.Equalf(t, tt.want, got, "FullLogs()")
})
}
}
@@ -664,8 +642,8 @@ func TestJenkinsConfigProvider_GetChangeSet(t *testing.T) {
if err != nil {
t.Fatal("could not parse json:", err)
}
j := &JenkinsConfigProvider{apiInformation: apiInformation}
assert.Equalf(t, tt.want, j.GetChangeSet(), "GetChangeSet()")
j := &jenkinsConfigProvider{apiInformation: apiInformation}
assert.Equalf(t, tt.want, j.ChangeSets(), "ChangeSets()")
})
}
}

View File

@@ -1,15 +1,12 @@
package orchestrator
import (
"errors"
"os"
"time"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/pkg/errors"
"sync"
"time"
)
type Orchestrator int
const (
Unknown Orchestrator = iota
AzureDevOps
@@ -31,67 +28,86 @@ const (
BuildReasonUnknown = "Unknown"
)
type OrchestratorSpecificConfigProviding interface {
InitOrchestratorProvider(settings *OrchestratorSettings)
var (
provider ConfigProvider
providerOnce sync.Once
)
type ConfigProvider interface {
Configure(opts *Options) error
OrchestratorType() string
OrchestratorVersion() string
GetStageName() string
GetBranch() string
GetReference() string
GetBuildURL() string
GetBuildID() string
GetJobURL() string
GetJobName() string
GetCommit() string
GetPullRequestConfig() PullRequestConfig
GetRepoURL() string
StageName() string
Branch() string
GitReference() string
RepoURL() string
BuildURL() string
BuildID() string
BuildStatus() string
BuildReason() string
JobURL() string
JobName() string
CommitSHA() string
PullRequestConfig() PullRequestConfig
IsPullRequest() bool
GetLog() ([]byte, error)
GetPipelineStartTime() time.Time
GetBuildStatus() string
GetBuildReason() string
GetChangeSet() []ChangeSet
FullLogs() ([]byte, error)
PipelineStartTime() time.Time
ChangeSets() []ChangeSet
}
type PullRequestConfig struct {
Branch string
Base string
Key string
}
type (
Orchestrator int
type ChangeSet struct {
CommitId string
Timestamp string
PrNumber int
}
// OrchestratorSettings struct to set orchestrator specific settings e.g. Jenkins credentials
type OrchestratorSettings struct {
JenkinsUser string
JenkinsToken string
AzureToken string
GitHubToken string
}
func NewOrchestratorSpecificConfigProvider() (OrchestratorSpecificConfigProviding, error) {
switch DetectOrchestrator() {
case AzureDevOps:
return &AzureDevOpsConfigProvider{}, nil
case GitHubActions:
ghProvider := &GitHubActionsConfigProvider{}
// Temporary workaround: The orchestrator provider is not always initialized after being created,
// which causes a panic in some places for GitHub Actions provider, as it needs to initialize
// github sdk client.
ghProvider.InitOrchestratorProvider(&OrchestratorSettings{})
return ghProvider, nil
case Jenkins:
return &JenkinsConfigProvider{}, nil
default:
return &UnknownOrchestratorConfigProvider{}, errors.New("unable to detect a supported orchestrator (Azure DevOps, GitHub Actions, Jenkins)")
// Options used to set orchestrator specific settings.
Options struct {
JenkinsUser string
JenkinsToken string
AzureToken string
GitHubToken string
}
PullRequestConfig struct {
Branch string
Base string
Key string
}
ChangeSet struct {
CommitId string
Timestamp string
PrNumber int
}
)
func GetOrchestratorConfigProvider(opts *Options) (ConfigProvider, error) {
var err error
providerOnce.Do(func() {
switch DetectOrchestrator() {
case AzureDevOps:
provider = newAzureDevopsConfigProvider()
case GitHubActions:
provider = newGithubActionsConfigProvider()
case Jenkins:
provider = newJenkinsConfigProvider()
default:
provider = newUnknownOrchestratorConfigProvider()
err = errors.New("unable to detect a supported orchestrator (Azure DevOps, GitHub Actions, Jenkins)")
}
if opts == nil {
log.Entry().Debug("ConfigProvider initialized without options. Some data may be unavailable")
return
}
if cfgErr := provider.Configure(opts); cfgErr != nil {
err = errors.Wrap(cfgErr, "provider configuration failed")
}
})
return provider, err
}
// DetectOrchestrator returns the name of the current orchestrator e.g. Jenkins, Azure, Unknown
// DetectOrchestrator function determines in which orchestrator Piper is running by examining environment variables.
func DetectOrchestrator() Orchestrator {
if isAzure() {
return AzureDevOps
@@ -108,34 +124,10 @@ func (o Orchestrator) String() string {
return [...]string{"Unknown", "AzureDevOps", "GitHubActions", "Jenkins"}[o]
}
func areIndicatingEnvVarsSet(envVars []string) bool {
for _, v := range envVars {
if truthy(v) {
return true
}
}
return false
}
// Checks if var is set and neither empty nor false
func truthy(key string) bool {
val, exists := os.LookupEnv(key)
if !exists {
return false
}
if len(val) == 0 || val == "no" || val == "false" || val == "off" || val == "0" {
return false
}
return true
}
// Wrapper function to read env variable and set default value
func getEnv(key, fallback string) string {
if value, ok := os.LookupEnv(key); ok {
log.Entry().Debugf("For: %s, found: %s", key, value)
return value
}
log.Entry().Debugf("Could not read env variable %v using fallback value %v", key, fallback)
return fallback
// ResetConfigProvider is intended to be used only for unit tests because some of these tests
// run with different environment variables (for example, mock runs in various orchestrators).
// Usage in production code is not recommended.
func ResetConfigProvider() {
provider = nil
providerOnce = sync.Once{}
}

View File

@@ -8,109 +8,99 @@ import (
type UnknownOrchestratorConfigProvider struct{}
// InitOrchestratorProvider returns n/a for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) InitOrchestratorProvider(settings *OrchestratorSettings) {
log.Entry().Warning("Unknown orchestrator - returning default values.")
const unknownOrchestratorWarning = "Unknown orchestrator - returning default values."
func newUnknownOrchestratorConfigProvider() *UnknownOrchestratorConfigProvider {
return &UnknownOrchestratorConfigProvider{}
}
func (u *UnknownOrchestratorConfigProvider) Configure(_ *Options) error {
log.Entry().Warning(unknownOrchestratorWarning)
return nil
}
// OrchestratorVersion returns n/a for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) OrchestratorVersion() string {
log.Entry().Warning("Unknown orchestrator - returning default values.")
log.Entry().Warning(unknownOrchestratorWarning)
return "n/a"
}
// GetBuildStatus returns n/a for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) GetBuildStatus() string {
log.Entry().Warning("Unknown orchestrator - returning default values.")
func (u *UnknownOrchestratorConfigProvider) BuildStatus() string {
log.Entry().Warning(unknownOrchestratorWarning)
return "FAILURE"
}
func (u *UnknownOrchestratorConfigProvider) GetChangeSet() []ChangeSet {
log.Entry().Infof("Unknown orchestrator - returning default values.")
func (u *UnknownOrchestratorConfigProvider) ChangeSets() []ChangeSet {
log.Entry().Infof(unknownOrchestratorWarning)
return []ChangeSet{}
}
// GetBuildReason returns n/a for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) GetBuildReason() string {
log.Entry().Infof("Unknown orchestrator - returning default values.")
func (u *UnknownOrchestratorConfigProvider) BuildReason() string {
log.Entry().Infof(unknownOrchestratorWarning)
return "n/a"
}
// GetBuildID returns n/a for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) GetBuildID() string {
log.Entry().Warning("Unknown orchestrator - returning default values.")
func (u *UnknownOrchestratorConfigProvider) BuildID() string {
log.Entry().Warning(unknownOrchestratorWarning)
return "n/a"
}
// GetJobName returns n/a for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) GetJobName() string {
log.Entry().Warning("Unknown orchestrator - returning default values.")
func (u *UnknownOrchestratorConfigProvider) JobName() string {
log.Entry().Warning(unknownOrchestratorWarning)
return "n/a"
}
// OrchestratorType returns n/a for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) OrchestratorType() string {
log.Entry().Warning("Unknown orchestrator - returning default values.")
log.Entry().Warning(unknownOrchestratorWarning)
return "Unknown"
}
// GetLog returns n/a for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) GetLog() ([]byte, error) {
log.Entry().Warning("Unknown orchestrator - returning default values.")
func (u *UnknownOrchestratorConfigProvider) FullLogs() ([]byte, error) {
log.Entry().Warning(unknownOrchestratorWarning)
return []byte{}, nil
}
// GetPipelineStartTime returns n/a for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) GetPipelineStartTime() time.Time {
log.Entry().Warning("Unknown orchestrator - returning default values.")
func (u *UnknownOrchestratorConfigProvider) PipelineStartTime() time.Time {
log.Entry().Warning(unknownOrchestratorWarning)
return time.Time{}.UTC()
}
// GetStageName returns n/a for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) GetStageName() string {
log.Entry().Warning("Unknown orchestrator - returning default values.")
func (u *UnknownOrchestratorConfigProvider) StageName() string {
log.Entry().Warning(unknownOrchestratorWarning)
return "n/a"
}
// GetBranch returns n/a for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) GetBranch() string {
log.Entry().Warning("Unknown orchestrator - returning default values.")
func (u *UnknownOrchestratorConfigProvider) Branch() string {
log.Entry().Warning(unknownOrchestratorWarning)
return "n/a"
}
// GetReference returns n/a for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) GetReference() string {
log.Entry().Warning("Unknown orchestrator - returning default values.")
func (u *UnknownOrchestratorConfigProvider) GitReference() string {
log.Entry().Warning(unknownOrchestratorWarning)
return "n/a"
}
// GetBuildURL returns n/a for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) GetBuildURL() string {
log.Entry().Warning("Unknown orchestrator - returning default values.")
func (u *UnknownOrchestratorConfigProvider) BuildURL() string {
log.Entry().Warning(unknownOrchestratorWarning)
return "n/a"
}
// GetJobURL returns n/a for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) GetJobURL() string {
log.Entry().Warning("Unknown orchestrator - returning default values.")
func (u *UnknownOrchestratorConfigProvider) JobURL() string {
log.Entry().Warning(unknownOrchestratorWarning)
return "n/a"
}
// GetCommit returns n/a for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) GetCommit() string {
log.Entry().Warning("Unknown orchestrator - returning default values.")
func (u *UnknownOrchestratorConfigProvider) CommitSHA() string {
log.Entry().Warning(unknownOrchestratorWarning)
return "n/a"
}
// GetRepoURL returns n/a for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) GetRepoURL() string {
log.Entry().Warning("Unknown orchestrator - returning default values.")
func (u *UnknownOrchestratorConfigProvider) RepoURL() string {
log.Entry().Warning(unknownOrchestratorWarning)
return "n/a"
}
// GetPullRequestConfig returns n/a for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) GetPullRequestConfig() PullRequestConfig {
log.Entry().Warning("Unknown orchestrator - returning default values.")
func (u *UnknownOrchestratorConfigProvider) PullRequestConfig() PullRequestConfig {
log.Entry().Warning(unknownOrchestratorWarning)
return PullRequestConfig{
Branch: "n/a",
Base: "n/a",
@@ -118,8 +108,7 @@ func (u *UnknownOrchestratorConfigProvider) GetPullRequestConfig() PullRequestCo
}
}
// IsPullRequest returns false for the unknownOrchestrator
func (u *UnknownOrchestratorConfigProvider) IsPullRequest() bool {
log.Entry().Warning("Unknown orchestrator - returning default values.")
log.Entry().Warning(unknownOrchestratorWarning)
return false
}

View File

@@ -1,61 +0,0 @@
//go:build unit
// +build unit
package orchestrator
import (
"os"
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestUnknownOrchestrator(t *testing.T) {
t.Run("BranchBuild", func(t *testing.T) {
defer resetEnv(os.Environ())
os.Clearenv()
p, _ := NewOrchestratorSpecificConfigProvider()
assert.False(t, p.IsPullRequest())
assert.Equal(t, "n/a", p.GetBuildURL())
assert.Equal(t, "n/a", p.GetBranch())
assert.Equal(t, "n/a", p.GetCommit())
assert.Equal(t, "n/a", p.GetRepoURL())
assert.Equal(t, "Unknown", p.OrchestratorType())
})
t.Run("PR", func(t *testing.T) {
defer resetEnv(os.Environ())
os.Clearenv()
p := UnknownOrchestratorConfigProvider{}
c := p.GetPullRequestConfig()
assert.False(t, p.IsPullRequest())
assert.Equal(t, "n/a", c.Branch)
assert.Equal(t, "n/a", c.Base)
assert.Equal(t, "n/a", c.Key)
})
t.Run("env variables", func(t *testing.T) {
defer resetEnv(os.Environ())
os.Clearenv()
p := UnknownOrchestratorConfigProvider{}
assert.Equal(t, "n/a", p.OrchestratorVersion())
assert.Equal(t, "n/a", p.GetBuildID())
assert.Equal(t, "n/a", p.GetJobName())
assert.Equal(t, "Unknown", p.OrchestratorType())
assert.Equal(t, time.Time{}.UTC(), p.GetPipelineStartTime())
assert.Equal(t, "FAILURE", p.GetBuildStatus())
assert.Equal(t, "n/a", p.GetRepoURL())
assert.Equal(t, "n/a", p.GetBuildURL())
assert.Equal(t, "n/a", p.GetStageName())
log, err := p.GetLog()
assert.Equal(t, []byte{}, log)
assert.Equal(t, nil, err)
})
}

View File

@@ -67,14 +67,14 @@ func (p *PolicyViolationReport) ToMarkdown() ([]byte, error) {
}
// only fill with orchestrator information if orchestrator can be identified properly
if provider, err := orchestrator.NewOrchestratorSpecificConfigProvider(); err == nil {
if provider, err := orchestrator.GetOrchestratorConfigProvider(nil); err == nil {
// only add information if not yet provided
if len(p.CommitID) == 0 {
p.CommitID = provider.GetCommit()
p.CommitID = provider.CommitSHA()
}
if len(p.PipelineLink) == 0 {
p.PipelineLink = provider.GetJobURL()
p.PipelineName = provider.GetJobName()
p.PipelineLink = provider.JobURL()
p.PipelineName = provider.JobName()
}
}

View File

@@ -91,18 +91,18 @@ func (v *VulnerabilityReport) ToMarkdown() ([]byte, error) {
}
// only fill with orchestrator information if orchestrator can be identified properly
if provider, err := orchestrator.NewOrchestratorSpecificConfigProvider(); err == nil {
if provider, err := orchestrator.GetOrchestratorConfigProvider(nil); err == nil {
// only add information if not yet provided
if len(v.CommitID) == 0 {
v.CommitID = provider.GetCommit()
v.CommitID = provider.CommitSHA()
}
if len(v.PipelineLink) == 0 {
v.PipelineLink = provider.GetJobURL()
v.PipelineName = provider.GetJobName()
v.PipelineLink = provider.JobURL()
v.PipelineName = provider.JobName()
}
if len(v.Branch) == 0 {
v.Branch = provider.GetBranch()
v.Branch = provider.Branch()
}
}

View File

@@ -14,8 +14,8 @@ type BaseData struct {
URL string `json:"url"`
StepName string `json:"e_3"` // set by step generator
StageName string `json:"e_10"`
PipelineURLHash string `json:"e_4"` // defaults to sha1 of provider.GetBuildURL()
BuildURLHash string `json:"e_5"` // defaults to sha1 of provider.GetJobURL()
PipelineURLHash string `json:"e_4"` // defaults to sha1 of provider.BuildURL()
BuildURLHash string `json:"e_5"` // defaults to sha1 of provider.JobURL()
Orchestrator string `json:"e_14"` // defaults to provider.OrchestratorType()
}

View File

@@ -28,7 +28,7 @@ type Telemetry struct {
baseData BaseData
baseMetaData BaseMetaData
data Data
provider orchestrator.OrchestratorSpecificConfigProviding
provider orchestrator.ConfigProvider
disabled bool
client *piperhttp.Client
CustomReportingDsn string
@@ -43,8 +43,8 @@ type Telemetry struct {
func (t *Telemetry) Initialize(telemetryDisabled bool, stepName string) {
t.disabled = telemetryDisabled
provider, err := orchestrator.NewOrchestratorSpecificConfigProvider()
if err != nil || provider == nil {
provider, err := orchestrator.GetOrchestratorConfigProvider(nil)
if err != nil {
log.Entry().Warningf("could not get orchestrator config provider, leads to insufficient data")
provider = &orchestrator.UnknownOrchestratorConfigProvider{}
}
@@ -73,8 +73,8 @@ func (t *Telemetry) Initialize(telemetryDisabled bool, stepName string) {
}
t.baseData = BaseData{
Orchestrator: provider.OrchestratorType(),
StageName: provider.GetStageName(),
Orchestrator: t.provider.OrchestratorType(),
StageName: t.provider.StageName(),
URL: LibraryRepository,
ActionName: actionName,
EventType: eventType,
@@ -87,12 +87,12 @@ func (t *Telemetry) Initialize(telemetryDisabled bool, stepName string) {
}
func (t *Telemetry) getPipelineURLHash() string {
jobURL := t.provider.GetJobURL()
jobURL := t.provider.JobURL()
return t.toSha1OrNA(jobURL)
}
func (t *Telemetry) getBuildURLHash() string {
buildURL := t.provider.GetBuildURL()
buildURL := t.provider.BuildURL()
return t.toSha1OrNA(buildURL)
}
@@ -160,7 +160,7 @@ func (t *Telemetry) logStepTelemetryData() {
StepDuration: t.data.CustomData.Duration,
ErrorCategory: t.data.CustomData.ErrorCategory,
ErrorDetail: fatalError,
CorrelationID: t.provider.GetBuildURL(),
CorrelationID: t.provider.BuildURL(),
PiperCommitHash: t.data.CustomData.PiperCommitHash,
}
stepTelemetryJSON, err := json.Marshal(stepTelemetryData)

View File

@@ -26,7 +26,7 @@ func TestTelemetry_Initialize(t *testing.T) {
baseData BaseData
baseMetaData BaseMetaData
data Data
provider orchestrator.OrchestratorSpecificConfigProviding
provider orchestrator.ConfigProvider
disabled bool
client *piperhttp.Client
CustomReportingDsn string
@@ -81,7 +81,7 @@ func TestTelemetry_Send(t *testing.T) {
baseData BaseData
baseMetaData BaseMetaData
data Data
provider orchestrator.OrchestratorSpecificConfigProviding
provider orchestrator.ConfigProvider
disabled bool
client *piperhttp.Client
CustomReportingDsn string
@@ -268,7 +268,7 @@ func TestTelemetry_logStepTelemetryData(t *testing.T) {
type fields struct {
data Data
provider orchestrator.OrchestratorSpecificConfigProviding
provider orchestrator.ConfigProvider
}
tests := []struct {
name string