Skip to content

Commit ade69a4

Browse files
author
Nate Smith
authored
Merge pull request cli#178 from github/issues-disabled
Warn about repo issues disabled on `issue status/list/create`
2 parents 58a6cbc + bd9b3b9 commit ade69a4

File tree

7 files changed

+165
-80
lines changed

7 files changed

+165
-80
lines changed

api/queries_issue.go

Lines changed: 54 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,6 @@ type IssueLabel struct {
2626
Name string
2727
}
2828

29-
type apiIssues struct {
30-
Issues struct {
31-
Nodes []Issue
32-
}
33-
}
34-
3529
const fragments = `
3630
fragment issue on Issue {
3731
number
@@ -47,12 +41,8 @@ const fragments = `
4741
}
4842
`
4943

50-
func IssueCreate(client *Client, ghRepo Repo, params map[string]interface{}) (*Issue, error) {
51-
repoID, err := GitHubRepoId(client, ghRepo)
52-
if err != nil {
53-
return nil, err
54-
}
55-
44+
// IssueCreate creates an issue in a GitHub repository
45+
func IssueCreate(client *Client, repo *Repository, params map[string]interface{}) (*Issue, error) {
5646
query := `
5747
mutation CreateIssue($input: CreateIssueInput!) {
5848
createIssue(input: $input) {
@@ -63,7 +53,7 @@ func IssueCreate(client *Client, ghRepo Repo, params map[string]interface{}) (*I
6353
}`
6454

6555
inputParams := map[string]interface{}{
66-
"repositoryId": repoID,
56+
"repositoryId": repo.ID,
6757
}
6858
for key, val := range params {
6959
inputParams[key] = val
@@ -78,7 +68,7 @@ func IssueCreate(client *Client, ghRepo Repo, params map[string]interface{}) (*I
7868
}
7969
}{}
8070

81-
err = client.GraphQL(query, variables, &result)
71+
err := client.GraphQL(query, variables, &result)
8272
if err != nil {
8373
return nil, err
8474
}
@@ -88,36 +78,41 @@ func IssueCreate(client *Client, ghRepo Repo, params map[string]interface{}) (*I
8878

8979
func IssueStatus(client *Client, ghRepo Repo, currentUsername string) (*IssuesPayload, error) {
9080
type response struct {
91-
Assigned apiIssues
92-
Mentioned apiIssues
93-
Authored apiIssues
81+
Repository struct {
82+
Assigned struct {
83+
Nodes []Issue
84+
}
85+
Mentioned struct {
86+
Nodes []Issue
87+
}
88+
Authored struct {
89+
Nodes []Issue
90+
}
91+
HasIssuesEnabled bool
92+
}
9493
}
9594

9695
query := fragments + `
97-
query($owner: String!, $repo: String!, $viewer: String!, $per_page: Int = 10) {
98-
assigned: repository(owner: $owner, name: $repo) {
99-
issues(filterBy: {assignee: $viewer, states: OPEN}, first: $per_page, orderBy: {field: CREATED_AT, direction: DESC}) {
100-
nodes {
101-
...issue
102-
}
103-
}
104-
}
105-
mentioned: repository(owner: $owner, name: $repo) {
106-
issues(filterBy: {mentioned: $viewer, states: OPEN}, first: $per_page, orderBy: {field: CREATED_AT, direction: DESC}) {
107-
nodes {
108-
...issue
109-
}
110-
}
111-
}
112-
authored: repository(owner: $owner, name: $repo) {
113-
issues(filterBy: {createdBy: $viewer, states: OPEN}, first: $per_page, orderBy: {field: CREATED_AT, direction: DESC}) {
114-
nodes {
115-
...issue
116-
}
117-
}
118-
}
119-
}
120-
`
96+
query($owner: String!, $repo: String!, $viewer: String!, $per_page: Int = 10) {
97+
repository(owner: $owner, name: $repo) {
98+
hasIssuesEnabled
99+
assigned: issues(filterBy: {assignee: $viewer, states: OPEN}, first: $per_page, orderBy: {field: CREATED_AT, direction: DESC}) {
100+
nodes {
101+
...issue
102+
}
103+
}
104+
mentioned: issues(filterBy: {mentioned: $viewer, states: OPEN}, first: $per_page, orderBy: {field: CREATED_AT, direction: DESC}) {
105+
nodes {
106+
...issue
107+
}
108+
}
109+
authored: issues(filterBy: {createdBy: $viewer, states: OPEN}, first: $per_page, orderBy: {field: CREATED_AT, direction: DESC}) {
110+
nodes {
111+
...issue
112+
}
113+
}
114+
}
115+
}`
121116

122117
owner := ghRepo.RepoOwner()
123118
repo := ghRepo.RepoName()
@@ -133,10 +128,14 @@ func IssueStatus(client *Client, ghRepo Repo, currentUsername string) (*IssuesPa
133128
return nil, err
134129
}
135130

131+
if !resp.Repository.HasIssuesEnabled {
132+
return nil, fmt.Errorf("the '%s/%s' repository has disabled issues", owner, repo)
133+
}
134+
136135
payload := IssuesPayload{
137-
Assigned: resp.Assigned.Issues.Nodes,
138-
Mentioned: resp.Mentioned.Issues.Nodes,
139-
Authored: resp.Authored.Issues.Nodes,
136+
Assigned: resp.Repository.Assigned.Nodes,
137+
Mentioned: resp.Repository.Mentioned.Nodes,
138+
Authored: resp.Repository.Authored.Nodes,
140139
}
141140

142141
return &payload, nil
@@ -171,6 +170,7 @@ func IssueList(client *Client, ghRepo Repo, state string, labels []string, assig
171170
query := fragments + `
172171
query($owner: String!, $repo: String!, $limit: Int, $states: [IssueState!] = OPEN, $labels: [String!], $assignee: String) {
173172
repository(owner: $owner, name: $repo) {
173+
hasIssuesEnabled
174174
issues(first: $limit, orderBy: {field: CREATED_AT, direction: DESC}, states: $states, labels: $labels, filterBy: {assignee: $assignee}) {
175175
nodes {
176176
...issue
@@ -192,14 +192,23 @@ func IssueList(client *Client, ghRepo Repo, state string, labels []string, assig
192192
}
193193

194194
var resp struct {
195-
Repository apiIssues
195+
Repository struct {
196+
Issues struct {
197+
Nodes []Issue
198+
}
199+
HasIssuesEnabled bool
200+
}
196201
}
197202

198203
err := client.GraphQL(query, variables, &resp)
199204
if err != nil {
200205
return nil, err
201206
}
202207

208+
if !resp.Repository.HasIssuesEnabled {
209+
return nil, fmt.Errorf("the '%s/%s' repository has disabled issues", owner, repo)
210+
}
211+
203212
return resp.Repository.Issues.Nodes, nil
204213
}
205214

api/queries_pr.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ func PullRequestForBranch(client *Client, ghRepo Repo, branch string) (*PullRequ
366366
}
367367

368368
func CreatePullRequest(client *Client, ghRepo Repo, params map[string]interface{}) (*PullRequest, error) {
369-
repoID, err := GitHubRepoId(client, ghRepo)
369+
repo, err := GitHubRepo(client, ghRepo)
370370
if err != nil {
371371
return nil, err
372372
}
@@ -381,7 +381,7 @@ func CreatePullRequest(client *Client, ghRepo Repo, params map[string]interface{
381381
}`
382382

383383
inputParams := map[string]interface{}{
384-
"repositoryId": repoID,
384+
"repositoryId": repo.ID,
385385
}
386386
for key, val := range params {
387387
inputParams[key] = val

api/queries_repo.go

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,46 @@
11
package api
22

3-
import "fmt"
3+
import (
4+
"fmt"
45

5-
func GitHubRepoId(client *Client, ghRepo Repo) (string, error) {
6+
"github.com/pkg/errors"
7+
)
8+
9+
// Repository contains information about a GitHub repo
10+
type Repository struct {
11+
ID string
12+
HasIssuesEnabled bool
13+
}
14+
15+
// GitHubRepo looks up the node ID of a named repository
16+
func GitHubRepo(client *Client, ghRepo Repo) (*Repository, error) {
617
owner := ghRepo.RepoOwner()
718
repo := ghRepo.RepoName()
819

920
query := `
10-
query FindRepoID($owner:String!, $name:String!) {
11-
repository(owner:$owner, name:$name) {
12-
id
13-
}
21+
query($owner: String!, $name: String!) {
22+
repository(owner: $owner, name: $name) {
23+
id
24+
hasIssuesEnabled
25+
}
1426
}`
1527
variables := map[string]interface{}{
1628
"owner": owner,
1729
"name": repo,
1830
}
1931

2032
result := struct {
21-
Repository struct {
22-
Id string
23-
}
33+
Repository Repository
2434
}{}
2535
err := client.GraphQL(query, variables, &result)
26-
if err != nil || result.Repository.Id == "" {
27-
return "", fmt.Errorf("failed to determine GH repo ID: %s", err)
36+
37+
if err != nil || result.Repository.ID == "" {
38+
newErr := fmt.Errorf("failed to determine repository ID for '%s/%s'", owner, repo)
39+
if err != nil {
40+
newErr = errors.Wrap(err, newErr.Error())
41+
}
42+
return nil, newErr
2843
}
2944

30-
return result.Repository.Id, nil
45+
return &result.Repository, nil
3146
}

command/issue.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,14 @@ func issueCreate(cmd *cobra.Command, args []string) error {
257257
return err
258258
}
259259

260+
repo, err := api.GitHubRepo(apiClient, baseRepo)
261+
if err != nil {
262+
return err
263+
}
264+
if !repo.HasIssuesEnabled {
265+
return fmt.Errorf("the '%s/%s' repository has disabled issues", baseRepo.RepoOwner(), baseRepo.RepoName())
266+
}
267+
260268
title, err := cmd.Flags().GetString("title")
261269
if err != nil {
262270
return errors.Wrap(err, "could not parse title")
@@ -291,7 +299,7 @@ func issueCreate(cmd *cobra.Command, args []string) error {
291299
"body": body,
292300
}
293301

294-
newIssue, err := api.IssueCreate(apiClient, baseRepo, params)
302+
newIssue, err := api.IssueCreate(apiClient, repo, params)
295303
if err != nil {
296304
return err
297305
}

command/issue_test.go

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,12 @@ func TestIssueStatus_blankSlate(t *testing.T) {
4545
http := initFakeHTTP()
4646

4747
http.StubResponse(200, bytes.NewBufferString(`
48-
{ "data": {
49-
"assigned": { "issues": { "nodes": [] } },
50-
"mentioned": { "issues": { "nodes": [] } },
51-
"authored": { "issues": { "nodes": [] } }
52-
} }
48+
{ "data": { "repository": {
49+
"hasIssuesEnabled": true,
50+
"assigned": { "nodes": [] },
51+
"mentioned": { "nodes": [] },
52+
"authored": { "nodes": [] }
53+
} } }
5354
`))
5455

5556
output, err := RunCommand(issueStatusCmd, "issue status")
@@ -72,6 +73,22 @@ Issues opened by you
7273
}
7374
}
7475

76+
func TestIssueStatus_disabledIssues(t *testing.T) {
77+
initBlankContext("OWNER/REPO", "master")
78+
http := initFakeHTTP()
79+
80+
http.StubResponse(200, bytes.NewBufferString(`
81+
{ "data": { "repository": {
82+
"hasIssuesEnabled": false
83+
} } }
84+
`))
85+
86+
_, err := RunCommand(issueStatusCmd, "issue status")
87+
if err == nil || err.Error() != "the 'OWNER/REPO' repository has disabled issues" {
88+
t.Errorf("error running command `issue status`: %v", err)
89+
}
90+
}
91+
7592
func TestIssueList(t *testing.T) {
7693
initBlankContext("OWNER/REPO", "master")
7794
http := initFakeHTTP()
@@ -100,9 +117,15 @@ func TestIssueList(t *testing.T) {
100117
}
101118

102119
func TestIssueList_withFlags(t *testing.T) {
120+
initBlankContext("OWNER/REPO", "master")
103121
http := initFakeHTTP()
104122

105-
http.StubResponse(200, bytes.NewBufferString(`{"data": {}}`)) // Since we are testing that the flags are passed, we don't care about the response
123+
http.StubResponse(200, bytes.NewBufferString(`
124+
{ "data": { "repository": {
125+
"hasIssuesEnabled": true,
126+
"issues": { "nodes": [] }
127+
} } }
128+
`))
106129

107130
output, err := RunCommand(issueListCmd, "issue list -a probablyCher -l web,bug -s open")
108131
if err != nil {
@@ -127,6 +150,22 @@ func TestIssueList_withFlags(t *testing.T) {
127150
eq(t, reqBody.Variables.States, []string{"OPEN"})
128151
}
129152

153+
func TestIssueList_disabledIssues(t *testing.T) {
154+
initBlankContext("OWNER/REPO", "master")
155+
http := initFakeHTTP()
156+
157+
http.StubResponse(200, bytes.NewBufferString(`
158+
{ "data": { "repository": {
159+
"hasIssuesEnabled": false
160+
} } }
161+
`))
162+
163+
_, err := RunCommand(issueListCmd, "issue list")
164+
if err == nil || err.Error() != "the 'OWNER/REPO' repository has disabled issues" {
165+
t.Errorf("error running command `issue list`: %v", err)
166+
}
167+
}
168+
130169
func TestIssueView(t *testing.T) {
131170
initBlankContext("OWNER/REPO", "master")
132171
http := initFakeHTTP()
@@ -225,7 +264,8 @@ func TestIssueCreate(t *testing.T) {
225264

226265
http.StubResponse(200, bytes.NewBufferString(`
227266
{ "data": { "repository": {
228-
"id": "REPOID"
267+
"id": "REPOID",
268+
"hasIssuesEnabled": true
229269
} } }
230270
`))
231271
http.StubResponse(200, bytes.NewBufferString(`
@@ -258,6 +298,23 @@ func TestIssueCreate(t *testing.T) {
258298
eq(t, output.String(), "https://github.com/OWNER/REPO/issues/12\n")
259299
}
260300

301+
func TestIssueCreate_disabledIssues(t *testing.T) {
302+
initBlankContext("OWNER/REPO", "master")
303+
http := initFakeHTTP()
304+
305+
http.StubResponse(200, bytes.NewBufferString(`
306+
{ "data": { "repository": {
307+
"id": "REPOID",
308+
"hasIssuesEnabled": false
309+
} } }
310+
`))
311+
312+
_, err := RunCommand(issueCreateCmd, `issue create -t heres -b johnny`)
313+
if err == nil || err.Error() != "the 'OWNER/REPO' repository has disabled issues" {
314+
t.Errorf("error running command `issue create`: %v", err)
315+
}
316+
}
317+
261318
func TestIssueCreate_web(t *testing.T) {
262319
initBlankContext("OWNER/REPO", "master")
263320
initFakeHTTP()

test/fixtures/issueList.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"data": {
33
"repository": {
4+
"hasIssuesEnabled": true,
45
"issues": {
56
"nodes": [
67
{

0 commit comments

Comments
 (0)