diff --git a/cmd/cogito/main.go b/cmd/cogito/main.go index 972c12ca..55005b3a 100644 --- a/cmd/cogito/main.go +++ b/cmd/cogito/main.go @@ -50,14 +50,21 @@ func mainErr(in io.Reader, out io.Writer, logOut io.Writer, args []string) error }) log.Info(cogito.BuildInfo()) + ghAPI := os.Getenv("COGITO_GITHUB_API") + if ghAPI != "" { + log.Info("endpoint override", "COGITO_GITHUB_API", ghAPI) + } else { + ghAPI = github.API + } + switch cmd { case "check": return cogito.Check(log, input, out, args[1:]) 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(ghAPI, 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..5a259560 100644 --- a/cmd/cogito/main_test.go +++ b/cmd/cogito/main_test.go @@ -69,12 +69,11 @@ func TestRunPutSuccess(t *testing.T) { googleChatSpy := testhelp.SpyHttpServer(&chatMsg, chatReply, &gchatUrl, http.StatusOK) in := bytes.NewReader(testhelp.ToJSON(t, cogito.PutRequest{ Source: cogito.Source{ - Owner: "the-owner", - Repo: "the-repo", - AccessToken: "the-secret", - GithubApiEndpoint: gitHubSpy.URL, - GChatWebHook: googleChatSpy.URL, - LogLevel: "debug", + Owner: "the-owner", + Repo: "the-repo", + AccessToken: "the-secret", + GChatWebHook: googleChatSpy.URL, + LogLevel: "debug", }, Params: cogito.PutParams{State: wantState}, })) @@ -82,6 +81,7 @@ func TestRunPutSuccess(t *testing.T) { var logOut bytes.Buffer inputDir := testhelp.MakeGitRepoFromTestdata(t, "../../cogito/testdata/one-repo/a-repo", testhelp.HttpsRemote("the-owner", "the-repo"), "dummySHA", wantGitRef) + t.Setenv("COGITO_GITHUB_API", gitHubSpy.URL) err := mainErr(in, &out, &logOut, []string{"out", inputDir}) diff --git a/cogito/ghcommitsink.go b/cogito/ghcommitsink.go index 1a6cea87..3d86acf3 100644 --- a/cogito/ghcommitsink.go +++ b/cogito/ghcommitsink.go @@ -58,7 +58,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/protocol.go b/cogito/protocol.go index 48ab969d..ac0b2d95 100644 --- a/cogito/protocol.go +++ b/cogito/protocol.go @@ -7,7 +7,6 @@ import ( "bytes" "encoding/json" "fmt" - "net/url" "os" "strings" @@ -172,7 +171,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. @@ -188,8 +186,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,13 +254,10 @@ 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 == "" { - return fmt.Errorf("source: github_api_endpoint '%s' is an invalid api endpoint", src.GithubApiEndpoint) - } - } + // + // In this case, nothing to validate. // // Apply defaults. diff --git a/cogito/protocol_test.go b/cogito/protocol_test.go index 304b62ff..508910ac 100644 --- a/cogito/protocol_test.go +++ b/cogito/protocol_test.go @@ -46,14 +46,6 @@ func TestSourceValidationSuccess(t *testing.T) { return source }, }, - { - name: "optional git source github_api_endpoint", - mkSource: func() cogito.Source { - source := baseGithubSource - source.GithubApiEndpoint = "https://github.coffee.com/api/v3" - return source - }, - }, } for _, tc := range testCases { @@ -110,36 +102,6 @@ func TestSourceValidationFailure(t *testing.T) { }, wantErr: "source: invalid sink(s): [closed coffee shop]", }, - { - name: "no protocol prefix in git source github_api_endpoint", - source: cogito.Source{ - Owner: "the-owner", - Repo: "the-repo", - AccessToken: "the-token", - GithubApiEndpoint: "github.coffee.com/api/v3", - }, - wantErr: "source: github_api_endpoint 'github.coffee.com/api/v3' is an invalid api endpoint", - }, - { - name: "invalid http protocol prefix in git source github_api_endpoint", - source: cogito.Source{ - Owner: "the-owner", - Repo: "the-repo", - AccessToken: "the-token", - GithubApiEndpoint: "https:github.coffee.com/api/v3", - }, - wantErr: "source: github_api_endpoint 'https:github.coffee.com/api/v3' is an invalid api endpoint", - }, - { - name: "invalid http protocol prefix in git source github_api_endpoint", - source: cogito.Source{ - Owner: "the-owner", - Repo: "the-repo", - AccessToken: "the-token", - GithubApiEndpoint: "john.smith.cim", - }, - wantErr: "source: github_api_endpoint 'john.smith.cim' is an invalid api endpoint", - }, } for _, tc := range testCases { @@ -230,8 +192,7 @@ 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) @@ -250,8 +211,7 @@ 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..23508b9d 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) } @@ -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 @@ -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 { @@ -436,25 +405,6 @@ 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.Request = cogito.PutRequest{ diff --git a/cogito/putter.go b/cogito/putter.go index b6adb7e0..ad9ef048 100644 --- a/cogito/putter.go +++ b/cogito/putter.go @@ -152,12 +152,10 @@ 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, + GhAPI: putter.ghAPI, GitRef: putter.gitRef, Request: putter.Request, }, @@ -169,9 +167,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 +179,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. @@ -273,9 +262,8 @@ 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} + left := []string{"github.com", owner, repo} + right := []string{gu.URL.Host, gu.Owner, gu.Repo} for i, l := range left { r := right[i] if !strings.EqualFold(l, r) {