mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-12 10:55:20 +02:00
feat(orchestrator): add implementation for GitHub (#4525)
* add comments with examples to methods * a bit refactoring and cleanup * actionsURL * GetBuildStatus * GetBuildID, GetChangeSet, GetPipelineStartTime * GetStageName and GetBuildReason * refactor fetching jobs * GetJobName and GetJobURL * chnage GetBuildURL * refactor actionsURL * fix guessCurrentJob bug * unit tests for all * refactor GetLog * refactor and fix tests * change GetBuildURL to use env vars * fix issues * leftover * add comment * fix according to review comments --------- Co-authored-by: Gulom Alimov <gulomjon.alimov@sap.com> Co-authored-by: Jordi van Liempt <35920075+jliempt@users.noreply.github.com>
This commit is contained in:
parent
b7663466f3
commit
e805beda70
@ -13,20 +13,17 @@ import (
|
||||
|
||||
type AzureDevOpsConfigProvider struct {
|
||||
client piperHttp.Client
|
||||
options piperHttp.ClientOptions
|
||||
apiInformation map[string]interface{}
|
||||
}
|
||||
|
||||
// InitOrchestratorProvider initializes http client for AzureDevopsConfigProvider
|
||||
func (a *AzureDevOpsConfigProvider) InitOrchestratorProvider(settings *OrchestratorSettings) {
|
||||
a.client = piperHttp.Client{}
|
||||
a.options = piperHttp.ClientOptions{
|
||||
a.client.SetOptions(piperHttp.ClientOptions{
|
||||
Username: "",
|
||||
Password: settings.AzureToken,
|
||||
MaxRetries: 3,
|
||||
TransportTimeout: time.Second * 10,
|
||||
}
|
||||
a.client.SetOptions(a.options)
|
||||
})
|
||||
log.Entry().Debug("Successfully initialized Azure config provider")
|
||||
}
|
||||
|
||||
@ -102,12 +99,12 @@ func (a *AzureDevOpsConfigProvider) GetBuildStatus() string {
|
||||
// cases to align with Jenkins: SUCCESS, FAILURE, NOT_BUILD, ABORTED
|
||||
switch buildStatus := getEnv("AGENT_JOBSTATUS", "FAILURE"); buildStatus {
|
||||
case "Succeeded":
|
||||
return "SUCCESS"
|
||||
return BuildStatusSuccess
|
||||
case "Canceled":
|
||||
return "ABORTED"
|
||||
return BuildStatusAborted
|
||||
default:
|
||||
// Failed, SucceededWithIssues
|
||||
return "FAILURE"
|
||||
return BuildStatusFailure
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@ package orchestrator
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
@ -14,53 +13,51 @@ import (
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
|
||||
"golang.org/x/sync/errgroup"
|
||||
"golang.org/x/sync/semaphore"
|
||||
)
|
||||
|
||||
var httpHeader = http.Header{
|
||||
"Accept": {"application/vnd.github+json"},
|
||||
type GitHubActionsConfigProvider struct {
|
||||
client piperHttp.Client
|
||||
runData run
|
||||
jobs []job
|
||||
jobsFetched bool
|
||||
currentJob job
|
||||
}
|
||||
|
||||
type GitHubActionsConfigProvider struct {
|
||||
client piperHttp.Client
|
||||
type run struct {
|
||||
fetched bool
|
||||
Status string `json:"status"`
|
||||
StartedAt time.Time `json:"run_started_at"`
|
||||
}
|
||||
|
||||
type job struct {
|
||||
ID int `json:"id"`
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
HtmlURL string `json:"html_url"`
|
||||
}
|
||||
|
||||
type stagesID struct {
|
||||
Jobs []job `json:"jobs"`
|
||||
}
|
||||
|
||||
type logs struct {
|
||||
type fullLog struct {
|
||||
sync.Mutex
|
||||
b [][]byte
|
||||
}
|
||||
|
||||
var httpHeaders = http.Header{
|
||||
"Accept": {"application/vnd.github+json"},
|
||||
"X-GitHub-Api-Version": {"2022-11-28"},
|
||||
}
|
||||
|
||||
// InitOrchestratorProvider initializes http client for GitHubActionsDevopsConfigProvider
|
||||
func (g *GitHubActionsConfigProvider) InitOrchestratorProvider(settings *OrchestratorSettings) {
|
||||
g.client = piperHttp.Client{}
|
||||
g.client.SetOptions(piperHttp.ClientOptions{
|
||||
Password: settings.GitHubToken,
|
||||
Token: "Bearer " + settings.GitHubToken,
|
||||
MaxRetries: 3,
|
||||
TransportTimeout: time.Second * 10,
|
||||
})
|
||||
|
||||
log.Entry().Debug("Successfully initialized GitHubActions config provider")
|
||||
}
|
||||
|
||||
func getActionsURL() string {
|
||||
ghURL := getEnv("GITHUB_URL", "")
|
||||
switch ghURL {
|
||||
case "https://github.com/":
|
||||
ghURL = "https://api.github.com"
|
||||
default:
|
||||
ghURL += "api/v3"
|
||||
}
|
||||
return fmt.Sprintf("%s/repos/%s/actions", ghURL, getEnv("GITHUB_REPOSITORY", ""))
|
||||
}
|
||||
|
||||
func (g *GitHubActionsConfigProvider) OrchestratorVersion() string {
|
||||
log.Entry().Debugf("OrchestratorVersion() for GitHub Actions is not applicable.")
|
||||
return "n/a"
|
||||
}
|
||||
|
||||
@ -68,109 +65,141 @@ func (g *GitHubActionsConfigProvider) OrchestratorType() string {
|
||||
return "GitHubActions"
|
||||
}
|
||||
|
||||
// GetBuildStatus returns current run status
|
||||
func (g *GitHubActionsConfigProvider) GetBuildStatus() string {
|
||||
log.Entry().Infof("GetBuildStatus() for GitHub Actions not yet implemented.")
|
||||
return "FAILURE"
|
||||
g.fetchRunData()
|
||||
switch g.runData.Status {
|
||||
case "success":
|
||||
return BuildStatusSuccess
|
||||
case "cancelled":
|
||||
return BuildStatusAborted
|
||||
case "in_progress":
|
||||
return BuildStatusInProgress
|
||||
default:
|
||||
return BuildStatusFailure
|
||||
}
|
||||
}
|
||||
|
||||
// GetLog returns the whole logfile for the current pipeline run
|
||||
func (g *GitHubActionsConfigProvider) GetLog() ([]byte, error) {
|
||||
ids, err := g.getStageIds()
|
||||
if err != nil {
|
||||
if err := g.fetchJobs(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// Ignore the last stage (job) as it is not possible in GitHub to fetch logs for a running job.
|
||||
jobs := g.jobs[:len(g.jobs)-1]
|
||||
|
||||
logs := logs{
|
||||
b: make([][]byte, len(ids)),
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
sem := semaphore.NewWeighted(10)
|
||||
fullLogs := fullLog{b: make([][]byte, len(jobs))}
|
||||
wg := errgroup.Group{}
|
||||
for i := range ids {
|
||||
wg.SetLimit(10)
|
||||
for i := range jobs {
|
||||
i := i // https://golang.org/doc/faq#closures_and_goroutines
|
||||
if err := sem.Acquire(ctx, 1); err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire semaphore: %w", err)
|
||||
}
|
||||
wg.Go(func() error {
|
||||
defer sem.Release(1)
|
||||
resp, err := g.client.GetRequest(fmt.Sprintf("%s/jobs/%d/logs", getActionsURL(), ids[i]), httpHeader, nil)
|
||||
resp, err := g.client.GetRequest(fmt.Sprintf("%s/jobs/%d/logs", actionsURL(), jobs[i].ID), httpHeaders, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get API data: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to read response body: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
logs.Lock()
|
||||
defer logs.Unlock()
|
||||
logs.b[i] = b
|
||||
|
||||
fullLogs.Lock()
|
||||
fullLogs.b[i] = b
|
||||
fullLogs.Unlock()
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if err = wg.Wait(); err != nil {
|
||||
if err := wg.Wait(); err != nil {
|
||||
return nil, fmt.Errorf("failed to get logs: %w", err)
|
||||
}
|
||||
|
||||
return bytes.Join(logs.b, []byte("")), nil
|
||||
return bytes.Join(fullLogs.b, []byte("")), nil
|
||||
}
|
||||
|
||||
// GetBuildID returns current run ID
|
||||
func (g *GitHubActionsConfigProvider) GetBuildID() string {
|
||||
log.Entry().Infof("GetBuildID() for GitHub Actions not yet implemented.")
|
||||
return "n/a"
|
||||
return getEnv("GITHUB_RUN_ID", "n/a")
|
||||
}
|
||||
|
||||
func (g *GitHubActionsConfigProvider) GetChangeSet() []ChangeSet {
|
||||
log.Entry().Warn("GetChangeSet for GitHubActions not yet implemented")
|
||||
log.Entry().Debug("GetChangeSet for GitHubActions not implemented")
|
||||
return []ChangeSet{}
|
||||
}
|
||||
|
||||
// GetPipelineStartTime returns the pipeline start time in UTC
|
||||
func (g *GitHubActionsConfigProvider) GetPipelineStartTime() time.Time {
|
||||
log.Entry().Infof("GetPipelineStartTime() for GitHub Actions not yet implemented.")
|
||||
return time.Time{}.UTC()
|
||||
g.fetchRunData()
|
||||
return g.runData.StartedAt.UTC()
|
||||
}
|
||||
|
||||
// GetStageName returns the human-readable name given to a stage.
|
||||
func (g *GitHubActionsConfigProvider) GetStageName() string {
|
||||
return "GITHUB_WORKFLOW" // TODO: is there something like is "stage" in GH Actions?
|
||||
return getEnv("GITHUB_JOB", "unknown")
|
||||
}
|
||||
|
||||
// GetBuildReason 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 {
|
||||
log.Entry().Infof("GetBuildReason() for GitHub Actions not yet implemented.")
|
||||
return "n/a"
|
||||
switch getEnv("GITHUB_EVENT_NAME", "") {
|
||||
case "workflow_dispatch":
|
||||
return BuildReasonManual
|
||||
case "schedule":
|
||||
return BuildReasonSchedule
|
||||
case "pull_request":
|
||||
return BuildReasonPullRequest
|
||||
case "workflow_call":
|
||||
return BuildReasonResourceTrigger
|
||||
case "push":
|
||||
return BuildReasonIndividualCI
|
||||
default:
|
||||
return BuildReasonUnknown
|
||||
}
|
||||
}
|
||||
|
||||
// GetBranch returns the source branch name, e.g. main
|
||||
func (g *GitHubActionsConfigProvider) GetBranch() string {
|
||||
return strings.TrimPrefix(getEnv("GITHUB_REF", "n/a"), "refs/heads/")
|
||||
return getEnv("GITHUB_REF_NAME", "n/a")
|
||||
}
|
||||
|
||||
// GetReference return the git reference. For example, refs/heads/your_branch_name
|
||||
func (g *GitHubActionsConfigProvider) GetReference() string {
|
||||
return getEnv("GITHUB_REF", "n/a")
|
||||
}
|
||||
|
||||
// GetBuildURL returns the builds URL. For example, https://github.com/SAP/jenkins-library/actions/runs/5815297487
|
||||
func (g *GitHubActionsConfigProvider) GetBuildURL() string {
|
||||
return g.GetRepoURL() + "/actions/runs/" + getEnv("GITHUB_RUN_ID", "n/a")
|
||||
return g.GetRepoURL() + "/actions/runs/" + g.GetBuildID()
|
||||
}
|
||||
|
||||
// GetJobURL returns the current job HTML URL (not API URL).
|
||||
// For example, https://github.com/SAP/jenkins-library/actions/runs/123456/jobs/7654321
|
||||
func (g *GitHubActionsConfigProvider) GetJobURL() string {
|
||||
log.Entry().Debugf("Not yet implemented.")
|
||||
return g.GetRepoURL() + "/actions/runs/" + getEnv("GITHUB_RUN_ID", "n/a")
|
||||
// We need to query the GitHub API here because the environment variable GITHUB_JOB returns
|
||||
// the name of the job, not a numeric ID (which we need to form the URL)
|
||||
g.guessCurrentJob()
|
||||
return g.currentJob.HtmlURL
|
||||
}
|
||||
|
||||
// GetJobName returns the current workflow name. For example, "Piper workflow"
|
||||
func (g *GitHubActionsConfigProvider) GetJobName() string {
|
||||
log.Entry().Debugf("GetJobName() for GitHubActions not yet implemented.")
|
||||
return "n/a"
|
||||
return getEnv("GITHUB_WORKFLOW", "unknown")
|
||||
}
|
||||
|
||||
// GetCommit returns the commit SHA that triggered the workflow. For example, ffac537e6cbbf934b08745a378932722df287a53
|
||||
func (g *GitHubActionsConfigProvider) GetCommit() 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 {
|
||||
return getEnv("GITHUB_SERVER_URL", "n/a") + "/" + getEnv("GITHUB_REPOSITORY", "n/a")
|
||||
}
|
||||
|
||||
// GetPullRequestConfig returns pull request configuration
|
||||
func (g *GitHubActionsConfigProvider) GetPullRequestConfig() 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")
|
||||
@ -182,6 +211,7 @@ 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")
|
||||
}
|
||||
@ -191,26 +221,82 @@ func isGitHubActions() bool {
|
||||
return areIndicatingEnvVarsSet(envVars)
|
||||
}
|
||||
|
||||
func (g *GitHubActionsConfigProvider) getStageIds() ([]int, error) {
|
||||
resp, err := g.client.GetRequest(fmt.Sprintf("%s/runs/%s/jobs", getActionsURL(), getEnv("GITHUB_RUN_ID", "")), httpHeader, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get API data: %w", err)
|
||||
}
|
||||
|
||||
var stagesID stagesID
|
||||
err = piperHttp.ParseHTTPResponseBodyJSON(resp, &stagesID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse JSON data: %w", err)
|
||||
}
|
||||
|
||||
ids := make([]int, len(stagesID.Jobs))
|
||||
for i, job := range stagesID.Jobs {
|
||||
ids[i] = job.ID
|
||||
}
|
||||
if len(ids) == 0 {
|
||||
return nil, fmt.Errorf("failed to get IDs")
|
||||
}
|
||||
|
||||
// execution of the last stage hasn't finished yet - we can't get logs of the last stage
|
||||
return ids[:len(stagesID.Jobs)-1], nil
|
||||
// actionsURL returns URL to actions resource. For example,
|
||||
// https://api.github.com/repos/SAP/jenkins-library/actions
|
||||
func actionsURL() string {
|
||||
return getEnv("GITHUB_API_URL", "") + "/repos/" + getEnv("GITHUB_REPOSITORY", "") + "/actions"
|
||||
}
|
||||
|
||||
func (g *GitHubActionsConfigProvider) fetchRunData() {
|
||||
if g.runData.fetched {
|
||||
return
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/runs/%s", actionsURL(), getEnv("GITHUB_RUN_ID", ""))
|
||||
resp, err := g.client.GetRequest(url, httpHeaders, nil)
|
||||
if err != nil || resp.StatusCode != 200 {
|
||||
log.Entry().Errorf("failed to get API data: %s", err)
|
||||
return
|
||||
}
|
||||
|
||||
err = piperHttp.ParseHTTPResponseBodyJSON(resp, &g.runData)
|
||||
if err != nil {
|
||||
log.Entry().Errorf("failed to parse JSON data: %s", err)
|
||||
return
|
||||
}
|
||||
g.runData.fetched = true
|
||||
}
|
||||
|
||||
func (g *GitHubActionsConfigProvider) fetchJobs() error {
|
||||
if g.jobsFetched {
|
||||
return nil
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s/runs/%s/jobs", actionsURL(), g.GetBuildID())
|
||||
resp, err := g.client.GetRequest(url, httpHeaders, nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get API data: %w", err)
|
||||
}
|
||||
|
||||
var result struct {
|
||||
Jobs []job `json:"jobs"`
|
||||
}
|
||||
err = piperHttp.ParseHTTPResponseBodyJSON(resp, &result)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to parse JSON data: %w", err)
|
||||
}
|
||||
|
||||
if len(result.Jobs) == 0 {
|
||||
return fmt.Errorf("no jobs found in response")
|
||||
}
|
||||
g.jobs = result.Jobs
|
||||
g.jobsFetched = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g *GitHubActionsConfigProvider) guessCurrentJob() {
|
||||
// check if the current job has already been guessed
|
||||
if g.currentJob.ID != 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// fetch jobs if they haven't been fetched yet
|
||||
if err := g.fetchJobs(); err != nil {
|
||||
log.Entry().Errorf("failed to fetch jobs: %s", err)
|
||||
g.jobs = []job{}
|
||||
return
|
||||
}
|
||||
|
||||
targetJobName := getEnv("GITHUB_JOB", "unknown")
|
||||
log.Entry().Debugf("looking for job '%s' in jobs list: %v", targetJobName, g.jobs)
|
||||
for _, j := range g.jobs {
|
||||
// j.Name may be something like "piper / Init / Init"
|
||||
// but GITHUB_JOB env may contain only "Init"
|
||||
if strings.HasSuffix(j.Name, targetJobName) {
|
||||
log.Entry().Debugf("current job id: %d", j.ID)
|
||||
g.currentJob = j
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,9 +5,9 @@ package orchestrator
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@ -17,187 +17,328 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestGitHubActions(t *testing.T) {
|
||||
t.Run("BranchBuild", func(t *testing.T) {
|
||||
defer resetEnv(os.Environ())
|
||||
os.Clearenv()
|
||||
os.Unsetenv("GITHUB_HEAD_REF")
|
||||
os.Setenv("GITHUB_ACTIONS", "true")
|
||||
os.Setenv("GITHUB_REF", "refs/heads/feat/test-gh-actions")
|
||||
os.Setenv("GITHUB_RUN_ID", "42")
|
||||
os.Setenv("GITHUB_SHA", "abcdef42713")
|
||||
os.Setenv("GITHUB_SERVER_URL", "github.com")
|
||||
os.Setenv("GITHUB_REPOSITORY", "foo/bar")
|
||||
|
||||
p, _ := NewOrchestratorSpecificConfigProvider()
|
||||
|
||||
assert.False(t, p.IsPullRequest())
|
||||
assert.Equal(t, "github.com/foo/bar/actions/runs/42", p.GetBuildURL())
|
||||
assert.Equal(t, "feat/test-gh-actions", p.GetBranch())
|
||||
assert.Equal(t, "refs/heads/feat/test-gh-actions", p.GetReference())
|
||||
assert.Equal(t, "abcdef42713", p.GetCommit())
|
||||
assert.Equal(t, "github.com/foo/bar", p.GetRepoURL())
|
||||
assert.Equal(t, "GitHubActions", p.OrchestratorType())
|
||||
})
|
||||
|
||||
t.Run("PR", func(t *testing.T) {
|
||||
defer resetEnv(os.Environ())
|
||||
os.Clearenv()
|
||||
os.Setenv("GITHUB_HEAD_REF", "feat/test-gh-actions")
|
||||
os.Setenv("GITHUB_BASE_REF", "main")
|
||||
os.Setenv("GITHUB_REF", "refs/pull/42/merge")
|
||||
|
||||
p := GitHubActionsConfigProvider{}
|
||||
c := p.GetPullRequestConfig()
|
||||
|
||||
assert.True(t, p.IsPullRequest())
|
||||
assert.Equal(t, "feat/test-gh-actions", c.Branch)
|
||||
assert.Equal(t, "main", c.Base)
|
||||
assert.Equal(t, "42", c.Key)
|
||||
})
|
||||
|
||||
t.Run("Test get logs - success", func(t *testing.T) {
|
||||
defer resetEnv(os.Environ())
|
||||
os.Clearenv()
|
||||
os.Unsetenv("GITHUB_HEAD_REF")
|
||||
os.Setenv("GITHUB_ACTIONS", "true")
|
||||
os.Setenv("GITHUB_REF_NAME", "feat/test-gh-actions")
|
||||
os.Setenv("GITHUB_REF", "refs/heads/feat/test-gh-actions")
|
||||
os.Setenv("GITHUB_RUN_ID", "42")
|
||||
os.Setenv("GITHUB_SHA", "abcdef42713")
|
||||
os.Setenv("GITHUB_REPOSITORY", "foo/bar")
|
||||
os.Setenv("GITHUB_URL", "https://github.com/")
|
||||
p := func() OrchestratorSpecificConfigProviding {
|
||||
g := GitHubActionsConfigProvider{}
|
||||
g.client = piperHttp.Client{}
|
||||
g.client.SetOptions(piperHttp.ClientOptions{
|
||||
MaxRequestDuration: 5 * time.Second,
|
||||
Password: "TOKEN",
|
||||
TransportSkipVerification: true,
|
||||
UseDefaultTransport: true, // need to use default transport for http mock
|
||||
MaxRetries: -1,
|
||||
})
|
||||
return &g
|
||||
}()
|
||||
stagesID := stagesID{
|
||||
Jobs: []job{
|
||||
{ID: 123},
|
||||
{ID: 124},
|
||||
{ID: 125},
|
||||
},
|
||||
}
|
||||
logs := []string{
|
||||
"log_record1\n",
|
||||
"log_record2\n",
|
||||
}
|
||||
httpmock.Activate()
|
||||
defer httpmock.DeactivateAndReset()
|
||||
httpmock.RegisterResponder(http.MethodGet, "https://api.github.com/repos/foo/bar/actions/runs/42/jobs",
|
||||
func(req *http.Request) (*http.Response, error) {
|
||||
return httpmock.NewJsonResponse(200, stagesID)
|
||||
},
|
||||
)
|
||||
httpmock.RegisterResponder(http.MethodGet, "https://api.github.com/repos/foo/bar/actions/jobs/123/logs",
|
||||
func(req *http.Request) (*http.Response, error) {
|
||||
return httpmock.NewStringResponse(200, string(logs[0])), nil
|
||||
},
|
||||
)
|
||||
httpmock.RegisterResponder(http.MethodGet, "https://api.github.com/repos/foo/bar/actions/jobs/124/logs",
|
||||
func(req *http.Request) (*http.Response, error) {
|
||||
return httpmock.NewStringResponse(200, string(logs[1])), nil
|
||||
},
|
||||
)
|
||||
|
||||
actual, err := p.GetLog()
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, strings.Join(logs, ""), string(actual))
|
||||
})
|
||||
|
||||
t.Run("Test get logs - error: failed to get stages ID", func(t *testing.T) {
|
||||
defer resetEnv(os.Environ())
|
||||
os.Clearenv()
|
||||
os.Unsetenv("GITHUB_HEAD_REF")
|
||||
os.Setenv("GITHUB_ACTIONS", "true")
|
||||
os.Setenv("GITHUB_REF_NAME", "feat/test-gh-actions")
|
||||
os.Setenv("GITHUB_REF", "refs/heads/feat/test-gh-actions")
|
||||
os.Setenv("GITHUB_RUN_ID", "42")
|
||||
os.Setenv("GITHUB_SHA", "abcdef42713")
|
||||
os.Setenv("GITHUB_REPOSITORY", "foo/bar")
|
||||
os.Setenv("GITHUB_URL", "https://github.com/")
|
||||
p := func() OrchestratorSpecificConfigProviding {
|
||||
g := GitHubActionsConfigProvider{}
|
||||
g.client = piperHttp.Client{}
|
||||
g.client.SetOptions(piperHttp.ClientOptions{
|
||||
MaxRequestDuration: 5 * time.Second,
|
||||
Password: "TOKEN",
|
||||
TransportSkipVerification: true,
|
||||
UseDefaultTransport: true, // need to use default transport for http mock
|
||||
MaxRetries: -1,
|
||||
})
|
||||
return &g
|
||||
}()
|
||||
httpmock.Activate()
|
||||
defer httpmock.DeactivateAndReset()
|
||||
httpmock.RegisterResponder(http.MethodGet, "https://api.github.com/repos/foo/bar/actions/runs/42/jobs",
|
||||
func(req *http.Request) (*http.Response, error) {
|
||||
return nil, fmt.Errorf("err")
|
||||
},
|
||||
)
|
||||
actual, err := p.GetLog()
|
||||
|
||||
assert.Nil(t, actual)
|
||||
assert.EqualError(t, err, "failed to get API data: HTTP request to https://api.github.com/repos/foo/bar/actions/runs/42/jobs failed with error: HTTP GET request to https://api.github.com/repos/foo/bar/actions/runs/42/jobs failed: Get \"https://api.github.com/repos/foo/bar/actions/runs/42/jobs\": err")
|
||||
})
|
||||
|
||||
t.Run("Test get logs - failed to get logs", func(t *testing.T) {
|
||||
defer resetEnv(os.Environ())
|
||||
os.Clearenv()
|
||||
os.Unsetenv("GITHUB_HEAD_REF")
|
||||
os.Setenv("GITHUB_ACTIONS", "true")
|
||||
os.Setenv("GITHUB_REF_NAME", "feat/test-gh-actions")
|
||||
os.Setenv("GITHUB_REF", "refs/heads/feat/test-gh-actions")
|
||||
os.Setenv("GITHUB_RUN_ID", "42")
|
||||
os.Setenv("GITHUB_SHA", "abcdef42713")
|
||||
os.Setenv("GITHUB_REPOSITORY", "foo/bar")
|
||||
os.Setenv("GITHUB_URL", "https://github.com/")
|
||||
p := func() OrchestratorSpecificConfigProviding {
|
||||
g := GitHubActionsConfigProvider{}
|
||||
g.client = piperHttp.Client{}
|
||||
g.client.SetOptions(piperHttp.ClientOptions{
|
||||
MaxRequestDuration: 5 * time.Second,
|
||||
Password: "TOKEN",
|
||||
TransportSkipVerification: true,
|
||||
UseDefaultTransport: true, // need to use default transport for http mock
|
||||
MaxRetries: -1,
|
||||
})
|
||||
return &g
|
||||
}()
|
||||
stagesID := stagesID{
|
||||
Jobs: []job{
|
||||
{ID: 123},
|
||||
{ID: 124},
|
||||
{ID: 125},
|
||||
},
|
||||
}
|
||||
httpmock.Activate()
|
||||
defer httpmock.DeactivateAndReset()
|
||||
httpmock.RegisterResponder(http.MethodGet, "https://api.github.com/repos/foo/bar/actions/runs/42/jobs",
|
||||
func(req *http.Request) (*http.Response, error) {
|
||||
return httpmock.NewJsonResponse(200, stagesID)
|
||||
},
|
||||
)
|
||||
httpmock.RegisterResponder(http.MethodGet, "https://api.github.com/repos/foo/bar/actions/jobs/123/logs",
|
||||
func(req *http.Request) (*http.Response, error) {
|
||||
return nil, fmt.Errorf("err")
|
||||
},
|
||||
)
|
||||
|
||||
actual, err := p.GetLog()
|
||||
|
||||
assert.Nil(t, actual)
|
||||
// GitHubActionsConfigProvider.GetLog calls http.GetRequest concurrently, so we don't know what log (123 or 124) will be got first
|
||||
// ref: pkg/orchestrator/gitHubActions.go:90
|
||||
assert.ErrorContains(t, err, "failed to get logs: failed to get API data: HTTP request to https://api.github.com/repos/foo/bar/actions/jobs/12")
|
||||
})
|
||||
func TestGitHubActionsConfigProvider_GetBuildStatus(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
runData run
|
||||
want string
|
||||
}{
|
||||
{"BuildStatusSuccess", run{fetched: true, Status: "success"}, BuildStatusSuccess},
|
||||
{"BuildStatusAborted", run{fetched: true, Status: "cancelled"}, BuildStatusAborted},
|
||||
{"BuildStatusInProgress", run{fetched: true, Status: "in_progress"}, BuildStatusInProgress},
|
||||
{"BuildStatusFailure", run{fetched: true, Status: "qwertyu"}, BuildStatusFailure},
|
||||
{"BuildStatusFailure", run{fetched: true, Status: ""}, BuildStatusFailure},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := &GitHubActionsConfigProvider{
|
||||
runData: tt.runData,
|
||||
}
|
||||
assert.Equalf(t, tt.want, g.GetBuildStatus(), "GetBuildStatus()")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGitHubActionsConfigProvider_GetBuildReason(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
envGithubRef string
|
||||
want string
|
||||
}{
|
||||
{"BuildReasonManual", "workflow_dispatch", BuildReasonManual},
|
||||
{"BuildReasonSchedule", "schedule", BuildReasonSchedule},
|
||||
{"BuildReasonPullRequest", "pull_request", BuildReasonPullRequest},
|
||||
{"BuildReasonResourceTrigger", "workflow_call", BuildReasonResourceTrigger},
|
||||
{"BuildReasonIndividualCI", "push", BuildReasonIndividualCI},
|
||||
{"BuildReasonUnknown", "qwerty", BuildReasonUnknown},
|
||||
{"BuildReasonUnknown", "", BuildReasonUnknown},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := &GitHubActionsConfigProvider{}
|
||||
|
||||
_ = os.Setenv("GITHUB_EVENT_NAME", tt.envGithubRef)
|
||||
assert.Equalf(t, tt.want, g.GetBuildReason(), "GetBuildReason()")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGitHubActionsConfigProvider_GetRepoURL(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
envServerURL string
|
||||
envRepo string
|
||||
want string
|
||||
}{
|
||||
{"github.com", "https://github.com", "SAP/jenkins-library", "https://github.com/SAP/jenkins-library"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := &GitHubActionsConfigProvider{}
|
||||
|
||||
_ = os.Setenv("GITHUB_SERVER_URL", tt.envServerURL)
|
||||
_ = os.Setenv("GITHUB_REPOSITORY", tt.envRepo)
|
||||
assert.Equalf(t, tt.want, g.GetRepoURL(), "GetRepoURL()")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGitHubActionsConfigProvider_GetPullRequestConfig(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
envRef string
|
||||
want PullRequestConfig
|
||||
}{
|
||||
{"1", "refs/pull/1234/merge", PullRequestConfig{"n/a", "n/a", "1234"}},
|
||||
{"2", "refs/pull/1234", PullRequestConfig{"n/a", "n/a", "1234"}},
|
||||
{"2", "1234/merge", PullRequestConfig{"n/a", "n/a", "1234"}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
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()")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGitHubActionsConfigProvider_guessCurrentJob(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
jobs []job
|
||||
jobsFetched bool
|
||||
targetJobName string
|
||||
wantJob job
|
||||
}{
|
||||
{
|
||||
name: "job found",
|
||||
jobs: []job{{Name: "Job1"}, {Name: "Job2"}, {Name: "Job3"}},
|
||||
jobsFetched: true,
|
||||
targetJobName: "Job2",
|
||||
wantJob: job{Name: "Job2"},
|
||||
},
|
||||
{
|
||||
name: "job found",
|
||||
jobs: []job{{Name: "Piper / Job1"}, {Name: "Piper / Job2"}, {Name: "Piper / Job3"}},
|
||||
jobsFetched: true,
|
||||
targetJobName: "Job2",
|
||||
wantJob: job{Name: "Piper / Job2"},
|
||||
},
|
||||
{
|
||||
name: "job not found",
|
||||
jobs: []job{{Name: "Job1"}, {Name: "Job2"}, {Name: "Job3"}},
|
||||
jobsFetched: true,
|
||||
targetJobName: "Job123",
|
||||
wantJob: job{},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g := &GitHubActionsConfigProvider{
|
||||
jobs: tt.jobs,
|
||||
jobsFetched: tt.jobsFetched,
|
||||
}
|
||||
_ = os.Setenv("GITHUB_JOB", tt.targetJobName)
|
||||
g.guessCurrentJob()
|
||||
|
||||
assert.Equal(t, tt.wantJob, g.currentJob)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGitHubActionsConfigProvider_fetchRunData(t *testing.T) {
|
||||
// data
|
||||
respJson := map[string]interface{}{
|
||||
"status": "completed",
|
||||
"run_started_at": "2023-08-11T07:28:24Z",
|
||||
"html_url": "https://github.com/SAP/jenkins-library/actions/runs/11111",
|
||||
}
|
||||
startedAt, _ := time.Parse(time.RFC3339, "2023-08-11T07:28:24Z")
|
||||
wantRunData := run{
|
||||
fetched: true,
|
||||
Status: "completed",
|
||||
StartedAt: startedAt,
|
||||
}
|
||||
|
||||
// setup provider
|
||||
g := &GitHubActionsConfigProvider{}
|
||||
g.client.SetOptions(piperHttp.ClientOptions{
|
||||
UseDefaultTransport: true, // need to use default transport for http mock
|
||||
MaxRetries: -1,
|
||||
})
|
||||
// setup http mock
|
||||
httpmock.Activate()
|
||||
defer httpmock.DeactivateAndReset()
|
||||
httpmock.RegisterResponder(http.MethodGet, "https://api.github.com/repos/SAP/jenkins-library/actions/runs/11111",
|
||||
func(req *http.Request) (*http.Response, error) {
|
||||
return httpmock.NewJsonResponse(200, respJson)
|
||||
},
|
||||
)
|
||||
// setup env vars
|
||||
defer resetEnv(os.Environ())
|
||||
os.Clearenv()
|
||||
_ = os.Setenv("GITHUB_API_URL", "https://api.github.com")
|
||||
_ = os.Setenv("GITHUB_REPOSITORY", "SAP/jenkins-library")
|
||||
_ = os.Setenv("GITHUB_RUN_ID", "11111")
|
||||
|
||||
// run
|
||||
g.fetchRunData()
|
||||
assert.Equal(t, wantRunData, g.runData)
|
||||
}
|
||||
|
||||
func TestGitHubActionsConfigProvider_fetchJobs(t *testing.T) {
|
||||
// data
|
||||
respJson := map[string]interface{}{"jobs": []map[string]interface{}{{
|
||||
"id": 111,
|
||||
"name": "Piper / Init",
|
||||
"html_url": "https://github.com/SAP/jenkins-library/actions/runs/11111/jobs/111",
|
||||
}, {
|
||||
"id": 222,
|
||||
"name": "Piper / Build",
|
||||
"html_url": "https://github.com/SAP/jenkins-library/actions/runs/11111/jobs/222",
|
||||
}, {
|
||||
"id": 333,
|
||||
"name": "Piper / Acceptance",
|
||||
"html_url": "https://github.com/SAP/jenkins-library/actions/runs/11111/jobs/333",
|
||||
},
|
||||
}}
|
||||
wantJobs := []job{{
|
||||
ID: 111,
|
||||
Name: "Piper / Init",
|
||||
HtmlURL: "https://github.com/SAP/jenkins-library/actions/runs/11111/jobs/111",
|
||||
}, {
|
||||
ID: 222,
|
||||
Name: "Piper / Build",
|
||||
HtmlURL: "https://github.com/SAP/jenkins-library/actions/runs/11111/jobs/222",
|
||||
}, {
|
||||
ID: 333,
|
||||
Name: "Piper / Acceptance",
|
||||
HtmlURL: "https://github.com/SAP/jenkins-library/actions/runs/11111/jobs/333",
|
||||
}}
|
||||
|
||||
// setup provider
|
||||
g := &GitHubActionsConfigProvider{}
|
||||
g.client.SetOptions(piperHttp.ClientOptions{
|
||||
UseDefaultTransport: true, // need to use default transport for http mock
|
||||
MaxRetries: -1,
|
||||
})
|
||||
// setup http mock
|
||||
httpmock.Activate()
|
||||
defer httpmock.DeactivateAndReset()
|
||||
httpmock.RegisterResponder(
|
||||
http.MethodGet,
|
||||
"https://api.github.com/repos/SAP/jenkins-library/actions/runs/11111/jobs",
|
||||
func(req *http.Request) (*http.Response, error) {
|
||||
return httpmock.NewJsonResponse(200, respJson)
|
||||
},
|
||||
)
|
||||
// setup env vars
|
||||
defer resetEnv(os.Environ())
|
||||
os.Clearenv()
|
||||
_ = os.Setenv("GITHUB_API_URL", "https://api.github.com")
|
||||
_ = os.Setenv("GITHUB_REPOSITORY", "SAP/jenkins-library")
|
||||
_ = os.Setenv("GITHUB_RUN_ID", "11111")
|
||||
|
||||
// run
|
||||
err := g.fetchJobs()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, wantJobs, g.jobs)
|
||||
}
|
||||
|
||||
func TestGitHubActionsConfigProvider_GetLog(t *testing.T) {
|
||||
// data
|
||||
respLogs := []string{
|
||||
"log_record11\nlog_record12\nlog_record13\n",
|
||||
"log_record21\nlog_record22\n",
|
||||
"log_record31\nlog_record32\n",
|
||||
"log_record41\n",
|
||||
}
|
||||
wantLogs := "log_record11\nlog_record12\nlog_record13\nlog_record21\n" +
|
||||
"log_record22\nlog_record31\nlog_record32\nlog_record41\n"
|
||||
jobs := []job{
|
||||
{ID: 111}, {ID: 222}, {ID: 333}, {ID: 444}, {ID: 555},
|
||||
}
|
||||
|
||||
// setup provider
|
||||
g := &GitHubActionsConfigProvider{
|
||||
client: piperHttp.Client{},
|
||||
jobs: jobs,
|
||||
jobsFetched: true,
|
||||
}
|
||||
g.client.SetOptions(piperHttp.ClientOptions{
|
||||
UseDefaultTransport: true, // need to use default transport for http mock
|
||||
MaxRetries: -1,
|
||||
})
|
||||
// setup http mock
|
||||
rand.Seed(time.Now().UnixNano())
|
||||
latencyMin, latencyMax := 15, 500 // milliseconds
|
||||
httpmock.Activate()
|
||||
defer httpmock.DeactivateAndReset()
|
||||
for i, j := range jobs {
|
||||
idx := i
|
||||
httpmock.RegisterResponder(
|
||||
http.MethodGet,
|
||||
fmt.Sprintf("https://api.github.com/repos/SAP/jenkins-library/actions/jobs/%d/logs", j.ID),
|
||||
func(req *http.Request) (*http.Response, error) {
|
||||
// simulate response delay
|
||||
latency := rand.Intn(latencyMax-latencyMin) + latencyMin
|
||||
time.Sleep(time.Duration(latency) * time.Millisecond)
|
||||
return httpmock.NewStringResponse(200, respLogs[idx]), nil
|
||||
},
|
||||
)
|
||||
}
|
||||
// setup env vars
|
||||
defer resetEnv(os.Environ())
|
||||
os.Clearenv()
|
||||
_ = os.Setenv("GITHUB_API_URL", "https://api.github.com")
|
||||
_ = os.Setenv("GITHUB_REPOSITORY", "SAP/jenkins-library")
|
||||
|
||||
// run
|
||||
logs, err := g.GetLog()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, wantLogs, string(logs))
|
||||
}
|
||||
|
||||
func TestGitHubActionsConfigProvider_Others(t *testing.T) {
|
||||
defer resetEnv(os.Environ())
|
||||
os.Clearenv()
|
||||
_ = os.Setenv("GITHUB_ACTION", "1")
|
||||
_ = os.Setenv("GITHUB_JOB", "Build")
|
||||
_ = os.Setenv("GITHUB_RUN_ID", "11111")
|
||||
_ = os.Setenv("GITHUB_REF_NAME", "main")
|
||||
_ = os.Setenv("GITHUB_HEAD_REF", "feature-branch-1")
|
||||
_ = os.Setenv("GITHUB_REF", "refs/pull/42/merge")
|
||||
_ = os.Setenv("GITHUB_WORKFLOW", "Piper workflow")
|
||||
_ = os.Setenv("GITHUB_SHA", "ffac537e6cbbf934b08745a378932722df287a53")
|
||||
_ = os.Setenv("GITHUB_API_URL", "https://api.github.com")
|
||||
_ = os.Setenv("GITHUB_SERVER_URL", "https://github.com")
|
||||
_ = os.Setenv("GITHUB_REPOSITORY", "SAP/jenkins-library")
|
||||
|
||||
p := GitHubActionsConfigProvider{}
|
||||
startedAt, _ := time.Parse(time.RFC3339, "2023-08-11T07:28:24Z")
|
||||
p.runData = run{
|
||||
fetched: true,
|
||||
Status: "",
|
||||
StartedAt: startedAt,
|
||||
}
|
||||
p.currentJob = job{ID: 111, Name: "job1", HtmlURL: "https://github.com/SAP/jenkins-library/actions/runs/123456/jobs/7654321"}
|
||||
|
||||
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/runs/123456/jobs/7654321", p.GetJobURL())
|
||||
assert.Equal(t, "Piper workflow", p.GetJobName())
|
||||
assert.Equal(t, "ffac537e6cbbf934b08745a378932722df287a53", p.GetCommit())
|
||||
assert.Equal(t, "https://api.github.com/repos/SAP/jenkins-library/actions", actionsURL())
|
||||
assert.True(t, p.IsPullRequest())
|
||||
assert.True(t, isGitHubActions())
|
||||
}
|
||||
|
@ -14,20 +14,17 @@ import (
|
||||
|
||||
type JenkinsConfigProvider struct {
|
||||
client piperHttp.Client
|
||||
options piperHttp.ClientOptions
|
||||
apiInformation map[string]interface{}
|
||||
}
|
||||
|
||||
// InitOrchestratorProvider initializes the Jenkins orchestrator with credentials
|
||||
func (j *JenkinsConfigProvider) InitOrchestratorProvider(settings *OrchestratorSettings) {
|
||||
j.client = piperHttp.Client{}
|
||||
j.options = piperHttp.ClientOptions{
|
||||
j.client.SetOptions(piperHttp.ClientOptions{
|
||||
Username: settings.JenkinsUser,
|
||||
Password: settings.JenkinsToken,
|
||||
MaxRetries: 3,
|
||||
TransportTimeout: time.Second * 10,
|
||||
}
|
||||
j.client.SetOptions(j.options)
|
||||
})
|
||||
log.Entry().Debug("Successfully initialized Jenkins config provider")
|
||||
}
|
||||
|
||||
@ -77,15 +74,15 @@ func (j *JenkinsConfigProvider) GetBuildStatus() string {
|
||||
// cases in ADO: succeeded, failed, canceled, none, partiallySucceeded
|
||||
switch result := val; result {
|
||||
case "SUCCESS":
|
||||
return "SUCCESS"
|
||||
return BuildStatusSuccess
|
||||
case "ABORTED":
|
||||
return "ABORTED"
|
||||
return BuildStatusAborted
|
||||
default:
|
||||
// FAILURE, NOT_BUILT
|
||||
return "FAILURE"
|
||||
return BuildStatusFailure
|
||||
}
|
||||
}
|
||||
return "FAILURE"
|
||||
return BuildStatusFailure
|
||||
}
|
||||
|
||||
// GetChangeSet returns the commitIds and timestamp of the changeSet of the current run
|
||||
@ -200,12 +197,12 @@ func (j *JenkinsConfigProvider) GetBuildReason() string {
|
||||
marshal, err := json.Marshal(j.apiInformation)
|
||||
if err != nil {
|
||||
log.Entry().WithError(err).Debugf("could not marshal apiInformation")
|
||||
return "Unknown"
|
||||
return BuildReasonUnknown
|
||||
}
|
||||
jsonParsed, err := gabs.ParseJSON(marshal)
|
||||
if err != nil {
|
||||
log.Entry().WithError(err).Debugf("could not parse apiInformation")
|
||||
return "Unknown"
|
||||
return BuildReasonUnknown
|
||||
}
|
||||
|
||||
for _, child := range jsonParsed.Path("actions").Children() {
|
||||
@ -217,21 +214,21 @@ func (j *JenkinsConfigProvider) GetBuildReason() string {
|
||||
for _, val := range child.Path("causes").Children() {
|
||||
subclass := val.S("_class")
|
||||
if subclass.Data().(string) == "hudson.model.Cause$UserIdCause" {
|
||||
return "Manual"
|
||||
return BuildReasonManual
|
||||
} else if subclass.Data().(string) == "hudson.triggers.TimerTrigger$TimerTriggerCause" {
|
||||
return "Schedule"
|
||||
return BuildReasonSchedule
|
||||
} else if subclass.Data().(string) == "jenkins.branch.BranchEventCause" {
|
||||
return "PullRequest"
|
||||
return BuildReasonPullRequest
|
||||
} else if subclass.Data().(string) == "org.jenkinsci.plugins.workflow.support.steps.build.BuildUpstreamCause" {
|
||||
return "ResourceTrigger"
|
||||
return BuildReasonResourceTrigger
|
||||
} else {
|
||||
return "Unknown"
|
||||
return BuildReasonUnknown
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return "Unknown"
|
||||
return BuildReasonUnknown
|
||||
}
|
||||
|
||||
// GetBranch returns the branch name, only works with the git plugin enabled
|
||||
|
@ -17,6 +17,20 @@ const (
|
||||
Jenkins
|
||||
)
|
||||
|
||||
const (
|
||||
BuildStatusSuccess = "SUCCESS"
|
||||
BuildStatusAborted = "ABORTED"
|
||||
BuildStatusFailure = "FAILURE"
|
||||
BuildStatusInProgress = "IN_PROGRESS"
|
||||
|
||||
BuildReasonManual = "Manual"
|
||||
BuildReasonSchedule = "Schedule"
|
||||
BuildReasonPullRequest = "PullRequest"
|
||||
BuildReasonResourceTrigger = "ResourceTrigger"
|
||||
BuildReasonIndividualCI = "IndividualCI"
|
||||
BuildReasonUnknown = "Unknown"
|
||||
)
|
||||
|
||||
type OrchestratorSpecificConfigProviding interface {
|
||||
InitOrchestratorProvider(settings *OrchestratorSettings)
|
||||
OrchestratorType() string
|
||||
@ -75,13 +89,13 @@ func NewOrchestratorSpecificConfigProvider() (OrchestratorSpecificConfigProvidin
|
||||
// DetectOrchestrator returns the name of the current orchestrator e.g. Jenkins, Azure, Unknown
|
||||
func DetectOrchestrator() Orchestrator {
|
||||
if isAzure() {
|
||||
return Orchestrator(AzureDevOps)
|
||||
return AzureDevOps
|
||||
} else if isGitHubActions() {
|
||||
return Orchestrator(GitHubActions)
|
||||
return GitHubActions
|
||||
} else if isJenkins() {
|
||||
return Orchestrator(Jenkins)
|
||||
return Jenkins
|
||||
} else {
|
||||
return Orchestrator(Unknown)
|
||||
return Unknown
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user