Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions github/code_quality.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright 2026 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package github

import (
"context"
"fmt"
)

// CodeQualityService handles communication with the code quality related
// methods of the GitHub API.
//
// GitHub API docs: https://docs.github.com/rest/code-quality/code-quality?apiVersion=2026-03-10
type CodeQualityService service

// CodeQualitySetupConfiguration represents a code quality setup configuration for a repository.
type CodeQualitySetupConfiguration struct {
State *string `json:"state,omitempty"`
Languages []string `json:"languages,omitempty"`
RunnerType *string `json:"runner_type,omitempty"`
RunnerLabel *string `json:"runner_label,omitempty"`
UpdatedAt *Timestamp `json:"updated_at,omitempty"`
Schedule *string `json:"schedule,omitempty"`
}

// UpdateCodeQualitySetupOptions specifies parameters to the
// CodeQualityService.UpdateSetup method.
type UpdateCodeQualitySetupOptions struct {
Comment thread
MasterOogway1466 marked this conversation as resolved.
Outdated
State *string `json:"state,omitempty"`
RunnerType *string `json:"runner_type,omitempty"`
RunnerLabel *string `json:"runner_label,omitempty"`
Languages []string `json:"languages,omitempty"`
}

// UpdateCodeQualitySetupResponse represents a response from updating a code quality setup configuration.
type UpdateCodeQualitySetupResponse struct {
Comment thread
MasterOogway1466 marked this conversation as resolved.
Outdated
RunID *int64 `json:"run_id,omitempty"`
RunURL *string `json:"run_url,omitempty"`
}

// GetSetup gets a code quality setup configuration for a repository.
//
// GitHub API docs: https://docs.github.com/rest/code-quality/code-quality?apiVersion=2022-11-28#get-a-code-quality-setup-configuration
Comment thread
MasterOogway1466 marked this conversation as resolved.
//
//meta:operation GET /repos/{owner}/{repo}/code-quality/setup
func (s *CodeQualityService) GetSetup(ctx context.Context, owner, repo string) (*CodeQualitySetupConfiguration, *Response, error) {
u := fmt.Sprintf("repos/%v/%v/code-quality/setup", owner, repo)

req, err := s.client.NewRequest(ctx, "GET", u, nil, WithVersion(api20260310))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The doc says, that apiVersion=2022-11-28. But the implementation has WithVersion(api20260310).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same for UpdateSetup

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, 2026-03-10 is the correct apiVersion sorry for not checking the comments thoroughly before submitting 🥲

if err != nil {
return nil, nil, err
}

var cfg *CodeQualitySetupConfiguration
resp, err := s.client.Do(req, &cfg)
if err != nil {
return nil, resp, err
}

return cfg, resp, nil
}

// UpdateSetup updates a code quality setup configuration for a repository.
//
// This method might return an AcceptedError and a status code of 202. This is because this is the status that GitHub
// returns to signify that it has now scheduled the update in a background task.
//
// GitHub API docs: https://docs.github.com/rest/code-quality/code-quality?apiVersion=2022-11-28#update-a-code-quality-setup-configuration
Comment thread
MasterOogway1466 marked this conversation as resolved.
//
//meta:operation PATCH /repos/{owner}/{repo}/code-quality/setup
func (s *CodeQualityService) UpdateSetup(ctx context.Context, owner, repo string, opts *UpdateCodeQualitySetupOptions) (*UpdateCodeQualitySetupResponse, *Response, error) {
Comment thread
MasterOogway1466 marked this conversation as resolved.
Outdated
u := fmt.Sprintf("repos/%v/%v/code-quality/setup", owner, repo)

req, err := s.client.NewRequest(ctx, "PATCH", u, opts, WithVersion(api20260310))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
req, err := s.client.NewRequest(ctx, "PATCH", u, opts, WithVersion(api20260310))
req, err := s.client.NewRequest(ctx, "PATCH", u, opts)
// GitHub API docs: https://docs.github.com/rest/code-quality/code-quality?apiVersion=2022-11-28#update-a-code-quality-setup-configuration

This link (L71) has apiVersion=2022-11-28. So I believe we can remove WithVersion(api20260310)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MasterOogway1466 Let's remove the WithVersion(api20260310). Basically, there is nothing specific for the API 2026-03-10 that is not present in 2022-11-28.

This will resolve your problem #4260 (comment)

if err != nil {
return nil, nil, err
}

var result *UpdateCodeQualitySetupResponse
resp, err := s.client.Do(req, &result)
if err != nil {
return nil, resp, err
}

return result, resp, nil
}
230 changes: 230 additions & 0 deletions github/code_quality_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
// Copyright 2026 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package github

