Skip to content

Commit

Permalink
Update captain to use cloud host (#63)
Browse files Browse the repository at this point in the history
  • Loading branch information
tonywok authored Jan 9, 2024
1 parent 669f3a4 commit c0b87a4
Show file tree
Hide file tree
Showing 9 changed files with 198 additions and 12 deletions.
14 changes: 12 additions & 2 deletions internal/backend/remote/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func (c Client) GetTestTimingManifest(
ctx context.Context,
testSuiteIdentifier string,
) ([]testing.TestFileTiming, error) {
endpoint := "/api/test_suites/timing_manifest"
endpoint := hostEndpointCompat(c, "/api/test_suites/timing_manifest")

req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
if err != nil {
Expand Down Expand Up @@ -177,7 +177,7 @@ func (c Client) GetRunConfiguration(
ctx context.Context,
testSuiteIdentifier string,
) (backend.RunConfiguration, error) {
endpoint := "/api/test_suites/run_configuration"
endpoint := hostEndpointCompat(c, "/api/test_suites/run_configuration")

req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
if err != nil {
Expand Down Expand Up @@ -214,3 +214,13 @@ func (c Client) GetRunConfiguration(

return runConfiguration, nil
}

// TODO(TS): Remove this once we're no longer testing against versions that use captain.build
func hostEndpointCompat(c Client, endpoint string) string {
remoteHost := c.ClientConfig.Host

if !strings.Contains(remoteHost, "cloud") {
return endpoint
}
return "/captain" + endpoint
}
2 changes: 1 addition & 1 deletion internal/backend/remote/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package remote
import "regexp"

const (
defaultHost = "captain.build"
defaultHost = "cloud.rwx.com"

contentTypeJSON = "application/json"
headerContentType = "Content-Type"
Expand Down
40 changes: 38 additions & 2 deletions internal/backend/remote/get_run_configuration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,55 @@ var _ = Describe("GetRunConfiguration", func() {
var (
apiClient remote.Client
mockRoundTripper func(*http.Request) (*http.Response, error)
host string
)

JustBeforeEach(func() {
apiClientConfig := remote.ClientConfig{Log: zap.NewNop().Sugar()}
apiClientConfig := remote.ClientConfig{Log: zap.NewNop().Sugar(), Host: host}
apiClient = remote.Client{ClientConfig: apiClientConfig, RoundTrip: mockRoundTripper}
})

Context("when the response is successful against captain.build", func() {
BeforeEach(func() {
host = "captain.build"
mockRoundTripper = func(req *http.Request) (*http.Response, error) {
var resp http.Response

Expect(req.Method).To(Equal(http.MethodGet))
Expect(req.URL.Path).To(HaveSuffix("/api/test_suites/run_configuration"))
Expect(req.URL.Query().Has("test_suite_identifier")).To(BeTrue())

resp.Body = io.NopCloser(strings.NewReader(`
{
"generated_at": "some-time",
"quarantined_tests": [{"composite_identifier": "q-1"}],
"flaky_tests": [{"composite_identifier": "f-1"}]
}
`))
resp.StatusCode = 200

return &resp, nil
}
})

It("returns the run configuration", func() {
runConfiguration, err := apiClient.GetRunConfiguration(context.Background(), "test-suite-id")
Expect(err).NotTo(HaveOccurred())
Expect(runConfiguration.QuarantinedTests).To(HaveLen(1))
Expect(runConfiguration.QuarantinedTests[0].CompositeIdentifier).To(Equal("q-1"))
Expect(runConfiguration.FlakyTests).To(HaveLen(1))
Expect(runConfiguration.FlakyTests[0].CompositeIdentifier).To(Equal("f-1"))
})
})

Context("when the response is successful", func() {
BeforeEach(func() {
host = "cloud.rwx.com"
mockRoundTripper = func(req *http.Request) (*http.Response, error) {
var resp http.Response

Expect(req.Method).To(Equal(http.MethodGet))
Expect(req.URL.Path).To(HaveSuffix("run_configuration"))
Expect(req.URL.Path).To(HaveSuffix("/captain/api/test_suites/run_configuration"))
Expect(req.URL.Query().Has("test_suite_identifier")).To(BeTrue())

resp.Body = io.NopCloser(strings.NewReader(`
Expand Down Expand Up @@ -59,6 +94,7 @@ var _ = Describe("GetRunConfiguration", func() {

Context("when the response is not successful", func() {
BeforeEach(func() {
host = "cloud.rwx.com"
mockRoundTripper = func(req *http.Request) (*http.Response, error) {
var resp http.Response

Expand Down
88 changes: 88 additions & 0 deletions internal/backend/remote/get_test_timing_manifest_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package remote_test

import (
"context"
"io"
"net/http"
"strings"

"go.uber.org/zap"

"github.com/rwx-research/captain-cli/internal/backend/remote"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var _ = Describe("GetTestTimingManifest", func() {
var (
apiClient remote.Client
mockRoundTripper func(*http.Request) (*http.Response, error)
host string
)

JustBeforeEach(func() {
apiClientConfig := remote.ClientConfig{Log: zap.NewNop().Sugar(), Host: host}
apiClient = remote.Client{ClientConfig: apiClientConfig, RoundTrip: mockRoundTripper}
})

Context("when the response is successful against captain.build", func() {
BeforeEach(func() {
host = "captain.build"
mockRoundTripper = func(req *http.Request) (*http.Response, error) {
var resp http.Response

Expect(req.Method).To(Equal(http.MethodGet))
Expect(req.URL.Path).To(HaveSuffix("/api/test_suites/timing_manifest"))
Expect(req.URL.Query().Has("test_suite_identifier")).To(BeTrue())
Expect(req.URL.Query().Has("commit_sha")).To(BeTrue())

resp.Body = io.NopCloser(strings.NewReader(`
{
"file_timings": [
{ "file_path": "some-file", "duration": 200 }
]
}
`))
resp.StatusCode = 200
return &resp, nil
}
})

It("returns the test file timing", func() {
testFileTiming, err := apiClient.GetTestTimingManifest(context.Background(), "test-suite-id")
Expect(err).NotTo(HaveOccurred())
Expect(testFileTiming).To(HaveLen(1))
})
})

Context("when the response is successful", func() {
BeforeEach(func() {
host = "cloud.rwx.com"
mockRoundTripper = func(req *http.Request) (*http.Response, error) {
var resp http.Response

Expect(req.Method).To(Equal(http.MethodGet))
Expect(req.URL.Path).To(HaveSuffix("/captain/api/test_suites/timing_manifest"))
Expect(req.URL.Query().Has("test_suite_identifier")).To(BeTrue())
Expect(req.URL.Query().Has("commit_sha")).To(BeTrue())

resp.Body = io.NopCloser(strings.NewReader(`
{
"file_timings": [
{ "file_path": "some-file", "duration": 200 }
]
}
`))
resp.StatusCode = 200
return &resp, nil
}
})

It("returns the test file timing", func() {
testFileTiming, err := apiClient.GetTestTimingManifest(context.Background(), "test-suite-id")
Expect(err).NotTo(HaveOccurred())
Expect(testFileTiming).To(HaveLen(1))
})
})
})
4 changes: 2 additions & 2 deletions internal/backend/remote/update_test_results.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ func (c Client) registerTestResults(
testSuite string,
testResultsFiles []TestResultsFile,
) ([]TestResultsFile, error) {
endpoint := "/api/test_suites/bulk_test_results"
endpoint := hostEndpointCompat(c, "/api/test_suites/bulk_test_results")

reqBody := struct {
AttemptedBy string `json:"attempted_by"`
Expand Down Expand Up @@ -105,7 +105,7 @@ func (c Client) updateTestResultsStatuses(
testSuite string,
testResultsFiles []TestResultsFile,
) error {
endpoint := "/api/test_suites/bulk_test_results"
endpoint := hostEndpointCompat(c, "/api/test_suites/bulk_test_results")

type uploadStatus struct {
CaptainID string `json:"id"`
Expand Down
56 changes: 54 additions & 2 deletions internal/backend/remote/update_test_results_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ var _ = Describe("Uploading Test Results", func() {
mockRoundTripper func(*http.Request) (*http.Response, error)
mockRoundTripCalls int
mockUUID uuid.UUID
host string
)

BeforeEach(func() {
Expand All @@ -41,18 +42,66 @@ var _ = Describe("Uploading Test Results", func() {
apiClient = remote.Client{ClientConfig: remote.ClientConfig{
Log: zap.NewNop().Sugar(),
NewUUID: mockNewUUID,
Host: host,
}, RoundTrip: mockRoundTripper}
})

Context("under expected conditions w/ captain.build host", func() {
BeforeEach(func() {
mockRoundTripper = func(req *http.Request) (*http.Response, error) {
var resp http.Response

switch mockRoundTripCalls {
case 0: // registering the test results file
Expect(req.Method).To(Equal(http.MethodPost))
Expect(req.URL.Path).To(HaveSuffix("/api/test_suites/bulk_test_results"))
Expect(req.Header.Get("Content-Type")).To(Equal("application/json"))
resp.Body = io.NopCloser(strings.NewReader(fmt.Sprintf(
"{\"test_results_uploads\":[{\"id\": %q, \"external_identifier\":%q,\"upload_url\":\"%d\"}]}",
"some-captain-identifier", mockUUID, GinkgoRandomSeed(),
)))
case 1: // upload to `upload_url`
Expect(req.Method).To(Equal(http.MethodPut))
Expect(req.URL.String()).To(ContainSubstring(fmt.Sprintf("%d", GinkgoRandomSeed())))
resp.Body = io.NopCloser(strings.NewReader(""))
case 2: // update status
Expect(req.Method).To(Equal(http.MethodPut))
Expect(req.URL.Path).To(HaveSuffix("/api/test_suites/bulk_test_results"))
body, err := io.ReadAll(req.Body)
Expect(err).ToNot(HaveOccurred())
Expect(string(body)).To(ContainSubstring(fmt.Sprintf(
"%q,\"upload_status\":\"uploaded\"",
"some-captain-identifier",
)))
resp.Body = io.NopCloser(strings.NewReader(""))
default:
Fail("too many HTTP calls")
}

mockRoundTripCalls++

return &resp, nil
}
})

It("registers, uploads, and updates the test result in sequence", func() {
uploadResults, err := apiClient.UpdateTestResults(context.Background(), "test suite id", testResults)
Expect(err).To(Succeed())
Expect(uploadResults).To(HaveLen(1))
Expect(uploadResults[0].Uploaded).To(Equal(true))
})
})

Context("under expected conditions", func() {
BeforeEach(func() {
host = "cloud.rwx.com"
mockRoundTripper = func(req *http.Request) (*http.Response, error) {
var resp http.Response

switch mockRoundTripCalls {
case 0: // registering the test results file
Expect(req.Method).To(Equal(http.MethodPost))
Expect(req.URL.Path).To(HaveSuffix("bulk_test_results"))
Expect(req.URL.Path).To(HaveSuffix("/captain/api/test_suites/bulk_test_results"))
Expect(req.Header.Get("Content-Type")).To(Equal("application/json"))
resp.Body = io.NopCloser(strings.NewReader(fmt.Sprintf(
"{\"test_results_uploads\":[{\"id\": %q, \"external_identifier\":%q,\"upload_url\":\"%d\"}]}",
Expand All @@ -64,7 +113,7 @@ var _ = Describe("Uploading Test Results", func() {
resp.Body = io.NopCloser(strings.NewReader(""))
case 2: // update status
Expect(req.Method).To(Equal(http.MethodPut))
Expect(req.URL.Path).To(HaveSuffix("bulk_test_results"))
Expect(req.URL.Path).To(HaveSuffix("/captain/api/test_suites/bulk_test_results"))
body, err := io.ReadAll(req.Body)
Expect(err).ToNot(HaveOccurred())
Expect(string(body)).To(ContainSubstring(fmt.Sprintf(
Expand Down Expand Up @@ -92,6 +141,7 @@ var _ = Describe("Uploading Test Results", func() {

Context("with an error during test results file registration", func() {
BeforeEach(func() {
host = "cloud.rwx.com"
mockRoundTripper = func(req *http.Request) (*http.Response, error) {
return nil, errors.NewInternalError("Error")
}
Expand All @@ -106,6 +156,7 @@ var _ = Describe("Uploading Test Results", func() {

Context("with an error from S3", func() {
BeforeEach(func() {
host = "cloud.rwx.com"
mockRoundTripper = func(req *http.Request) (*http.Response, error) {
var resp http.Response

Expand Down Expand Up @@ -146,6 +197,7 @@ var _ = Describe("Uploading Test Results", func() {

Context("with an error while updating an test results file status", func() {
BeforeEach(func() {
host = "cloud.rwx.com"
mockRoundTripper = func(req *http.Request) (*http.Response, error) {
var (
resp http.Response
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# `some-suite-id` Summary

[🔗 View in Captain Cloud](https://example.com/deep_link/test_suite_summaries/some-suite-id/some/branch/abcdef113131)
[🔗 View in Captain Cloud](https://example.com/captain/deep_link/test_suite_summaries/some-suite-id/some/branch/abcdef113131)

9 tests, 1 flaky, 3 failed, 1 timed out, 1 quarantined, 1 canceled, 1 skipped, 2 retries

Expand Down
2 changes: 1 addition & 1 deletion internal/reporting/markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ func WriteMarkdownSummary(file fs.File, testResults v1.TestResults, cfg Configur
if cfg.CloudEnabled {
if _, err := markdown.WriteString(
fmt.Sprintf(
"[🔗 View in Captain Cloud](https://%v/deep_link/test_suite_summaries/%v/%v/%v)\n\n",
"[🔗 View in Captain Cloud](https://%v/captain/deep_link/test_suite_summaries/%v/%v/%v)\n\n",
cfg.CloudHost,
cfg.SuiteID,
cfg.Provider.BranchName,
Expand Down
2 changes: 1 addition & 1 deletion test/cloud_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ var _ = Describe(versionedPrefixForQuarantining()+"Cloud Mode Integration Tests"
withAndWithoutInheritedEnv(func(getEnv envGenerator, prefix string) {
getEnvWithAccessToken := func() map[string]string {
env := getEnv()
env["CAPTAIN_HOST"] = "staging.captain.build"
env["CAPTAIN_HOST"] = "staging.cloud.rwx.com"
env["RWX_ACCESS_TOKEN"] = os.Getenv("RWX_ACCESS_TOKEN_STAGING")
return env
}
Expand Down

0 comments on commit c0b87a4

Please sign in to comment.