Repository navigation
feat: Add support for viewing autolink references #10324
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
e8475d9
Initial, working implementation
hoffm f941608
Partial testing for view
hoffm 11ce0c6
Updates following renaming domain to shared
hoffm 58d84a4
Shorten description
hoffm 32ee4db
Autolink view HTTP tests
hoffm 8f55dbc
Error case test for viewRun
hoffm 8b7d6d1
Remove unused test field
hoffm 21a5267
Remove unused test field
hoffm af538b2
Expand test case
andyfeller fe21e10
Keeping autolink IDs the same in all test cases
andyfeller 9725a32
Merge branch 'trunk' into view-autolinks
hoffm e4d720b
Remove redundant error check
hoffm b23cf6e
Update formatting for autolink output
hoffm d609c40
Merge branch 'trunk' into view-autolinks
hoffm File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| package view | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "fmt" | ||
| "net/http" | ||
|
|
||
| "github.com/cli/cli/v2/api" | ||
| "github.com/cli/cli/v2/internal/ghinstance" | ||
| "github.com/cli/cli/v2/internal/ghrepo" | ||
| "github.com/cli/cli/v2/pkg/cmd/repo/autolink/shared" | ||
| ) | ||
|
|
||
| type AutolinkViewer struct { | ||
| HTTPClient *http.Client | ||
| } | ||
|
|
||
| func (a *AutolinkViewer) View(repo ghrepo.Interface, id string) (*shared.Autolink, error) { | ||
| path := fmt.Sprintf("repos/%s/%s/autolinks/%s", repo.RepoOwner(), repo.RepoName(), id) | ||
| url := ghinstance.RESTPrefix(repo.RepoHost()) + path | ||
| req, err := http.NewRequest(http.MethodGet, url, nil) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| resp, err := a.HTTPClient.Do(req) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| defer resp.Body.Close() | ||
|
|
||
| if resp.StatusCode == http.StatusNotFound { | ||
| return nil, fmt.Errorf("HTTP 404: Either no autolink with this ID exists for this repository or you are missing admin rights to the repository. (https://api.github.com/%s)", path) | ||
| } else if resp.StatusCode > 299 { | ||
| return nil, api.HandleHTTPError(resp) | ||
| } | ||
|
|
||
| var autolink shared.Autolink | ||
| err = json.NewDecoder(resp.Body).Decode(&autolink) | ||
|
|
||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| return &autolink, nil | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,102 @@ | ||
| package view | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "net/http" | ||
| "testing" | ||
|
|
||
| "github.com/cli/cli/v2/internal/ghrepo" | ||
| "github.com/cli/cli/v2/pkg/cmd/repo/autolink/shared" | ||
| "github.com/cli/cli/v2/pkg/httpmock" | ||
| "github.com/stretchr/testify/assert" | ||
| "github.com/stretchr/testify/require" | ||
| ) | ||
|
|
||
| func TestAutolinkViewer_View(t *testing.T) { | ||
| repo := ghrepo.New("OWNER", "REPO") | ||
|
|
||
| tests := []struct { | ||
| name string | ||
| id string | ||
| stubStatus int | ||
| stubRespJSON string | ||
|
|
||
| expectedAutolink *shared.Autolink | ||
| expectErr bool | ||
| expectedErrMsg string | ||
| }{ | ||
| { | ||
| name: "200 successful alphanumeric view", | ||
| id: "123", | ||
| stubStatus: 200, | ||
| stubRespJSON: `{ | ||
| "id": 123, | ||
| "key_prefix": "TICKET-", | ||
| "url_template": "https://example.com/TICKET?query=<num>", | ||
| "is_alphanumeric": true | ||
| }`, | ||
| expectedAutolink: &shared.Autolink{ | ||
| ID: 123, | ||
| KeyPrefix: "TICKET-", | ||
| URLTemplate: "https://example.com/TICKET?query=<num>", | ||
| IsAlphanumeric: true, | ||
| }, | ||
| }, | ||
|
andyfeller marked this conversation as resolved.
|
||
| { | ||
| name: "200 successful numeric view", | ||
| id: "123", | ||
| stubStatus: 200, | ||
| stubRespJSON: `{ | ||
| "id": 123, | ||
| "key_prefix": "TICKET-", | ||
| "url_template": "https://example.com/TICKET?query=<num>", | ||
| "is_alphanumeric": false | ||
| }`, | ||
| expectedAutolink: &shared.Autolink{ | ||
| ID: 123, | ||
| KeyPrefix: "TICKET-", | ||
| URLTemplate: "https://example.com/TICKET?query=<num>", | ||
| IsAlphanumeric: false, | ||
| }, | ||
| }, | ||
| { | ||
| name: "404 repo or autolink not found", | ||
| id: "123", | ||
| stubStatus: 404, | ||
| stubRespJSON: `{ | ||
| "message": "Not Found", | ||
| "documentation_url": "https://docs.github.com/rest/repos/autolinks#get-an-autolink-reference-of-a-repository", | ||
| "status": "404" | ||
| }`, | ||
| expectErr: true, | ||
| expectedErrMsg: "HTTP 404: Either no autolink with this ID exists for this repository or you are missing admin rights to the repository. (https://api.github.com/repos/OWNER/REPO/autolinks/123)", | ||
| }, | ||
| } | ||
|
|
||
| for _, tt := range tests { | ||
| t.Run(tt.name, func(t *testing.T) { | ||
| reg := &httpmock.Registry{} | ||
| reg.Register( | ||
| httpmock.REST( | ||
| http.MethodGet, | ||
| fmt.Sprintf("repos/%s/%s/autolinks/%s", repo.RepoOwner(), repo.RepoName(), tt.id), | ||
| ), | ||
| httpmock.StatusStringResponse(tt.stubStatus, tt.stubRespJSON), | ||
| ) | ||
| defer reg.Verify(t) | ||
|
|
||
| autolinkCreator := &AutolinkViewer{ | ||
| HTTPClient: &http.Client{Transport: reg}, | ||
| } | ||
|
|
||
| autolink, err := autolinkCreator.View(repo, tt.id) | ||
|
|
||
| if tt.expectErr { | ||
| require.EqualError(t, err, tt.expectedErrMsg) | ||
| } else { | ||
| require.NoError(t, err) | ||
| assert.Equal(t, tt.expectedAutolink, autolink) | ||
| } | ||
| }) | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| package view | ||
|
|
||
| import ( | ||
| "fmt" | ||
|
|
||
| "github.com/cli/cli/v2/internal/browser" | ||
| "github.com/cli/cli/v2/internal/ghrepo" | ||
| "github.com/cli/cli/v2/pkg/cmd/repo/autolink/shared" | ||
| "github.com/cli/cli/v2/pkg/cmdutil" | ||
| "github.com/cli/cli/v2/pkg/iostreams" | ||
| "github.com/spf13/cobra" | ||
| ) | ||
|
|
||
| type viewOptions struct { | ||
| BaseRepo func() (ghrepo.Interface, error) | ||
| Browser browser.Browser | ||
| AutolinkClient AutolinkViewClient | ||
| IO *iostreams.IOStreams | ||
| Exporter cmdutil.Exporter | ||
|
|
||
| ID string | ||
| } | ||
|
|
||
| type AutolinkViewClient interface { | ||
| View(repo ghrepo.Interface, id string) (*shared.Autolink, error) | ||
| } | ||
|
|
||
| func NewCmdView(f *cmdutil.Factory, runF func(*viewOptions) error) *cobra.Command { | ||
| opts := &viewOptions{ | ||
| Browser: f.Browser, | ||
| IO: f.IOStreams, | ||
| } | ||
|
|
||
| cmd := &cobra.Command{ | ||
| Use: "view <id>", | ||
| Short: "View an autolink reference", | ||
| Long: "View an autolink reference for a repository.", | ||
| Args: cobra.ExactArgs(1), | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| httpClient, err := f.HttpClient() | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| opts.BaseRepo = f.BaseRepo | ||
| opts.ID = args[0] | ||
| opts.AutolinkClient = &AutolinkViewer{HTTPClient: httpClient} | ||
|
|
||
| if runF != nil { | ||
| return runF(opts) | ||
| } | ||
|
|
||
| return viewRun(opts) | ||
| }, | ||
| } | ||
|
|
||
| cmdutil.AddJSONFlags(cmd, &opts.Exporter, shared.AutolinkFields) | ||
|
|
||
| return cmd | ||
| } | ||
|
|
||
| func viewRun(opts *viewOptions) error { | ||
| repo, err := opts.BaseRepo() | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| out := opts.IO.Out | ||
| cs := opts.IO.ColorScheme() | ||
|
|
||
| autolink, err := opts.AutolinkClient.View(repo, opts.ID) | ||
|
|
||
| if err != nil { | ||
| return fmt.Errorf("%s %w", cs.Red("error viewing autolink:"), err) | ||
| } | ||
|
|
||
| if opts.Exporter != nil { | ||
| return opts.Exporter.Write(opts.IO, autolink) | ||
| } | ||
|
|
||
| fmt.Fprintf(out, "Autolink in %s\n\n", ghrepo.FullName(repo)) | ||
|
|
||
| fmt.Fprint(out, cs.Bold("ID: ")) | ||
| fmt.Fprintln(out, cs.Cyanf("%d", autolink.ID)) | ||
|
|
||
| fmt.Fprint(out, cs.Bold("Key Prefix: ")) | ||
| fmt.Fprintln(out, autolink.KeyPrefix) | ||
|
|
||
| fmt.Fprint(out, cs.Bold("URL Template: ")) | ||
| fmt.Fprintln(out, autolink.URLTemplate) | ||
|
|
||
| fmt.Fprint(out, cs.Bold("Alphanumeric: ")) | ||
| fmt.Fprintln(out, autolink.IsAlphanumeric) | ||
|
|
||
| return nil | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just noting it took me a hot minute to see
pathbeing reused later for error messaging if 404 arises.