From 17a3d8c58e7135f1424faa0b895e62ce607a14f0 Mon Sep 17 00:00:00 2001 From: aliculPix4D Date: Wed, 18 Oct 2023 10:05:47 +0200 Subject: [PATCH] cogito: add support for configuring Github API endpoint - adds support for Github Enterprise API endpoints --- cmd/cogito/main.go | 5 +-- cmd/cogito/main_test.go | 11 +++-- cogito/ghcommitsink.go | 4 +- cogito/ghcommitsink_test.go | 4 +- cogito/protocol.go | 12 ++++-- cogito/protocol_test.go | 9 ++-- cogito/put.go | 4 +- cogito/put_test.go | 81 +++++++---------------------------- cogito/putter.go | 36 +++++----------- cogito/putter_private_test.go | 33 ++++++++------ testhelp/testhelper.go | 12 +++--- 11 files changed, 81 insertions(+), 130 deletions(-) diff --git a/cmd/cogito/main.go b/cmd/cogito/main.go index 972c12ca..c8403786 100644 --- a/cmd/cogito/main.go +++ b/cmd/cogito/main.go @@ -12,7 +12,6 @@ import ( "github.com/hashicorp/go-hclog" "github.com/Pix4D/cogito/cogito" - "github.com/Pix4D/cogito/github" "github.com/Pix4D/cogito/sets" ) @@ -56,8 +55,8 @@ func mainErr(in io.Reader, out io.Writer, logOut io.Writer, args []string) error case "in": return cogito.Get(log, input, out, args[1:]) case "out": - putter := cogito.NewPutter(github.API, log) - return cogito.Put(input, out, args[1:], putter) + putter := cogito.NewPutter(log) + return cogito.Put(log, input, out, args[1:], putter) default: return fmt.Errorf("cli wiring error; please report") } diff --git a/cmd/cogito/main_test.go b/cmd/cogito/main_test.go index 396d443b..68ca1709 100644 --- a/cmd/cogito/main_test.go +++ b/cmd/cogito/main_test.go @@ -67,6 +67,11 @@ func TestRunPutSuccess(t *testing.T) { chatReply := googlechat.MessageReply{} var gchatUrl *url.URL googleChatSpy := testhelp.SpyHttpServer(&chatMsg, chatReply, &gchatUrl, http.StatusOK) + gitHubSpyDomain, err := url.Parse(gitHubSpy.URL) + if err != nil { + t.Fatalf("error parsing SpyHttpServer URL: %s", err) + } + in := bytes.NewReader(testhelp.ToJSON(t, cogito.PutRequest{ Source: cogito.Source{ Owner: "the-owner", @@ -81,9 +86,9 @@ func TestRunPutSuccess(t *testing.T) { var out bytes.Buffer var logOut bytes.Buffer inputDir := testhelp.MakeGitRepoFromTestdata(t, "../../cogito/testdata/one-repo/a-repo", - testhelp.HttpsRemote("the-owner", "the-repo"), "dummySHA", wantGitRef) + testhelp.HttpsRemote(gitHubSpyDomain.Host, "the-owner", "the-repo"), "dummySHA", wantGitRef) - err := mainErr(in, &out, &logOut, []string{"out", inputDir}) + err = mainErr(in, &out, &logOut, []string{"out", inputDir}) assert.NilError(t, err, "\nout: %s\nlogOut: %s", out.String(), logOut.String()) // @@ -115,7 +120,7 @@ func TestRunPutSuccessIntegration(t *testing.T) { var out bytes.Buffer var logOut bytes.Buffer inputDir := testhelp.MakeGitRepoFromTestdata(t, "../../cogito/testdata/one-repo/a-repo", - testhelp.HttpsRemote(gitHubCfg.Owner, gitHubCfg.Repo), gitHubCfg.SHA, + testhelp.HttpsRemote("github.com", gitHubCfg.Owner, gitHubCfg.Repo), gitHubCfg.SHA, "ref: refs/heads/a-branch-FIXME") t.Setenv("BUILD_JOB_NAME", "TestRunPutSuccessIntegration") t.Setenv("ATC_EXTERNAL_URL", "https://cogito.invalid") diff --git a/cogito/ghcommitsink.go b/cogito/ghcommitsink.go index 1a6cea87..9ebd82b3 100644 --- a/cogito/ghcommitsink.go +++ b/cogito/ghcommitsink.go @@ -27,7 +27,6 @@ const ( // GitHubCommitStatusSink is an implementation of [Sinker] for the Cogito resource. type GitHubCommitStatusSink struct { Log hclog.Logger - GhAPI string GitRef string Request PutRequest } @@ -42,7 +41,7 @@ func (sink GitHubCommitStatusSink) Send() error { context := ghMakeContext(sink.Request) target := &github.Target{ - Server: sink.GhAPI, + Server: sink.Request.Source.GithubApiEndpoint, Retry: retry.Retry{ FirstDelay: retryFirstDelay, BackoffLimit: retryBackoffLimit, @@ -58,7 +57,6 @@ func (sink GitHubCommitStatusSink) Send() error { "state", ghState, "owner", sink.Request.Source.Owner, "repo", sink.Request.Source.Repo, "git-ref", sink.GitRef, "context", context, "buildURL", buildURL, "description", description) - if err := commitStatus.Add(sink.GitRef, ghState, buildURL, description); err != nil { return err } diff --git a/cogito/ghcommitsink_test.go b/cogito/ghcommitsink_test.go index f20de9b3..10ed0062 100644 --- a/cogito/ghcommitsink_test.go +++ b/cogito/ghcommitsink_test.go @@ -25,9 +25,9 @@ func TestSinkGitHubCommitStatusSendSuccess(t *testing.T) { ts := testhelp.SpyHttpServer(&ghReq, nil, &URL, http.StatusCreated) sink := cogito.GitHubCommitStatusSink{ Log: hclog.NewNullLogger(), - GhAPI: ts.URL, GitRef: wantGitRef, Request: cogito.PutRequest{ + Source: cogito.Source{GithubApiEndpoint: ts.URL}, Params: cogito.PutParams{State: wantState}, Env: cogito.Environment{BuildJobName: jobName}, }, @@ -50,9 +50,9 @@ func TestSinkGitHubCommitStatusSendFailure(t *testing.T) { defer ts.Close() sink := cogito.GitHubCommitStatusSink{ Log: hclog.NewNullLogger(), - GhAPI: ts.URL, GitRef: "deadbeefdeadbeef", Request: cogito.PutRequest{ + Source: cogito.Source{GithubApiEndpoint: ts.URL}, Params: cogito.PutParams{State: cogito.StatePending}, }, } diff --git a/cogito/protocol.go b/cogito/protocol.go index 48ab969d..3282bc78 100644 --- a/cogito/protocol.go +++ b/cogito/protocol.go @@ -11,6 +11,7 @@ import ( "os" "strings" + "github.com/Pix4D/cogito/github" "github.com/Pix4D/cogito/sets" ) @@ -165,6 +166,7 @@ type Source struct { // // Optional // + GithubApiEndpoint string `json:"github_api_endpoint"` GChatWebHook string `json:"gchat_webhook"` // SENSITIVE LogLevel string `json:"log_level"` LogUrl string `json:"log_url"` // DEPRECATED @@ -172,7 +174,6 @@ type Source struct { ChatAppendSummary bool `json:"chat_append_summary"` ChatNotifyOnStates []BuildState `json:"chat_notify_on_states"` Sinks []string `json:"sinks"` - GithubApiEndpoint string `json:"github_api_endpoint"` } // String renders Source, redacting the sensitive fields. @@ -181,6 +182,7 @@ func (src Source) String() string { fmt.Fprintf(&bld, "owner: %s\n", src.Owner) fmt.Fprintf(&bld, "repo: %s\n", src.Repo) + fmt.Fprintf(&bld, "github_api_endpoint: %s\n", src.GithubApiEndpoint) fmt.Fprintf(&bld, "access_token: %s\n", redact(src.AccessToken)) fmt.Fprintf(&bld, "gchat_webhook: %s\n", redact(src.GChatWebHook)) fmt.Fprintf(&bld, "log_level: %s\n", src.LogLevel) @@ -188,8 +190,7 @@ func (src Source) String() string { fmt.Fprintf(&bld, "chat_append_summary: %t\n", src.ChatAppendSummary) fmt.Fprintf(&bld, "chat_notify_on_states: %s\n", src.ChatNotifyOnStates) // Last one: no newline. - fmt.Fprintf(&bld, "sinks: %s\n", src.Sinks) - fmt.Fprintf(&bld, "github_api_endpoint: %s", src.GithubApiEndpoint) + fmt.Fprintf(&bld, "sinks: %s", src.Sinks) return bld.String() } @@ -257,7 +258,9 @@ func (src *Source) Validate() error { return fmt.Errorf("source: missing keys: %s", strings.Join(mandatory, ", ")) } + // // Validate optional fields. + // if src.GithubApiEndpoint != "" { u, err := url.ParseRequestURI(src.GithubApiEndpoint) if err != nil || u.Host == "" { @@ -274,6 +277,9 @@ func (src *Source) Validate() error { if len(src.ChatNotifyOnStates) == 0 { src.ChatNotifyOnStates = defaultNotifyStates } + if len(src.GithubApiEndpoint) == 0 { + src.GithubApiEndpoint = github.API + } return nil } diff --git a/cogito/protocol_test.go b/cogito/protocol_test.go index 304b62ff..0b96ccd5 100644 --- a/cogito/protocol_test.go +++ b/cogito/protocol_test.go @@ -213,6 +213,7 @@ func TestSourcePrintLogRedaction(t *testing.T) { source := cogito.Source{ Owner: "the-owner", Repo: "the-repo", + GithubApiEndpoint: "dummy-api", AccessToken: "sensitive-the-access-token", GChatWebHook: "sensitive-gchat-webhook", LogLevel: "debug", @@ -224,14 +225,14 @@ func TestSourcePrintLogRedaction(t *testing.T) { t.Run("fmt.Print redacts fields", func(t *testing.T) { want := `owner: the-owner repo: the-repo +github_api_endpoint: dummy-api access_token: ***REDACTED*** gchat_webhook: ***REDACTED*** log_level: debug context_prefix: the-prefix chat_append_summary: true chat_notify_on_states: [success failure] -sinks: [] -github_api_endpoint: ` +sinks: []` have := fmt.Sprint(source) @@ -244,14 +245,14 @@ github_api_endpoint: ` } want := `owner: the-owner repo: +github_api_endpoint: access_token: gchat_webhook: log_level: context_prefix: chat_append_summary: false chat_notify_on_states: [] -sinks: [] -github_api_endpoint: ` +sinks: []` have := fmt.Sprint(input) diff --git a/cogito/put.go b/cogito/put.go index 5060ca72..6ca058c0 100644 --- a/cogito/put.go +++ b/cogito/put.go @@ -4,6 +4,8 @@ import ( "fmt" "io" "strings" + + "github.com/hashicorp/go-hclog" ) // Putter represents the put step of a Concourse resource. @@ -38,7 +40,7 @@ type Sinker interface { // Additionally, the script may emit metadata as a list of key-value pairs. This data is // intended for public consumption and will make it upstream, intended to be shown on the // build's page. -func Put(input []byte, out io.Writer, args []string, putter Putter) error { +func Put(log hclog.Logger, input []byte, out io.Writer, args []string, putter Putter) error { if err := putter.LoadConfiguration(input, args); err != nil { return fmt.Errorf("put: %s", err) } diff --git a/cogito/put_test.go b/cogito/put_test.go index dd222d8b..f54488e5 100644 --- a/cogito/put_test.go +++ b/cogito/put_test.go @@ -3,7 +3,6 @@ package cogito_test import ( "errors" "fmt" - "github.com/Pix4D/cogito/github" "io" "path/filepath" "testing" @@ -65,7 +64,7 @@ func (ms MockSinker) Send() error { func TestPutSuccess(t *testing.T) { putter := MockPutter{sinkers: []cogito.Sinker{MockSinker{}}} - err := cogito.Put(nil, nil, nil, putter) + err := cogito.Put(hclog.NewNullLogger(), nil, nil, nil, putter) assert.NilError(t, err) } @@ -78,7 +77,7 @@ func TestPutFailure(t *testing.T) { } test := func(t *testing.T, tc testCase) { - err := cogito.Put(nil, nil, nil, tc.putter) + err := cogito.Put(hclog.NewNullLogger(), nil, nil, nil, tc.putter) assert.ErrorContains(t, err, tc.wantErr) } @@ -124,7 +123,7 @@ func TestPutFailure(t *testing.T) { func TestPutterLoadConfigurationSuccess(t *testing.T) { in := testhelp.ToJSON(t, basePutRequest) - putter := cogito.NewPutter("dummy-API", hclog.NewNullLogger()) + putter := cogito.NewPutter(hclog.NewNullLogger()) err := putter.LoadConfiguration(in, []string{"dummy-dir"}) @@ -143,7 +142,7 @@ func TestPutterLoadConfigurationSinksOverrideSuccess(t *testing.T) { }, "params": {"sinks": ["gchat"]} }`) - putter := cogito.NewPutter("dummy-API", hclog.NewNullLogger()) + putter := cogito.NewPutter(hclog.NewNullLogger()) inputDir := []string{""} err := putter.LoadConfiguration(in, inputDir) assert.NilError(t, err) @@ -154,22 +153,6 @@ func TestPutterLoadConfigurationSinksOverrideSuccess(t *testing.T) { assert.NilError(t, err) } -func TestPutterLoadConfigurationGhApiEndpointOverrideSuccess(t *testing.T) { - in := []byte(` - { - "source": { - "owner": "the-owner", - "repo": "the-repo", - "access_token": "the-token", - "github_api_endpoint": "https://ghe.company.com" - } - }`) - putter := cogito.NewPutter("dummy-API", hclog.NewNullLogger()) - inputDir := []string{""} - err := putter.LoadConfiguration(in, inputDir) - assert.NilError(t, err) -} - func TestPutterLoadConfigurationFailure(t *testing.T) { type testCase struct { name string @@ -180,7 +163,7 @@ func TestPutterLoadConfigurationFailure(t *testing.T) { test := func(t *testing.T, tc testCase) { in := testhelp.ToJSON(t, tc.putInput) - putter := cogito.NewPutter("dummy-API", hclog.NewNullLogger()) + putter := cogito.NewPutter(hclog.NewNullLogger()) err := putter.LoadConfiguration(in, tc.args) @@ -207,20 +190,6 @@ func TestPutterLoadConfigurationFailure(t *testing.T) { args: []string{}, wantErr: "put: concourse resource protocol violation: missing input directory", }, - { - name: "invalid GH endpoint url in source", - putInput: cogito.PutRequest{ - Source: cogito.Source{ - Owner: "owner", - Repo: "repo", - AccessToken: "token", - GithubApiEndpoint: "invalid-api-endpoint", - }, - Params: cogito.PutParams{State: cogito.StateSuccess}, - }, - args: []string{}, - wantErr: "put: source: github_api_endpoint 'invalid-api-endpoint' is an invalid api endpoint", - }, } for _, tc := range testCases { @@ -235,7 +204,7 @@ func TestPutterLoadConfigurationInvalidParamsFailure(t *testing.T) { "params": {"pizza": "margherita"} }`) wantErr := `put: parsing request: json: unknown field "pizza"` - putter := cogito.NewPutter("dummy-API", hclog.NewNullLogger()) + putter := cogito.NewPutter(hclog.NewNullLogger()) err := putter.LoadConfiguration(in, nil) @@ -249,7 +218,7 @@ func TestPutterLoadConfigurationMissingGchatwebHook(t *testing.T) { "params": {} }`) wantErr := `put: source: missing keys: gchat_webhook` - putter := cogito.NewPutter("dummy-API", hclog.NewNullLogger()) + putter := cogito.NewPutter(hclog.NewNullLogger()) err := putter.LoadConfiguration(in, nil) @@ -263,7 +232,7 @@ func TestPutterLoadConfigurationUnknownSink(t *testing.T) { "params": {} }`) wantErr := `put: source: invalid sink(s): [pizza]` - putter := cogito.NewPutter("dummy-API", hclog.NewNullLogger()) + putter := cogito.NewPutter(hclog.NewNullLogger()) err := putter.LoadConfiguration(in, nil) @@ -277,7 +246,7 @@ func TestPutterLoadConfigurationUnknownSinkPutParams(t *testing.T) { "params": {"sinks": ["pizza"]} }`) wantErr := `put: arguments: unsupported sink(s): [pizza]` - putter := cogito.NewPutter("dummy-API", hclog.NewNullLogger()) + putter := cogito.NewPutter(hclog.NewNullLogger()) err := putter.LoadConfiguration(in, nil) @@ -293,7 +262,7 @@ func TestPutterProcessInputDirSuccess(t *testing.T) { } test := func(t *testing.T, tc testCase) { - putter := cogito.NewPutter("dummy-API", hclog.NewNullLogger()) + putter := cogito.NewPutter(hclog.NewNullLogger()) tmpDir := testhelp.MakeGitRepoFromTestdata(t, tc.inputDir, "https://github.com/dummy-owner/dummy-repo", "dummySHA", "banana") putter.InputDir = filepath.Join(tmpDir, filepath.Base(tc.inputDir)) @@ -303,7 +272,6 @@ func TestPutterProcessInputDirSuccess(t *testing.T) { } err := putter.ProcessInputDir() - assert.NilError(t, err) } @@ -348,7 +316,7 @@ func TestPutterProcessInputDirFailure(t *testing.T) { test := func(t *testing.T, tc testCase) { tmpDir := testhelp.MakeGitRepoFromTestdata(t, tc.inputDir, "https://github.com/dummy-owner/dummy-repo", "dummySHA", "banana mango") - putter := cogito.NewPutter("dummy-api", hclog.NewNullLogger()) + putter := cogito.NewPutter(hclog.NewNullLogger()) putter.Request = cogito.PutRequest{ Source: cogito.Source{Owner: "dummy-owner", Repo: "dummy-repo"}, Params: tc.params, @@ -425,7 +393,7 @@ func TestPutterProcessInputDirNonExisting(t *testing.T) { } func TestPutterSinks(t *testing.T) { - putter := cogito.NewPutter("dummy-API", hclog.NewNullLogger()) + putter := cogito.NewPutter(hclog.NewNullLogger()) sinks := putter.Sinks() assert.Assert(t, len(sinks) == 2) @@ -436,27 +404,8 @@ func TestPutterSinks(t *testing.T) { assert.Assert(t, ok2) } -func TestGitHubCommitStatusSinkApiEndpointOverrideFromSource(t *testing.T) { - // default case - defaultApiEndpoint := github.API - defaultPutter := cogito.NewPutter(defaultApiEndpoint, hclog.NewNullLogger()) - sinks := defaultPutter.Sinks() - ghSink := sinks[1].(cogito.GitHubCommitStatusSink) - assert.Assert(t, ghSink.GhAPI == defaultApiEndpoint) - - // override - customEndpointPutter := cogito.NewPutter(defaultApiEndpoint, hclog.NewNullLogger()) - customEndpoint := "https://ghe.company.com" - customEndpointPutter.Request = cogito.PutRequest{ - Source: cogito.Source{GithubApiEndpoint: customEndpoint}, - } - customPutterSinks := customEndpointPutter.Sinks() - customPutterGhSink := customPutterSinks[1].(cogito.GitHubCommitStatusSink) - assert.Assert(t, customPutterGhSink.GhAPI == customEndpoint) -} - func TestPutterCustomSinks(t *testing.T) { - putter := cogito.NewPutter("dummy-api", hclog.NewNullLogger()) + putter := cogito.NewPutter(hclog.NewNullLogger()) putter.Request = cogito.PutRequest{ Params: cogito.PutParams{Sinks: []string{"gchat"}}, } @@ -467,7 +416,7 @@ func TestPutterCustomSinks(t *testing.T) { } func TestPutterOutputSuccess(t *testing.T) { - putter := cogito.NewPutter("dummy-API", hclog.NewNullLogger()) + putter := cogito.NewPutter(hclog.NewNullLogger()) err := putter.Output(io.Discard) @@ -475,7 +424,7 @@ func TestPutterOutputSuccess(t *testing.T) { } func TestPutterOutputFailure(t *testing.T) { - putter := cogito.NewPutter("dummy-API", hclog.NewNullLogger()) + putter := cogito.NewPutter(hclog.NewNullLogger()) err := putter.Output(&testhelp.FailingWriter{}) diff --git a/cogito/putter.go b/cogito/putter.go index b6adb7e0..99cd586f 100644 --- a/cogito/putter.go +++ b/cogito/putter.go @@ -23,16 +23,14 @@ type ProdPutter struct { Request PutRequest InputDir string // Cogito specific fields. - ghAPI string log hclog.Logger gitRef string } // NewPutter returns a Cogito ProdPutter. -func NewPutter(ghAPI string, log hclog.Logger) *ProdPutter { +func NewPutter(log hclog.Logger) *ProdPutter { return &ProdPutter{ - ghAPI: ghAPI, - log: log, + log: log, } } @@ -133,7 +131,7 @@ func (putter *ProdPutter) ProcessInputDir() error { case 1: repoDir := filepath.Join(putter.InputDir, inputDirs.OrderedList()[0]) putter.log.Debug("", "inputDirs", inputDirs, "repoDir", repoDir, "msgDir", msgDir) - if err := checkGitRepoDir(repoDir, source.Owner, source.Repo); err != nil { + if err := checkGitRepoDir(repoDir, source.GithubApiEndpoint, source.Owner, source.Repo); err != nil { return err } putter.gitRef, err = getGitCommit(repoDir) @@ -152,12 +150,9 @@ func (putter *ProdPutter) ProcessInputDir() error { } func (putter *ProdPutter) Sinks() []Sinker { - source := putter.Request.Source - ghApiEndpoint := getEndpointFromSourceOrDefault(putter, source) supportedSinkers := map[string]Sinker{ "github": GitHubCommitStatusSink{ Log: putter.log.Named("ghCommitStatus"), - GhAPI: ghApiEndpoint, GitRef: putter.gitRef, Request: putter.Request, }, @@ -169,9 +164,9 @@ func (putter *ProdPutter) Sinks() []Sinker { Request: putter.Request, }, } - sourceSinks := source.Sinks + source := putter.Request.Source.Sinks params := putter.Request.Params.Sinks - sinks, _ := MergeAndValidateSinks(sourceSinks, params) + sinks, _ := MergeAndValidateSinks(source, params) sinkers := make([]Sinker, 0, sinks.Size()) for _, s := range sinks.OrderedList() { @@ -181,15 +176,6 @@ func (putter *ProdPutter) Sinks() []Sinker { return sinkers } -func getEndpointFromSourceOrDefault(putter *ProdPutter, source Source) string { - if source.GithubApiEndpoint != "" { - return source.GithubApiEndpoint - } else { - // the default - return putter.ghAPI - } -} - func (putter *ProdPutter) Output(out io.Writer) error { // Following the protocol for put, we return the version and metadata. // For Cogito, the metadata contains the Concourse build state. @@ -251,7 +237,7 @@ func collectInputDirs(dir string) ([]string, error) { // - The repo configuration contains a "remote origin" section. // - The remote origin url can be parsed following the GitHub conventions. // - The result of the parse matches OWNER and REPO. -func checkGitRepoDir(dir, owner, repo string) error { +func checkGitRepoDir(dir, endpoint, owner, repo string) error { cfg, err := mini.LoadConfiguration(filepath.Join(dir, ".git/config")) if err != nil { return fmt.Errorf("parsing .git/config: %w", err) @@ -273,7 +259,6 @@ func checkGitRepoDir(dir, owner, repo string) error { if err != nil { return fmt.Errorf(".git/config: remote: %w", err) } - left := []string{owner, repo} right := []string{gu.Owner, gu.Repo} for i, l := range left { @@ -282,15 +267,16 @@ func checkGitRepoDir(dir, owner, repo string) error { return fmt.Errorf(`the received git repository is incompatible with the Cogito configuration. Git repository configuration (received as 'inputs:' in this PUT step): - url: %s + url: %s owner: %s - repo: %s + repo: %s Cogito SOURCE configuration: + github_api_endpoint: %s owner: %s - repo: %s`, + repo: %s`, gitUrl, gu.Owner, gu.Repo, - owner, repo) + endpoint, owner, repo) } } return nil diff --git a/cogito/putter_private_test.go b/cogito/putter_private_test.go index 36991f6b..cbd68059 100644 --- a/cogito/putter_private_test.go +++ b/cogito/putter_private_test.go @@ -2,6 +2,7 @@ package cogito import ( "errors" + "fmt" "net/url" "os" "path/filepath" @@ -10,6 +11,7 @@ import ( "github.com/google/go-cmp/cmp" "gotest.tools/v3/assert" + "github.com/Pix4D/cogito/github" "github.com/Pix4D/cogito/testhelp" ) @@ -65,6 +67,7 @@ func TestCheckGitRepoDirSuccess(t *testing.T) { repoURL string } + const wantDomain = "github.com" const wantOwner = "smiling" const wantRepo = "butterfly" @@ -73,7 +76,7 @@ func TestCheckGitRepoDirSuccess(t *testing.T) { "dummySHA", "dummyHead") err := checkGitRepoDir(filepath.Join(inputDir, filepath.Base(tc.dir)), - wantOwner, wantRepo) + github.API, wantOwner, wantRepo) assert.NilError(t, err) } @@ -82,22 +85,22 @@ func TestCheckGitRepoDirSuccess(t *testing.T) { { name: "repo with good SSH remote", dir: "testdata/one-repo/a-repo", - repoURL: testhelp.SshRemote(wantOwner, wantRepo), + repoURL: testhelp.SshRemote(wantDomain, wantOwner, wantRepo), }, { name: "repo with good HTTPS remote", dir: "testdata/one-repo/a-repo", - repoURL: testhelp.HttpsRemote(wantOwner, wantRepo), + repoURL: testhelp.HttpsRemote(wantDomain, wantOwner, wantRepo), }, { name: "repo with good HTTP remote", dir: "testdata/one-repo/a-repo", - repoURL: testhelp.HttpRemote(wantOwner, wantRepo), + repoURL: testhelp.HttpRemote(wantDomain, wantOwner, wantRepo), }, { name: "PR resource but with basic auth in URL (see PR #46)", dir: "testdata/one-repo/a-repo", - repoURL: "https://x-oauth-basic:ghp_XXX@github.com/smiling/butterfly.git", + repoURL: fmt.Sprintf("https://x-oauth-basic:ghp_XXX@%s/%s/%s.git", wantDomain, wantOwner, wantRepo), }, } @@ -122,7 +125,7 @@ func TestCheckGitRepoDirFailure(t *testing.T) { "dummySHA", "dummyHead") err := checkGitRepoDir(filepath.Join(inDir, filepath.Base(tc.dir)), - wantOwner, wantRepo) + github.API, wantOwner, wantRepo) assert.ErrorContains(t, err, tc.wantErrWild) } @@ -143,32 +146,34 @@ func TestCheckGitRepoDirFailure(t *testing.T) { { name: "repo with unrelated HTTPS remote", dir: "testdata/one-repo/a-repo", - repoURL: testhelp.HttpsRemote("owner-a", "repo-a"), + repoURL: testhelp.HttpsRemote("github.com", "owner-a", "repo-a"), wantErrWild: `the received git repository is incompatible with the Cogito configuration. Git repository configuration (received as 'inputs:' in this PUT step): - url: https://github.com/owner-a/repo-a.git + url: https://github.com/owner-a/repo-a.git owner: owner-a - repo: repo-a + repo: repo-a Cogito SOURCE configuration: + github_api_endpoint: https://api.github.com owner: smiling - repo: butterfly`, + repo: butterfly`, }, { name: "repo with unrelated SSH remote or wrong source config", dir: "testdata/one-repo/a-repo", - repoURL: testhelp.SshRemote("owner-a", "repo-a"), + repoURL: testhelp.SshRemote("github.com", "owner-a", "repo-a"), wantErrWild: `the received git repository is incompatible with the Cogito configuration. Git repository configuration (received as 'inputs:' in this PUT step): - url: git@github.com:owner-a/repo-a.git + url: git@github.com:owner-a/repo-a.git owner: owner-a - repo: repo-a + repo: repo-a Cogito SOURCE configuration: + github_api_endpoint: https://api.github.com owner: smiling - repo: butterfly`, + repo: butterfly`, }, { name: "invalid git pseudo URL in .git/config", diff --git a/testhelp/testhelper.go b/testhelp/testhelper.go index 4849558a..a5cc70f8 100644 --- a/testhelp/testhelper.go +++ b/testhelp/testhelper.go @@ -247,18 +247,18 @@ func MakeGitRepoFromTestdata( } // SshRemote returns a GitHub SSH URL -func SshRemote(owner, repo string) string { - return fmt.Sprintf("git@github.com:%s/%s.git", owner, repo) +func SshRemote(domain, owner, repo string) string { + return fmt.Sprintf("git@%s:%s/%s.git", domain, owner, repo) } // HttpsRemote returns a GitHub HTTPS URL -func HttpsRemote(owner, repo string) string { - return fmt.Sprintf("https://github.com/%s/%s.git", owner, repo) +func HttpsRemote(domain, owner, repo string) string { + return fmt.Sprintf("https://%s/%s/%s.git", domain, owner, repo) } // HttpRemote returns a GitHub HTTP URL -func HttpRemote(owner, repo string) string { - return fmt.Sprintf("http://github.com/%s/%s.git", owner, repo) +func HttpRemote(domain, owner, repo string) string { + return fmt.Sprintf("http://%s/%s/%s.git", domain, owner, repo) } // ToJSON returns the JSON encoding of thing.