Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
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
16 changes: 3 additions & 13 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,10 @@ jobs:
with:
go-version-file: 'go.mod'

- name: Ensure go.mod and go.sum are up to date
- name: Ensure Go source and modules are up to date
run: |
STATUS=0
assert-nothing-changed() {
local diff
"$@" >/dev/null || return 1
if ! diff="$(git diff -U1 --color --exit-code)"; then
printf '\e[31mError: running `\e[1m%s\e[22m` results in modifications that you must check into version control:\e[0m\n%s\n\n' "$*" "$diff" >&2
git checkout -- .
STATUS=1
fi
}
assert-nothing-changed go mod tidy
exit $STATUS
go mod tidy -diff
go fix -diff ./...

- name: golangci-lint
uses: golangci/golangci-lint-action@ba0d7d2ec06a0ea1cb5fa41b2e4a3ab91d21278a # v9.3.0
Expand Down
24 changes: 12 additions & 12 deletions api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func (err HTTPError) ScopesSuggestion() string {

// GraphQL performs a GraphQL request using the query string and parses the response into data receiver. If there are errors in the response,
// GraphQLError will be returned, but the receiver will also be partially populated.
func (c Client) GraphQL(hostname string, query string, variables map[string]interface{}, data interface{}) error {
func (c Client) GraphQL(hostname string, query string, variables map[string]any, data any) error {
opts := clientOptions(hostname, c.http.Transport)
opts.Headers[graphqlFeatures] = features
gqlClient, err := ghAPI.NewGraphQLClient(opts)
Expand All @@ -66,7 +66,7 @@ func (c Client) GraphQL(hostname string, query string, variables map[string]inte

// Mutate performs a GraphQL mutation based on a struct and parses the response with the same struct as the receiver. If there are errors in the response,
// GraphQLError will be returned, but the receiver will also be partially populated.
func (c Client) Mutate(hostname, name string, mutation interface{}, variables map[string]interface{}) error {
func (c Client) Mutate(hostname, name string, mutation any, variables map[string]any) error {
opts := clientOptions(hostname, c.http.Transport)
opts.Headers[graphqlFeatures] = features
gqlClient, err := ghAPI.NewGraphQLClient(opts)
Expand All @@ -78,7 +78,7 @@ func (c Client) Mutate(hostname, name string, mutation interface{}, variables ma

// Query performs a GraphQL query based on a struct and parses the response with the same struct as the receiver. If there are errors in the response,
// GraphQLError will be returned, but the receiver will also be partially populated.
func (c Client) Query(hostname, name string, query interface{}, variables map[string]interface{}) error {
func (c Client) Query(hostname, name string, query any, variables map[string]any) error {
opts := clientOptions(hostname, c.http.Transport)
opts.Headers[graphqlFeatures] = features
gqlClient, err := ghAPI.NewGraphQLClient(opts)
Expand All @@ -90,7 +90,7 @@ func (c Client) Query(hostname, name string, query interface{}, variables map[st

// QueryWithContext performs a GraphQL query based on a struct and parses the response with the same struct as the receiver. If there are errors in the response,
// GraphQLError will be returned, but the receiver will also be partially populated.
func (c Client) QueryWithContext(ctx context.Context, hostname, name string, query interface{}, variables map[string]interface{}) error {
func (c Client) QueryWithContext(ctx context.Context, hostname, name string, query any, variables map[string]any) error {
opts := clientOptions(hostname, c.http.Transport)
opts.Headers[graphqlFeatures] = features
gqlClient, err := ghAPI.NewGraphQLClient(opts)
Expand All @@ -101,7 +101,7 @@ func (c Client) QueryWithContext(ctx context.Context, hostname, name string, que
}

// REST performs a REST request and parses the response.
func (c Client) REST(hostname string, method string, p string, body io.Reader, data interface{}) error {
func (c Client) REST(hostname string, method string, p string, body io.Reader, data any) error {
opts := clientOptions(hostname, c.http.Transport)
restClient, err := ghAPI.NewRESTClient(opts)
if err != nil {
Expand All @@ -110,7 +110,7 @@ func (c Client) REST(hostname string, method string, p string, body io.Reader, d
return handleResponse(restClient.Do(method, p, body, data))
}

func (c Client) RESTWithNext(hostname string, method string, p string, body io.Reader, data interface{}) (string, error) {
func (c Client) RESTWithNext(hostname string, method string, p string, body io.Reader, data any) (string, error) {
opts := clientOptions(hostname, c.http.Transport)
restClient, err := ghAPI.NewRESTClient(opts)
if err != nil {
Expand Down Expand Up @@ -211,7 +211,7 @@ func generateScopesSuggestion(statusCode int, endpointNeedsScopes, tokenHasScope
}

gotScopes := map[string]struct{}{}
for _, s := range strings.Split(tokenHasScopes, ",") {
for s := range strings.SplitSeq(tokenHasScopes, ",") {
s = strings.TrimSpace(s)
gotScopes[s] = struct{}{}

Expand All @@ -230,15 +230,15 @@ func generateScopesSuggestion(statusCode int, endpointNeedsScopes, tokenHasScope
gotScopes["user:follow"] = struct{}{}
} else if s == "codespace" {
gotScopes["codespace:secrets"] = struct{}{}
} else if strings.HasPrefix(s, "admin:") {
gotScopes["read:"+strings.TrimPrefix(s, "admin:")] = struct{}{}
} else if after, ok := strings.CutPrefix(s, "admin:"); ok {
gotScopes["read:"+after] = struct{}{}
gotScopes["write:"+strings.TrimPrefix(s, "admin:")] = struct{}{}
} else if strings.HasPrefix(s, "write:") {
gotScopes["read:"+strings.TrimPrefix(s, "write:")] = struct{}{}
} else if after, ok := strings.CutPrefix(s, "write:"); ok {
gotScopes["read:"+after] = struct{}{}
}
}

for _, s := range strings.Split(endpointNeedsScopes, ",") {
for s := range strings.SplitSeq(endpointNeedsScopes, ",") {
s = strings.TrimSpace(s)
if _, gotScope := gotScopes[s]; s == "" || gotScope {
continue
Expand Down
2 changes: 1 addition & 1 deletion api/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func TestGraphQL(t *testing.T) {
http := &httpmock.Registry{}
client := newTestClient(http)

vars := map[string]interface{}{"name": "Mona"}
vars := map[string]any{"name": "Mona"}
response := struct {
Viewer struct {
Login string
Expand Down
70 changes: 35 additions & 35 deletions api/export_pr.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"strings"
)

func (issue *Issue) ExportData(fields []string) map[string]interface{} {
func (issue *Issue) ExportData(fields []string) map[string]any {
v := reflect.ValueOf(issue).Elem()
data := map[string]interface{}{}
data := map[string]any{}

for _, f := range fields {
switch f {
Expand All @@ -20,25 +20,25 @@ func (issue *Issue) ExportData(fields []string) map[string]interface{} {
case "projectCards":
data[f] = issue.ProjectCards.Nodes
case "projectItems":
items := make([]map[string]interface{}, 0, len(issue.ProjectItems.Nodes))
items := make([]map[string]any, 0, len(issue.ProjectItems.Nodes))
for _, n := range issue.ProjectItems.Nodes {
items = append(items, map[string]interface{}{
items = append(items, map[string]any{
"status": n.Status,
"title": n.Project.Title,
})
}
data[f] = items
case "closedByPullRequestsReferences":
items := make([]map[string]interface{}, 0, len(issue.ClosedByPullRequestsReferences.Nodes))
items := make([]map[string]any, 0, len(issue.ClosedByPullRequestsReferences.Nodes))
for _, n := range issue.ClosedByPullRequestsReferences.Nodes {
items = append(items, map[string]interface{}{
items = append(items, map[string]any{
"id": n.ID,
"number": n.Number,
"url": n.URL,
"repository": map[string]interface{}{
"repository": map[string]any{
"id": n.Repository.ID,
"name": n.Repository.Name,
"owner": map[string]interface{}{
"owner": map[string]any{
"id": n.Repository.Owner.ID,
"login": n.Repository.Owner.Login,
},
Expand All @@ -50,7 +50,7 @@ func (issue *Issue) ExportData(fields []string) map[string]interface{} {
data[f] = issue.IssueType
case "parent":
if issue.Parent != nil {
data[f] = map[string]interface{}{
data[f] = map[string]any{
"id": issue.Parent.ID,
"number": issue.Parent.Number,
"title": issue.Parent.Title,
Expand All @@ -61,53 +61,53 @@ func (issue *Issue) ExportData(fields []string) map[string]interface{} {
data[f] = nil
}
case "subIssues":
items := make([]map[string]interface{}, 0, len(issue.SubIssues.Nodes))
items := make([]map[string]any, 0, len(issue.SubIssues.Nodes))
for _, n := range issue.SubIssues.Nodes {
items = append(items, map[string]interface{}{
items = append(items, map[string]any{
"id": n.ID,
"number": n.Number,
"title": n.Title,
"url": n.URL,
"state": n.State,
})
}
data[f] = map[string]interface{}{
data[f] = map[string]any{
"nodes": items,
"totalCount": issue.SubIssues.TotalCount,
}
case "subIssuesSummary":
data[f] = map[string]interface{}{
data[f] = map[string]any{
"total": issue.SubIssuesSummary.Total,
"completed": issue.SubIssuesSummary.Completed,
"percentCompleted": issue.SubIssuesSummary.PercentCompleted,
}
case "blockedBy":
items := make([]map[string]interface{}, 0, len(issue.BlockedBy.Nodes))
items := make([]map[string]any, 0, len(issue.BlockedBy.Nodes))
for _, n := range issue.BlockedBy.Nodes {
items = append(items, map[string]interface{}{
items = append(items, map[string]any{
"id": n.ID,
"number": n.Number,
"title": n.Title,
"url": n.URL,
"state": n.State,
})
}
data[f] = map[string]interface{}{
data[f] = map[string]any{
"nodes": items,
"totalCount": issue.BlockedBy.TotalCount,
}
case "blocking":
items := make([]map[string]interface{}, 0, len(issue.Blocking.Nodes))
items := make([]map[string]any, 0, len(issue.Blocking.Nodes))
for _, n := range issue.Blocking.Nodes {
items = append(items, map[string]interface{}{
items = append(items, map[string]any{
"id": n.ID,
"number": n.Number,
"title": n.Title,
"url": n.URL,
"state": n.State,
})
}
data[f] = map[string]interface{}{
data[f] = map[string]any{
"nodes": items,
"totalCount": issue.Blocking.TotalCount,
}
Expand All @@ -120,20 +120,20 @@ func (issue *Issue) ExportData(fields []string) map[string]interface{} {
return data
}

func (pr *PullRequest) ExportData(fields []string) map[string]interface{} {
func (pr *PullRequest) ExportData(fields []string) map[string]any {
v := reflect.ValueOf(pr).Elem()
data := map[string]interface{}{}
data := map[string]any{}

for _, f := range fields {
switch f {
case "headRepository":
data[f] = pr.HeadRepository
case "statusCheckRollup":
if n := pr.StatusCheckRollup.Nodes; len(n) > 0 {
checks := make([]interface{}, 0, len(n[0].Commit.StatusCheckRollup.Contexts.Nodes))
checks := make([]any, 0, len(n[0].Commit.StatusCheckRollup.Contexts.Nodes))
for _, c := range n[0].Commit.StatusCheckRollup.Contexts.Nodes {
if c.TypeName == "CheckRun" {
checks = append(checks, map[string]interface{}{
checks = append(checks, map[string]any{
"__typename": c.TypeName,
"name": c.Name,
"workflowName": c.CheckSuite.WorkflowRun.Workflow.Name,
Expand All @@ -144,7 +144,7 @@ func (pr *PullRequest) ExportData(fields []string) map[string]interface{} {
"detailsUrl": c.DetailsURL,
})
} else {
checks = append(checks, map[string]interface{}{
checks = append(checks, map[string]any{
"__typename": c.TypeName,
"context": c.Context,
"state": c.State,
Expand All @@ -158,19 +158,19 @@ func (pr *PullRequest) ExportData(fields []string) map[string]interface{} {
data[f] = nil
}
case "commits":
commits := make([]interface{}, 0, len(pr.Commits.Nodes))
commits := make([]any, 0, len(pr.Commits.Nodes))
for _, c := range pr.Commits.Nodes {
commit := c.Commit
authors := make([]interface{}, 0, len(commit.Authors.Nodes))
authors := make([]any, 0, len(commit.Authors.Nodes))
for _, author := range commit.Authors.Nodes {
authors = append(authors, map[string]interface{}{
authors = append(authors, map[string]any{
"name": author.Name,
"email": author.Email,
"id": author.User.ID,
"login": author.User.Login,
})
}
commits = append(commits, map[string]interface{}{
commits = append(commits, map[string]any{
"oid": commit.OID,
"messageHeadline": commit.MessageHeadline,
"messageBody": commit.MessageBody,
Expand All @@ -189,9 +189,9 @@ func (pr *PullRequest) ExportData(fields []string) map[string]interface{} {
case "projectCards":
data[f] = pr.ProjectCards.Nodes
case "projectItems":
items := make([]map[string]interface{}, 0, len(pr.ProjectItems.Nodes))
items := make([]map[string]any, 0, len(pr.ProjectItems.Nodes))
for _, n := range pr.ProjectItems.Nodes {
items = append(items, map[string]interface{}{
items = append(items, map[string]any{
"status": n.Status,
"title": n.Project.Title,
})
Expand All @@ -204,7 +204,7 @@ func (pr *PullRequest) ExportData(fields []string) map[string]interface{} {
case "files":
data[f] = pr.Files.Nodes
case "reviewRequests":
requests := make([]interface{}, 0, len(pr.ReviewRequests.Nodes))
requests := make([]any, 0, len(pr.ReviewRequests.Nodes))
for _, req := range pr.ReviewRequests.Nodes {
r := req.RequestedReviewer
switch r.TypeName {
Expand All @@ -223,16 +223,16 @@ func (pr *PullRequest) ExportData(fields []string) map[string]interface{} {
}
data[f] = &requests
case "closingIssuesReferences":
items := make([]map[string]interface{}, 0, len(pr.ClosingIssuesReferences.Nodes))
items := make([]map[string]any, 0, len(pr.ClosingIssuesReferences.Nodes))
for _, n := range pr.ClosingIssuesReferences.Nodes {
items = append(items, map[string]interface{}{
items = append(items, map[string]any{
"id": n.ID,
"number": n.Number,
"url": n.URL,
"repository": map[string]interface{}{
"repository": map[string]any{
"id": n.Repository.ID,
"name": n.Repository.Name,
"owner": map[string]interface{}{
"owner": map[string]any{
"id": n.Repository.Owner.ID,
"login": n.Repository.Owner.Login,
},
Expand Down
8 changes: 4 additions & 4 deletions api/export_pr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,10 +414,10 @@ func TestIssue_ExportData(t *testing.T) {
enc.SetIndent("", "\t")
require.NoError(t, enc.Encode(exported))

var gotData interface{}
var gotData any
dec = json.NewDecoder(&buf)
require.NoError(t, dec.Decode(&gotData))
var expectData interface{}
var expectData any
require.NoError(t, json.Unmarshal([]byte(tt.outputJSON), &expectData))

assert.Equal(t, expectData, gotData)
Expand Down Expand Up @@ -669,10 +669,10 @@ func TestPullRequest_ExportData(t *testing.T) {
enc.SetIndent("", "\t")
require.NoError(t, enc.Encode(exported))

var gotData interface{}
var gotData any
dec = json.NewDecoder(&buf)
require.NoError(t, dec.Decode(&gotData))
var expectData interface{}
var expectData any
require.NoError(t, json.Unmarshal([]byte(tt.outputJSON), &expectData))

assert.Equal(t, expectData, gotData)
Expand Down
8 changes: 4 additions & 4 deletions api/export_repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ import (
"reflect"
)

func (repo *Repository) ExportData(fields []string) map[string]interface{} {
func (repo *Repository) ExportData(fields []string) map[string]any {
v := reflect.ValueOf(repo).Elem()
data := map[string]interface{}{}
data := map[string]any{}

for _, f := range fields {
switch f {
Expand Down Expand Up @@ -41,11 +41,11 @@ func (repo *Repository) ExportData(fields []string) map[string]interface{} {
return data
}

func miniRepoExport(r *Repository) map[string]interface{} {
func miniRepoExport(r *Repository) map[string]any {
if r == nil {
return nil
}
return map[string]interface{}{
return map[string]any{
"id": r.ID,
"name": r.Name,
"owner": r.Owner,
Expand Down
Loading