Inconsistent use of template flags between `gh pr create --template` and `gh issue create --template`
Describe the bug
There are different, inconsistent behaviors using templates for creating issues versus pull requests along with incorrect documentation on the feature.
Both gh pr create --template and gh issue create --template say they use remote template file names ...
| cmd.Flags().StringVarP(&opts.Template, "template", "T", "", "Template `file` to use as starting body text") |
| fl.StringVarP(&opts.Template, "template", "T", "", "Template `file` to use as starting body text") |
Underlying code shows that only pull request templates have filename retrieved whereas issue templates use template name ...
| type issueTemplate struct { | |
| Gname string `graphql:"name"` | |
| Gbody string `graphql:"body"` | |
| Gtitle string `graphql:"title"` | |
| } | |
| type pullRequestTemplate struct { | |
| Gname string `graphql:"filename"` | |
| Gbody string `graphql:"body"` | |
| } | |
| func (t *issueTemplate) Name() string { | |
| return t.Gname | |
| } |
This leads to inconsistent feature behaviors when selecting a template based on user input
| func (m *templateManager) Select(name string) (Template, error) { | |
| if err := m.memoizedFetch(); err != nil { | |
| return nil, err | |
| } | |
| if len(m.templates) == 0 { | |
| return nil, errors.New("no templates found") | |
| } | |
| for _, t := range m.templates { | |
| if t.Name() == name { | |
| return t, nil | |
| } | |
| } | |
| return nil, fmt.Errorf("template %q not found", name) | |
| } |
Steps to reproduce the behavior
-
Create markdown-based issue template in repository
- Use
foo-issue.mdfor the template filename - Use "Foo Issue" for the template name
NOTE: This should not be an issue form as those are not supported by API or GitHub CLI currently.
- Use
-
Create pull request template in repository
- Use
foo-pr.mdfor the template filename - Use "Foo PR" for the template name
- Use
-
Successfully create pull request using template's filename:
gh pr create --template foo-pr.md -
Unsuccessfully create pull request using template's name:
gh pr create --template "Foo PR" -
Unsuccessfully create issue using template's filename:
gh issue create --template foo-issue.md -
Successfully create issue using template's filename:
gh issue create --template "Foo Issue"
Expected vs actual behavior
I expect gh pr create --template and gh issue create --template experiences to be consistent; basically pick one:
- Check only template names
- Check only template filenames
- Check both template names and filenames
Logs
➜ planning git:(main) ✗ GH_DEBUG=api gh issue create --template "bug_report.md" [git remote -v] [git config --get-regexp ^remote\..*\.gh-resolved$] * Request at 2025-01-08 17:24:56.51639 +0100 CET m=+0.181550667 * Request to https://api.github.com/graphql > POST /graphql HTTP/1.1 > Host: api.github.com > Accept: application/vnd.github.merge-info-preview+json, application/vnd.github.nebula-preview > Authorization: token ████████████████████ > Content-Length: 390 > Content-Type: application/json; charset=utf-8 > Graphql-Features: merge_queue > Time-Zone: Europe/Berlin > User-Agent: GitHub CLI 2.58.0 GraphQL query: fragment repo on Repository { id name owner { login } viewerPermission defaultBranchRef { name } isPrivate } query RepositoryNetwork { viewer { login } repo_000: repository(owner: "nors-24", name: "planning") { ...repo parent { ...repo } } } GraphQL variables: null < HTTP/2.0 200 OK < Access-Control-Allow-Origin: * < Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset < Content-Security-Policy: default-src 'none' < Content-Type: application/json; charset=utf-8 < Date: Wed, 08 Jan 2025 16:24:56 GMT < Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin < Server: github.com < Strict-Transport-Security: max-age=31536000; includeSubdomains; preload < Vary: Accept-Encoding, Accept, X-Requested-With < X-Accepted-Oauth-Scopes: repo < X-Content-Type-Options: nosniff < X-Frame-Options: deny < X-Github-Media-Type: github.v4; param=merge-info-preview.nebula-preview; format=json < X-Github-Request-Id: F0FD:EBDF7:1A0CBB:1A844F:677EA6D8 < X-Oauth-Client-Id: 178c6fc778ccc68e1d6a < X-Oauth-Scopes: admin:public_key, codespace, gist, read:org, read:packages, repo, workflow < X-Ratelimit-Limit: 5000 < X-Ratelimit-Remaining: 5000 < X-Ratelimit-Reset: 1736356418 < X-Ratelimit-Resource: graphql < X-Ratelimit-Used: 99 < X-Xss-Protection: 0 { "data": { "viewer": { "login": "norascheuch" }, "repo_000": { "id": "R_kgDONVDy7g", "name": "planning", "owner": { "login": "nors-24" }, "viewerPermission": "ADMIN", "defaultBranchRef": { "name": "main" }, "isPrivate": true, "parent": null } } } * Request took 369.033167ms Creating issue in nors-24/planning * Request at 2025-01-08 17:24:56.93244 +0100 CET m=+0.597596917 * Request to https://api.github.com/graphql > POST /graphql HTTP/1.1 > Host: api.github.com > Accept: application/vnd.github.merge-info-preview+json, application/vnd.github.nebula-preview > Authorization: token ████████████████████ > Content-Length: 517 > Content-Type: application/json; charset=utf-8 > Graphql-Features: merge_queue > Time-Zone: Europe/Berlin > User-Agent: GitHub CLI 2.58.0 GraphQL query: fragment repo on Repository { id name owner { login } hasIssuesEnabled description hasWikiEnabled viewerPermission defaultBranchRef { name } } query RepositoryInfo($owner: String!, $name: String!) { repository(owner: $owner, name: $name) { ...repo parent { ...repo } mergeCommitAllowed rebaseMergeAllowed squashMergeAllowed } } GraphQL variables: {"name":"planning","owner":"nors-24"} < HTTP/2.0 200 OK < Access-Control-Allow-Origin: * < Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset < Content-Security-Policy: default-src 'none' < Content-Type: application/json; charset=utf-8 < Date: Wed, 08 Jan 2025 16:24:57 GMT < Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin < Server: github.com < Strict-Transport-Security: max-age=31536000; includeSubdomains; preload < Vary: Accept-Encoding, Accept, X-Requested-With < X-Accepted-Oauth-Scopes: repo < X-Content-Type-Options: nosniff < X-Frame-Options: deny < X-Github-Media-Type: github.v4; param=merge-info-preview.nebula-preview; format=json < X-Github-Request-Id: F0FD:EBDF7:1A0DD4:1A857F:677EA6D8 < X-Oauth-Client-Id: 178c6fc778ccc68e1d6a < X-Oauth-Scopes: admin:public_key, codespace, gist, read:org, read:packages, repo, workflow < X-Ratelimit-Limit: 5000 < X-Ratelimit-Remaining: 5000 < X-Ratelimit-Reset: 1736356418 < X-Ratelimit-Resource: graphql < X-Ratelimit-Used: 100 < X-Xss-Protection: 0 { "data": { "repository": { "id": "R_kgDONVDy7g", "name": "planning", "owner": { "login": "nors-24" }, "hasIssuesEnabled": true, "description": null, "hasWikiEnabled": false, "viewerPermission": "ADMIN", "defaultBranchRef": { "name": "main" }, "parent": null, "mergeCommitAllowed": true, "rebaseMergeAllowed": true, "squashMergeAllowed": true } } } * Request took 344.753084ms ? Title title * Request at 2025-01-08 17:26:03.396025 +0100 CET m=+67.060513626 * Request to https://api.github.com/graphql > POST /graphql HTTP/1.1 > Host: api.github.com > Accept: application/vnd.github.merge-info-preview+json, application/vnd.github.nebula-preview > Authorization: token ████████████████████ > Content-Length: 185 > Content-Type: application/json > Graphql-Features: merge_queue > Time-Zone: Europe/Berlin > User-Agent: GitHub CLI 2.58.0 GraphQL query: query IssueTemplates($name:String!$owner:String!){repository(owner: $owner, name: $name){issueTemplates{name,body,title}}} GraphQL variables: {"name":"planning","owner":"nors-24"} < HTTP/2.0 200 OK < Access-Control-Allow-Origin: * < Access-Control-Expose-Headers: ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset < Content-Security-Policy: default-src 'none' < Content-Type: application/json; charset=utf-8 < Date: Wed, 08 Jan 2025 16:26:03 GMT < Referrer-Policy: origin-when-cross-origin, strict-origin-when-cross-origin < Server: github.com < Strict-Transport-Security: max-age=31536000; includeSubdomains; preload < Vary: Accept-Encoding, Accept, X-Requested-With < X-Accepted-Oauth-Scopes: repo < X-Content-Type-Options: nosniff < X-Frame-Options: deny < X-Github-Media-Type: github.v4; param=merge-info-preview.nebula-preview; format=json < X-Github-Request-Id: F110:F3BC3:1C3B40:1CB774:677EA71B < X-Oauth-Client-Id: 178c6fc778ccc68e1d6a < X-Oauth-Scopes: admin:public_key, codespace, gist, read:org, read:packages, repo, workflow < X-Ratelimit-Limit: 5000 < X-Ratelimit-Remaining: 5000 < X-Ratelimit-Reset: 1736356418 < X-Ratelimit-Resource: graphql < X-Ratelimit-Used: 117 < X-Xss-Protection: 0 { "data": { "repository": { "issueTemplates": [ { "name": "Bug report", "body": "**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Desktop (please complete the following information):**\n - OS: [e.g. iOS]\n - Browser [e.g. chrome, safari]\n - Version [e.g. 22]\n\n**Smartphone (please complete the following information):**\n - Device: [e.g. iPhone6]\n - OS: [e.g. iOS8.1]\n - Browser [e.g. stock browser, safari]\n - Version [e.g. 22]\n\n**Additional context**\nAdd any other context about the problem here.\n", "title": "" }, { "name": "Task Issue", "body": "# Notes\n", "title": "" }, { "name": "Tracking Issue", "body": "# Tracked Issue:\n - [ ] \n\n# Related PRs:\n - [ ] \n\n# Notes\n", "title": "" } ] } } } * Request took 449.228291ms [git rev-parse --show-toplevel] X operation failed. To restore: gh issue create --recover /var/folders/_p/rfdm0l5x105flclh25v17tpr0000gn/T/gh1852231467.json template "bug_report.md" not found