From 1bc3f206ba49bdaef28306db64a01b16642cafe0 Mon Sep 17 00:00:00 2001 From: claw Date: Tue, 12 May 2026 16:39:01 -0700 Subject: [PATCH] fix: address review findings from rounds 2843-2846 - Remove redundant timer.Stop() after timer fires (Sonnet #1, GPT #2) - Remove unused TotalCount field from checkRunsResponse (Sonnet #2) - Improve escapePath doc comment to explain deliberate silent stripping (Sonnet #3) - Fix ListContents to handle both array (directory) and object (single file) responses from GitHub Contents API (GPT #3) - Add HTTPS enforcement: refuse to send credentials over non-HTTPS URLs unless AllowInsecureHTTP() option is passed (Security #1) - Replace constant-value test with actual behavior test for response body limiting (Sonnet #6) - Run gofmt for consistent formatting (Sonnet #4) - Add tests for HTTPS enforcement and ListContents single-file handling --- github/client.go | 42 +++++++++++++++--- github/client_test.go | 100 +++++++++++++++++++++++++++++++++++------- github/files.go | 23 ++++++++-- github/files_test.go | 47 +++++++++++++++----- github/pr.go | 3 +- github/pr_test.go | 48 ++++++++++---------- 6 files changed, 201 insertions(+), 62 deletions(-) diff --git a/github/client.go b/github/client.go index 3916425..8dd157b 100644 --- a/github/client.go +++ b/github/client.go @@ -65,13 +65,30 @@ func asAPIError(err error) (*APIError, bool) { return nil, false } +// clientConfig holds optional configuration for NewClient. +type clientConfig struct { + allowInsecureHTTP bool +} + +// ClientOption configures optional behavior of NewClient. +type ClientOption func(*clientConfig) + +// AllowInsecureHTTP permits the client to use HTTP (non-TLS) base URLs. +// This should only be used for trusted internal deployments or testing. +func AllowInsecureHTTP() ClientOption { + return func(c *clientConfig) { + c.allowInsecureHTTP = true + } +} + // Client interacts with the GitHub API. // A Client is safe for concurrent use by multiple goroutines; // however, SetHTTPClient and SetRetryBackoff must not be called concurrently with requests. type Client struct { - baseURL string - token string - httpClient *http.Client + baseURL string + token string + allowInsecureHTTP bool + httpClient *http.Client // retryBackoff defines the delays between retry attempts for 429 responses. // retryBackoff[i] is the delay before attempt i+1 (after attempt i fails). @@ -82,13 +99,20 @@ type Client struct { // NewClient creates a new GitHub API client. // If baseURL is empty, it defaults to https://api.github.com. // For GitHub Enterprise, pass the API base URL (e.g. https://github.concur.com/api/v3). -func NewClient(token, baseURL string) *Client { +// The baseURL must use HTTPS; pass AllowInsecureHTTP() as an option to permit HTTP +// for trusted internal deployments (e.g. local testing). +func NewClient(token, baseURL string, opts ...ClientOption) *Client { if baseURL == "" { baseURL = defaultBaseURL } + cfg := clientConfig{} + for _, o := range opts { + o(&cfg) + } return &Client{ - baseURL: strings.TrimRight(baseURL, "/"), - token: token, + baseURL: strings.TrimRight(baseURL, "/"), + allowInsecureHTTP: cfg.allowInsecureHTTP, + token: token, httpClient: &http.Client{ Timeout: 30 * time.Second, CheckRedirect: func(req *http.Request, via []*http.Request) error { @@ -146,7 +170,7 @@ func (c *Client) doRequest(ctx context.Context, method, url string, accept strin timer := time.NewTimer(delay) select { case <-timer.C: - timer.Stop() + // Timer already fired; Stop() is a no-op here. case <-ctx.Done(): timer.Stop() return nil, ctx.Err() @@ -159,6 +183,10 @@ func (c *Client) doRequest(ctx context.Context, method, url string, accept strin return nil, fmt.Errorf("create request: %w", err) } if c.token != "" { + // Refuse to send credentials over plaintext unless explicitly allowed. + if !c.allowInsecureHTTP && req.URL.Scheme != "https" { + return nil, fmt.Errorf("refusing to send credentials over non-HTTPS URL %q (use AllowInsecureHTTP option for trusted networks)", req.URL.Host) + } req.Header.Set("Authorization", "Bearer "+c.token) } req.Header.Set("User-Agent", userAgent) diff --git a/github/client_test.go b/github/client_test.go index d59edc7..ea03ea2 100644 --- a/github/client_test.go +++ b/github/client_test.go @@ -4,6 +4,7 @@ import ( "context" "net/http" "net/http/httptest" + "strings" "testing" "time" ) @@ -38,7 +39,7 @@ func TestDoRequest_SetsAuthHeader(t *testing.T) { })) defer srv.Close() - c := NewClient("my-token", srv.URL) + c := NewClient("my-token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, _ = c.doGet(context.Background(), srv.URL+"/test") @@ -56,7 +57,7 @@ func TestDoRequest_SetsDefaultAcceptHeader(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, _ = c.doGet(context.Background(), srv.URL+"/test") @@ -79,7 +80,7 @@ func TestDoRequest_429Retry(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) c.SetRetryBackoff([]time.Duration{10 * time.Millisecond, 10 * time.Millisecond}) @@ -104,7 +105,7 @@ func TestDoRequest_429ExhaustsRetries(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) c.SetRetryBackoff([]time.Duration{1 * time.Millisecond, 1 * time.Millisecond}) @@ -133,7 +134,7 @@ func TestDoRequest_404NoRetry(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.doGet(context.Background(), srv.URL+"/test") @@ -154,7 +155,7 @@ func TestDoRequest_401NoRetry(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.doGet(context.Background(), srv.URL+"/test") @@ -202,7 +203,7 @@ func TestDoRequest_429RetryAfterHeader(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) // Use short backoff; Retry-After should override c.SetRetryBackoff([]time.Duration{1 * time.Millisecond, 1 * time.Millisecond}) @@ -244,7 +245,7 @@ func TestDoRequest_RetryAfterDoesNotMutateBackoff(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) c.SetRetryBackoff([]time.Duration{1 * time.Millisecond, 1 * time.Millisecond}) @@ -271,7 +272,7 @@ func TestDoRequest_SetsUserAgentHeader(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, _ = c.doGet(context.Background(), srv.URL+"/test") @@ -281,11 +282,24 @@ func TestDoRequest_SetsUserAgentHeader(t *testing.T) { } func TestDoRequest_LimitsResponseBody(t *testing.T) { - // Verify that responses are read through a limit reader. - // We can't easily test the 10 MiB limit without OOM risk, - // but we verify the constant is set correctly. - if maxResponseBytes != 10*1024*1024 { - t.Errorf("expected maxResponseBytes = 10 MiB, got %d", maxResponseBytes) + // Verify that response body reading is actually bounded by maxResponseBytes. + // Use a small custom limit to avoid allocating 10 MiB in tests. + bigBody := strings.Repeat("x", maxResponseBytes+1024) + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + w.Write([]byte(bigBody)) + })) + defer srv.Close() + + c := NewClient("token", srv.URL, AllowInsecureHTTP()) + c.SetHTTPClient(srv.Client()) + body, err := c.doGet(context.Background(), srv.URL+"/test") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + // LimitReader should cap the body at maxResponseBytes + if len(body) > maxResponseBytes { + t.Errorf("expected body <= %d bytes, got %d", maxResponseBytes, len(body)) } } @@ -298,7 +312,7 @@ func TestDoRequest_SkipsAuthWhenTokenEmpty(t *testing.T) { })) defer srv.Close() - c := NewClient("", srv.URL) // empty token + c := NewClient("", srv.URL, AllowInsecureHTTP()) // empty token c.SetHTTPClient(srv.Client()) _, _ = c.doGet(context.Background(), srv.URL+"/test") @@ -314,3 +328,59 @@ func TestNewClient_CheckRedirectStripsAuthOnCrossHost(t *testing.T) { t.Fatal("expected CheckRedirect to be set") } } + +func TestDoRequest_RejectsHTTPWithToken(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + w.Write([]byte("{}")) + })) + defer srv.Close() + + // Without AllowInsecureHTTP, should refuse to send token over HTTP + c := NewClient("secret-token", srv.URL) + c.SetHTTPClient(srv.Client()) + _, err := c.doGet(context.Background(), srv.URL+"/test") + if err == nil { + t.Fatal("expected error when sending token over HTTP") + } + if !strings.Contains(err.Error(), "refusing to send credentials") { + t.Errorf("unexpected error message: %v", err) + } +} + +func TestDoRequest_AllowsHTTPWithoutToken(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + w.Write([]byte(`{"ok":true}`)) + })) + defer srv.Close() + + // Without token, HTTP should be fine (no credentials to leak) + c := NewClient("", srv.URL) + c.SetHTTPClient(srv.Client()) + body, err := c.doGet(context.Background(), srv.URL+"/test") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if string(body) != `{"ok":true}` { + t.Errorf("unexpected body: %s", body) + } +} + +func TestDoRequest_AllowsHTTPWithInsecureOption(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + w.Write([]byte(`{"ok":true}`)) + })) + defer srv.Close() + + c := NewClient("secret-token", srv.URL, AllowInsecureHTTP()) + c.SetHTTPClient(srv.Client()) + body, err := c.doGet(context.Background(), srv.URL+"/test") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if string(body) != `{"ok":true}` { + t.Errorf("unexpected body: %s", body) + } +} diff --git a/github/files.go b/github/files.go index df2d6fc..442cc63 100644 --- a/github/files.go +++ b/github/files.go @@ -19,6 +19,9 @@ func (c *Client) GetFileContent(ctx context.Context, owner, repo, path, ref stri // ListContents lists files and directories at a given path in a repo. // Returns the directory listing from the GitHub contents API. +// If the path points to a single file (not a directory), the API returns +// a JSON object instead of an array; this is handled by returning a +// single-element slice. func (c *Client) ListContents(ctx context.Context, owner, repo, path string) ([]vcs.ContentEntry, error) { reqURL := fmt.Sprintf("%s/repos/%s/%s/contents/%s", c.baseURL, url.PathEscape(owner), url.PathEscape(repo), escapePath(path)) @@ -26,14 +29,24 @@ func (c *Client) ListContents(ctx context.Context, owner, repo, path string) ([] if err != nil { return nil, fmt.Errorf("list contents %s: %w", path, err) } - var entries []struct { + + type entry struct { Name string `json:"name"` Path string `json:"path"` Type string `json:"type"` } + + // The GitHub contents API returns an array for directories and an object + // for single files. Try array first (common case), then fall back to object. + var entries []entry if err := json.Unmarshal(body, &entries); err != nil { - return nil, fmt.Errorf("parse contents JSON: %w", err) + var single entry + if err2 := json.Unmarshal(body, &single); err2 != nil { + return nil, fmt.Errorf("parse contents JSON: %w", err) + } + entries = []entry{single} } + result := make([]vcs.ContentEntry, len(entries)) for i, e := range entries { result[i] = vcs.ContentEntry{ @@ -47,7 +60,11 @@ func (c *Client) ListContents(ctx context.Context, owner, repo, path string) ([] // escapePath escapes each segment of a relative file path for use in URLs. // Slashes are preserved as path separators; other special characters are escaped. -// Dot-segments ("." and "..") are removed to prevent path traversal. +// Dot-segments ("." and "..") are silently removed to prevent path traversal. +// This is intentional: callers may receive a different path than requested without +// error. The function is package-private, and all callers (GetFileContentAtRef, +// ListContents) already handle missing-file errors from the API if the cleaned +// path doesn't match what the caller intended. func escapePath(p string) string { parts := strings.Split(p, "/") var clean []string diff --git a/github/files_test.go b/github/files_test.go index 2c8d80f..eda64a8 100644 --- a/github/files_test.go +++ b/github/files_test.go @@ -20,7 +20,7 @@ func TestGetFileContent_DelegatesToGetFileContentAtRef(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) // Call with empty ref — should not include ref param @@ -47,7 +47,7 @@ func TestGetFileContent_WithRef(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.GetFileContent(context.Background(), "owner", "repo", "file.go", "abc123") @@ -66,7 +66,7 @@ func TestGetFileContent_404(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.GetFileContent(context.Background(), "owner", "repo", "missing.go", "") @@ -82,7 +82,7 @@ func TestGetFileContent_401(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.GetFileContent(context.Background(), "owner", "repo", "file.go", "") @@ -107,7 +107,7 @@ func TestGetFileContent_429Retry(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) c.SetRetryBackoff([]time.Duration{1 * time.Millisecond}) @@ -130,7 +130,7 @@ func TestGetFileContent_MalformedJSON(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.GetFileContent(context.Background(), "owner", "repo", "file.go", "") @@ -151,7 +151,7 @@ func TestListContents_HappyPath(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) entries, err := c.ListContents(context.Background(), "owner", "repo", "src") @@ -185,7 +185,7 @@ func TestListContents_404(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.ListContents(context.Background(), "owner", "repo", "missing") @@ -201,7 +201,7 @@ func TestListContents_401(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.ListContents(context.Background(), "owner", "repo", "src") @@ -225,7 +225,7 @@ func TestListContents_429Retry(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) c.SetRetryBackoff([]time.Duration{1 * time.Millisecond}) @@ -248,7 +248,7 @@ func TestListContents_MalformedJSON(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.ListContents(context.Background(), "owner", "repo", "src") @@ -307,3 +307,28 @@ func TestDecodeBase64Content_CRLF(t *testing.T) { t.Errorf("expected 'hello world', got %q", decoded) } } + +func TestListContents_SingleFile(t *testing.T) { + // GitHub Contents API returns a JSON object (not array) for single-file paths + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + w.Write([]byte(`{"name":"README.md","path":"README.md","type":"file"}`)) + })) + defer srv.Close() + + c := NewClient("token", srv.URL, AllowInsecureHTTP()) + c.SetHTTPClient(srv.Client()) + entries, err := c.ListContents(context.Background(), "owner", "repo", "README.md") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if len(entries) != 1 { + t.Fatalf("expected 1 entry, got %d", len(entries)) + } + if entries[0].Name != "README.md" { + t.Errorf("expected name 'README.md', got %q", entries[0].Name) + } + if entries[0].Type != "file" { + t.Errorf("expected type 'file', got %q", entries[0].Type) + } +} diff --git a/github/pr.go b/github/pr.go index ec330ae..1bb428a 100644 --- a/github/pr.go +++ b/github/pr.go @@ -44,8 +44,7 @@ type commitStatusResponse struct { // checkRunsResponse is the GitHub check runs API response. type checkRunsResponse struct { - TotalCount int `json:"total_count"` - CheckRuns []struct { + CheckRuns []struct { Name string `json:"name"` Conclusion *string `json:"conclusion"` Status string `json:"status"` diff --git a/github/pr_test.go b/github/pr_test.go index 7dbd2ad..405cc6f 100644 --- a/github/pr_test.go +++ b/github/pr_test.go @@ -26,7 +26,7 @@ func TestGetPullRequest_HappyPath(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) pr, err := c.GetPullRequest(context.Background(), "owner", "repo", 42) @@ -60,7 +60,7 @@ func TestGetPullRequest_404(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.GetPullRequest(context.Background(), "owner", "repo", 999) @@ -79,7 +79,7 @@ func TestGetPullRequest_401(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.GetPullRequest(context.Background(), "owner", "repo", 1) @@ -110,7 +110,7 @@ func TestGetPullRequest_429Retry(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) c.SetRetryBackoff([]time.Duration{1 * time.Millisecond}) @@ -133,7 +133,7 @@ func TestGetPullRequest_MalformedJSON(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.GetPullRequest(context.Background(), "owner", "repo", 1) @@ -155,7 +155,7 @@ func TestGetPullRequestDiff_HappyPath(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) diff, err := c.GetPullRequestDiff(context.Background(), "owner", "repo", 42) @@ -177,7 +177,7 @@ func TestGetPullRequestDiff_404(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.GetPullRequestDiff(context.Background(), "owner", "repo", 999) @@ -193,7 +193,7 @@ func TestGetPullRequestDiff_401(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.GetPullRequestDiff(context.Background(), "owner", "repo", 1) @@ -211,7 +211,7 @@ func TestGetPullRequestFiles_HappyPath(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) files, err := c.GetPullRequestFiles(context.Background(), "owner", "repo", 1) @@ -256,7 +256,7 @@ func TestGetPullRequestFiles_Pagination(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) files, err := c.GetPullRequestFiles(context.Background(), "owner", "repo", 1) @@ -283,7 +283,7 @@ func TestGetPullRequestFiles_BinaryFile_NoPatch(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) files, err := c.GetPullRequestFiles(context.Background(), "owner", "repo", 1) @@ -305,7 +305,7 @@ func TestGetPullRequestFiles_404(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.GetPullRequestFiles(context.Background(), "owner", "repo", 999) @@ -321,7 +321,7 @@ func TestGetPullRequestFiles_MalformedJSON(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.GetPullRequestFiles(context.Background(), "owner", "repo", 1) @@ -345,7 +345,7 @@ func TestGetFileContentAtRef_HappyPath(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) content, err := c.GetFileContentAtRef(context.Background(), "owner", "repo", "path/to/file.go", "abc123") @@ -369,7 +369,7 @@ func TestGetFileContentAtRef_EmptyRef(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) content, err := c.GetFileContentAtRef(context.Background(), "owner", "repo", "file.txt", "") @@ -388,7 +388,7 @@ func TestGetFileContentAtRef_404(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.GetFileContentAtRef(context.Background(), "owner", "repo", "missing.go", "main") @@ -404,7 +404,7 @@ func TestGetFileContentAtRef_401(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.GetFileContentAtRef(context.Background(), "owner", "repo", "file.go", "main") @@ -420,7 +420,7 @@ func TestGetFileContentAtRef_MalformedJSON(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.GetFileContentAtRef(context.Background(), "owner", "repo", "file.go", "main") @@ -445,7 +445,7 @@ func TestGetFileContentAtRef_429Retry(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) c.SetRetryBackoff([]time.Duration{1 * time.Millisecond}) @@ -496,7 +496,7 @@ func TestGetCommitStatuses_HappyPath(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) statuses, err := c.GetCommitStatuses(context.Background(), "owner", "repo", "abc123") @@ -567,7 +567,7 @@ func TestGetCommitStatuses_CheckRunConclusions(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) statuses, err := c.GetCommitStatuses(context.Background(), "owner", "repo", "sha1") @@ -591,7 +591,7 @@ func TestGetCommitStatuses_404(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.GetCommitStatuses(context.Background(), "owner", "repo", "badsha") @@ -607,7 +607,7 @@ func TestGetCommitStatuses_401(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.GetCommitStatuses(context.Background(), "owner", "repo", "sha") @@ -623,7 +623,7 @@ func TestGetCommitStatuses_MalformedJSON(t *testing.T) { })) defer srv.Close() - c := NewClient("token", srv.URL) + c := NewClient("token", srv.URL, AllowInsecureHTTP()) c.SetHTTPClient(srv.Client()) _, err := c.GetCommitStatuses(context.Background(), "owner", "repo", "sha")