import (
"fmt"
"net/http"
"testing"
"time"

"github.com/google/go-cmp/cmp"
)

func TestCodeQualitySetupConfiguration_Marshal(t *testing.T) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is no longer needed.
Reason comment

t.Parallel()
testJSONMarshal(t, &CodeQualitySetupConfiguration{}, "{}")

c := &CodeQualitySetupConfiguration{
State: Ptr("configured"),
Languages: []string{"javascript-typescript", "python"},
RunnerType: Ptr("standard"),
RunnerLabel: nil,
UpdatedAt: &Timestamp{referenceTime},
Schedule: Ptr("weekly"),
}

want := `{
"state": "configured",
"languages": ["javascript-typescript", "python"],
"runner_type": "standard",
"updated_at": ` + referenceTimeStr + `,
"schedule": "weekly"
}`

testJSONMarshal(t, c, want)
}

func TestUpdateCodeQualitySetupResponse_Marshal(t *testing.T) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is no longer needed.
comment

t.Parallel()
testJSONMarshal(t, &UpdateCodeQualitySetupResponse{}, "{}")

r := &UpdateCodeQualitySetupResponse{
RunID: Ptr(int64(42)),
RunURL: Ptr("https://api.github.com/repos/octocat/hello-world/actions/runs/42"),
}

want := `{
"run_id": 42,
"run_url": "https://api.github.com/repos/octocat/hello-world/actions/runs/42"
}`

testJSONMarshal(t, r, want)
}

func TestCodeQualityService_GetSetup(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)

mux.HandleFunc("/repos/o/r/code-quality/setup", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "GET")
testHeader(t, r, "X-Github-Api-Version", api20260310)
fmt.Fprint(w, `{
"state": "configured",
"languages": ["javascript-typescript", "python"],
"runner_type": "standard",
"runner_label": null,
"updated_at": "2023-01-01T00:00:00Z",
"schedule": "weekly"
}`)
})

ctx := t.Context()
cfg, _, err := client.CodeQuality.GetSetup(ctx, "o", "r")
if err != nil {
t.Fatalf("CodeQuality.GetSetup returned error: %v", err)
}

want := &CodeQualitySetupConfiguration{
State: Ptr("configured"),
Languages: []string{"javascript-typescript", "python"},
RunnerType: Ptr("standard"),
UpdatedAt: &Timestamp{time.Date(2023, time.January, 1, 0, 0, 0, 0, time.UTC)},
Schedule: Ptr("weekly"),
}
if diff := cmp.Diff(want, cfg); diff != "" {
t.Errorf("CodeQuality.GetSetup mismatch (-want +got):\n%v", diff)
}

const methodName = "GetSetup"
testBadOptions(t, methodName, func() (err error) {
_, _, err = client.CodeQuality.GetSetup(ctx, "\n", "\n")
return err
})

testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
got, resp, err := client.CodeQuality.GetSetup(ctx, "o", "r")
if got != nil {
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
}
return resp, err
})
}

func TestCodeQualityService_UpdateSetup(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)

input := &UpdateCodeQualitySetupOptions{
State: Ptr("configured"),
Languages: []string{"javascript-typescript", "python", "ruby"},
}

