1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2024-12-14 11:03:09 +02:00
sap-jenkins-library/pkg/orchestrator/gitHubActions_test.go
Googlom e805beda70
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>
2023-08-29 09:32:35 +02:00

345 lines
11 KiB
Go

//go:build unit
// +build unit
package orchestrator
import (
"fmt"
"math/rand"
"net/http"
"os"
"testing"
"time"
piperHttp "github.com/SAP/jenkins-library/pkg/http"
"github.com/jarcoal/httpmock"
"github.com/stretchr/testify/assert"
)
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())
}