mux.HandleFunc("/repos/o/r/code-quality/setup", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PATCH")
testHeader(t, r, "X-Github-Api-Version", api20260310)
testJSONBody(t, r, input)
fmt.Fprint(w, `{
"run_id": 42,
"run_url": "https://api.github.com/repos/octocat/hello-world/actions/runs/42"
}`)
})

ctx := t.Context()
result, _, err := client.CodeQuality.UpdateSetup(ctx, "o", "r", input)
if err != nil {
t.Fatalf("CodeQuality.UpdateSetup returned error: %v", err)
}

want := &UpdateCodeQualitySetupResponse{
RunID: Ptr(int64(42)),
RunURL: Ptr("https://api.github.com/repos/octocat/hello-world/actions/runs/42"),
}
if diff := cmp.Diff(want, result); diff != "" {
t.Errorf("CodeQuality.UpdateSetup mismatch (-want +got):\n%v", diff)
}

const methodName = "UpdateSetup"
testBadOptions(t, methodName, func() (err error) {
_, _, err = client.CodeQuality.UpdateSetup(ctx, "\n", "\n", input)
return err
})

testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
got, resp, err := client.CodeQuality.UpdateSetup(ctx, "o", "r", input)
if got != nil {
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
}
return resp, err
})
}

func TestCodeQualityService_UpdateSetup_withRunnerLabel(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)

input := &UpdateCodeQualitySetupOptions{
State: Ptr("configured"),
RunnerType: Ptr("labeled"),
RunnerLabel: Ptr("my-runner"),
Languages: []string{"go", "python"},
}

mux.HandleFunc("/repos/o/r/code-quality/setup", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PATCH")
testHeader(t, r, "X-Github-Api-Version", api20260310)
testJSONBody(t, r, input)
fmt.Fprint(w, `{
"run_id": 99,
"run_url": "https://api.github.com/repos/octocat/hello-world/actions/runs/99"
}`)
})

ctx := t.Context()
result, _, err := client.CodeQuality.UpdateSetup(ctx, "o", "r", input)
if err != nil {
t.Fatalf("CodeQuality.UpdateSetup returned error: %v", err)
}

want := &UpdateCodeQualitySetupResponse{
RunID: Ptr(int64(99)),
RunURL: Ptr("https://api.github.com/repos/octocat/hello-world/actions/runs/99"),
}
if diff := cmp.Diff(want, result); diff != "" {
t.Errorf("CodeQuality.UpdateSetup mismatch (-want +got):\n%v", diff)
}
}

func TestCodeQualityService_UpdateSetup_notConfigured(t *testing.T) {
t.Parallel()
client, mux, _ := setup(t)

input := &UpdateCodeQualitySetupOptions{
State: Ptr("not-configured"),
}

mux.HandleFunc("/repos/o/r/code-quality/setup", func(w http.ResponseWriter, r *http.Request) {
testMethod(t, r, "PATCH")
testHeader(t, r, "X-Github-Api-Version", api20260310)
testJSONBody(t, r, input)
w.WriteHeader(http.StatusOK)
fmt.Fprint(w, `{}`)
})

ctx := t.Context()
_, _, err := client.CodeQuality.UpdateSetup(ctx, "o", "r", input)
if err != nil {
t.Fatalf("CodeQuality.UpdateSetup returned error: %v", err)
}
}

func TestCodeQualityService_GetSetup_invalidOwner(t *testing.T) {
t.Parallel()
client, _, _ := setup(t)

ctx := t.Context()
_, _, err := client.CodeQuality.GetSetup(ctx, "%", "r")
testURLParseError(t, err)
}

func TestCodeQualityService_UpdateSetup_invalidOwner(t *testing.T) {
t.Parallel()
client, _, _ := setup(t)

ctx := t.Context()
_, _, err := client.CodeQuality.UpdateSetup(ctx, "%", "r", nil)
testURLParseError(t, err)
}
Loading
Loading