Skip to content

Commit 9330cac

Browse files
authored
Breaking changes for v2.0.0 (#95)
* Fix up repository package * Refactor api package * Fix up browser package * Fix up config package * Fix up template package * Wrap shurcool Errors in GQLError (#104) * Rename CurrentRepository to Current * Fix up tests * Change all references of GQL to GraphQL and references of gql to graphQL * Update to Go 1.20 * Update package to V2 * Update README
1 parent 026e976 commit 9330cac

37 files changed

+1079
-1006
lines changed

.github/workflows/lint.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ jobs:
1010
- name: Set up Go
1111
uses: actions/setup-go@v3
1212
with:
13-
go-version: "1.19"
13+
go-version: "1.20"
1414

1515
- name: Checkout repository
1616
uses: actions/checkout@v3

.github/workflows/test.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ jobs:
88
fail-fast: false
99
matrix:
1010
os: [ubuntu-latest, windows-latest, macos-latest]
11-
go: ["1.19"]
11+
go: ["1.20"]
1212

1313
runs-on: ${{ matrix.os }}
1414

README.md

+11-12
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,41 @@
44

55
Modules from this library will obey GitHub CLI conventions by default:
66

7-
- [`CurrentRepository()`](https://pkg.go.dev/github.com/cli/go-gh#CurrentRepository) respects the value of the `GH_REPO` environment variable and reads from git remote configuration as fallback.
7+
- [`repository.Current()`](https://pkg.go.dev/github.com/cli/go-gh/v2/pkg/repository#current) respects the value of the `GH_REPO` environment variable and reads from git remote configuration as fallback.
88

99
- GitHub API requests will be authenticated using the same mechanism as `gh`, i.e. using the values of `GH_TOKEN` and `GH_HOST` environment variables and falling back to the user's stored OAuth token.
1010

11-
- [Terminal capabilities](https://pkg.go.dev/github.com/cli/go-gh/pkg/term) are determined by taking environment variables `GH_FORCE_TTY`, `NO_COLOR`, `CLICOLOR`, etc. into account.
11+
- [Terminal capabilities](https://pkg.go.dev/github.com/cli/go-gh/v2/pkg/term) are determined by taking environment variables `GH_FORCE_TTY`, `NO_COLOR`, `CLICOLOR`, etc. into account.
1212

13-
- Generating [table](https://pkg.go.dev/github.com/cli/go-gh/pkg/tableprinter) or [Go template](https://pkg.go.dev/github.com/cli/go-gh/pkg/template) output uses the same engine as gh.
13+
- Generating [table](https://pkg.go.dev/github.com/cli/go-gh/v2/pkg/tableprinter) or [Go template](https://pkg.go.dev/github.com/cli/go-gh/pkg/template) output uses the same engine as gh.
1414

15-
- The [`browser`](https://pkg.go.dev/github.com/cli/go-gh/pkg/browser) module activates the user's preferred web browser.
15+
- The [`browser`](https://pkg.go.dev/github.com/cli/go-gh/v2/pkg/browser) module activates the user's preferred web browser.
1616

1717
## Usage
1818

19-
See the full `go-gh` [reference documentation](https://pkg.go.dev/github.com/cli/go-gh) for more information
19+
See the full `go-gh` [reference documentation](https://pkg.go.dev/github.com/cli/go-gh/v2) for more information
2020

2121
```golang
2222
package main
2323

2424
import (
2525
"fmt"
2626
"log"
27-
"github.com/cli/go-gh"
27+
"github.com/cli/go-gh/v2"
2828
)
2929

3030
func main() {
31-
// These examples assume `gh` is installed and has been authenticated
31+
// These examples assume `gh` is installed and has been authenticated.
3232

33-
// Shell out to a gh command and read its output
33+
// Shell out to a gh command and read its output.
3434
issueList, _, err := gh.Exec("issue", "list", "--repo", "cli/cli", "--limit", "5")
3535
if err != nil {
3636
log.Fatal(err)
3737
}
3838
fmt.Println(issueList.String())
39-
40-
// Use an API helper to grab repository tags
41-
client, err := gh.RESTClient(nil)
39+
40+
// Use an API client to retrieve repository tags.
41+
client, err := api.DefaultRESTClient()
4242
if err != nil {
4343
log.Fatal(err)
4444
}
@@ -59,7 +59,6 @@ See [examples][] for more demonstrations of usage.
5959

6060
If anything feels off, or if you feel that some functionality is missing, please check out our [contributing docs][contributing]. There you will find instructions for sharing your feedback and for submitting pull requests to the project. Thank you!
6161

62-
6362
[extensions]: https://docs.github.com/en/github-cli/github-cli/creating-github-cli-extensions
6463
[examples]: ./example_gh_test.go
6564
[contributing]: ./.github/CONTRIBUTING.md

example_gh_test.go

+26-25
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ import (
1010
"regexp"
1111
"time"
1212

13-
gh "github.com/cli/go-gh"
14-
"github.com/cli/go-gh/pkg/api"
15-
"github.com/cli/go-gh/pkg/tableprinter"
16-
"github.com/cli/go-gh/pkg/term"
13+
gh "github.com/cli/go-gh/v2"
14+
"github.com/cli/go-gh/v2/pkg/api"
15+
"github.com/cli/go-gh/v2/pkg/repository"
16+
"github.com/cli/go-gh/v2/pkg/tableprinter"
17+
"github.com/cli/go-gh/v2/pkg/term"
1718
graphql "github.com/cli/shurcooL-graphql"
1819
)
1920

@@ -29,8 +30,8 @@ func ExampleExec() {
2930
}
3031

3132
// Get tags from cli/cli repository using REST API.
32-
func ExampleRESTClient_simple() {
33-
client, err := gh.RESTClient(nil)
33+
func ExampleDefaultRESTClient() {
34+
client, err := api.DefaultRESTClient()
3435
if err != nil {
3536
log.Fatal(err)
3637
}
@@ -44,14 +45,14 @@ func ExampleRESTClient_simple() {
4445

4546
// Get tags from cli/cli repository using REST API.
4647
// Specifying host, auth token, headers and logging to stdout.
47-
func ExampleRESTClient_advanced() {
48+
func ExampleRESTClient() {
4849
opts := api.ClientOptions{
4950
Host: "github.com",
5051
AuthToken: "xxxxxxxxxx", // Replace with valid auth token.
5152
Headers: map[string]string{"Time-Zone": "America/Los_Angeles"},
5253
Log: os.Stdout,
5354
}
54-
client, err := gh.RESTClient(&opts)
55+
client, err := api.NewRESTClient(opts)
5556
if err != nil {
5657
log.Fatal(err)
5758
}
@@ -68,7 +69,7 @@ func ExampleRESTClient_request() {
6869
opts := api.ClientOptions{
6970
Headers: map[string]string{"Accept": "application/octet-stream"},
7071
}
71-
client, err := gh.RESTClient(&opts)
72+
client, err := api.NewRESTClient(opts)
7273
if err != nil {
7374
log.Fatal(err)
7475
}
@@ -102,7 +103,7 @@ func ExampleRESTClient_pagination() {
102103
}
103104
return "", false
104105
}
105-
client, err := gh.RESTClient(nil)
106+
client, err := api.DefaultRESTClient()
106107
if err != nil {
107108
log.Fatal(err)
108109
}
@@ -132,9 +133,9 @@ func ExampleRESTClient_pagination() {
132133
}
133134
}
134135

135-
// Query tags from cli/cli repository using GQL API.
136-
func ExampleGQLClient_simple() {
137-
client, err := gh.GQLClient(nil)
136+
// Query tags from cli/cli repository using GraphQL API.
137+
func ExampleDefaultGraphQLClient() {
138+
client, err := api.DefaultGraphQLClient()
138139
if err != nil {
139140
log.Fatal(err)
140141
}
@@ -160,14 +161,14 @@ func ExampleGQLClient_simple() {
160161
fmt.Println(query)
161162
}
162163

163-
// Query tags from cli/cli repository using GQL API.
164+
// Query tags from cli/cli repository using GraphQL API.
164165
// Enable caching and request timeout.
165-
func ExampleGQLClient_advanced() {
166+
func ExampleGraphQLClient() {
166167
opts := api.ClientOptions{
167168
EnableCache: true,
168169
Timeout: 5 * time.Second,
169170
}
170-
client, err := gh.GQLClient(&opts)
171+
client, err := api.NewGraphQLClient(opts)
171172
if err != nil {
172173
log.Fatal(err)
173174
}
@@ -193,9 +194,9 @@ func ExampleGQLClient_advanced() {
193194
fmt.Println(query)
194195
}
195196

196-
// Add a star to the cli/go-gh repository using the GQL API.
197-
func ExampleGQLClient_mutate_simple() {
198-
client, err := gh.GQLClient(nil)
197+
// Add a star to the cli/go-gh repository using the GraphQL API.
198+
func ExampleGraphQLClient_mutate() {
199+
client, err := api.DefaultGraphQLClient()
199200
if err != nil {
200201
log.Fatal(err)
201202
}
@@ -228,9 +229,9 @@ func ExampleGQLClient_mutate_simple() {
228229
fmt.Println(mutation.AddStar.Starrable.Repository.StargazerCount)
229230
}
230231

231-
// Query releases from cli/cli repository using GQL API with paginated results.
232-
func ExampleGQLClient_pagination() {
233-
client, err := gh.GQLClient(nil)
232+
// Query releases from cli/cli repository using GraphQL API with paginated results.
233+
func ExampleGraphQLClient_pagination() {
234+
client, err := api.DefaultGraphQLClient()
234235
if err != nil {
235236
log.Fatal(err)
236237
}
@@ -268,12 +269,12 @@ func ExampleGQLClient_pagination() {
268269
}
269270

270271
// Get repository for the current directory.
271-
func ExampleCurrentRepository() {
272-
repo, err := gh.CurrentRepository()
272+
func ExampleCurrent() {
273+
repo, err := repository.Current()
273274
if err != nil {
274275
log.Fatal(err)
275276
}
276-
fmt.Printf("%s/%s/%s\n", repo.Host(), repo.Owner(), repo.Name())
277+
fmt.Printf("%s/%s/%s\n", repo.Host, repo.Owner, repo.Name)
277278
}
278279

279280
// Print tabular data to a terminal or in machine-readable format for scripts.

gh.go

-134
Original file line numberDiff line numberDiff line change
@@ -8,21 +8,11 @@ package gh
88
import (
99
"bytes"
1010
"context"
11-
"errors"
1211
"fmt"
1312
"io"
14-
"net/http"
1513
"os"
1614
"os/exec"
1715

18-
iapi "github.com/cli/go-gh/internal/api"
19-
"github.com/cli/go-gh/internal/git"
20-
irepo "github.com/cli/go-gh/internal/repository"
21-
"github.com/cli/go-gh/pkg/api"
22-
"github.com/cli/go-gh/pkg/auth"
23-
"github.com/cli/go-gh/pkg/config"
24-
repo "github.com/cli/go-gh/pkg/repository"
25-
"github.com/cli/go-gh/pkg/ssh"
2616
"github.com/cli/safeexec"
2717
)
2818

@@ -76,127 +66,3 @@ func run(ctx context.Context, ghExe string, env []string, stdin io.Reader, stdou
7666
}
7767
return nil
7868
}
79-
80-
// RESTClient builds a client to send requests to GitHub REST API endpoints.
81-
// As part of the configuration a hostname, auth token, default set of headers,
82-
// and unix domain socket are resolved from the gh environment configuration.
83-
// These behaviors can be overridden using the opts argument.
84-
func RESTClient(opts *api.ClientOptions) (api.RESTClient, error) {
85-
if opts == nil {
86-
opts = &api.ClientOptions{}
87-
}
88-
if optionsNeedResolution(opts) {
89-
err := resolveOptions(opts)
90-
if err != nil {
91-
return nil, err
92-
}
93-
}
94-
return iapi.NewRESTClient(opts.Host, opts), nil
95-
}
96-
97-
// GQLClient builds a client to send requests to GitHub GraphQL API endpoints.
98-
// As part of the configuration a hostname, auth token, default set of headers,
99-
// and unix domain socket are resolved from the gh environment configuration.
100-
// These behaviors can be overridden using the opts argument.
101-
func GQLClient(opts *api.ClientOptions) (api.GQLClient, error) {
102-
if opts == nil {
103-
opts = &api.ClientOptions{}
104-
}
105-
if optionsNeedResolution(opts) {
106-
err := resolveOptions(opts)
107-
if err != nil {
108-
return nil, err
109-
}
110-
}
111-
return iapi.NewGQLClient(opts.Host, opts), nil
112-
}
113-
114-
// HTTPClient builds a client that can be passed to another library.
115-
// As part of the configuration a hostname, auth token, default set of headers,
116-
// and unix domain socket are resolved from the gh environment configuration.
117-
// These behaviors can be overridden using the opts argument. In this instance
118-
// providing opts.Host will not change the destination of your request as it is
119-
// the responsibility of the consumer to configure this. However, if opts.Host
120-
// does not match the request host, the auth token will not be added to the headers.
121-
// This is to protect against the case where tokens could be sent to an arbitrary
122-
// host.
123-
func HTTPClient(opts *api.ClientOptions) (*http.Client, error) {
124-
if opts == nil {
125-
opts = &api.ClientOptions{}
126-
}
127-
if optionsNeedResolution(opts) {
128-
err := resolveOptions(opts)
129-
if err != nil {
130-
return nil, err
131-
}
132-
}
133-
client := iapi.NewHTTPClient(opts)
134-
return &client, nil
135-
}
136-
137-
// CurrentRepository uses git remotes to determine the GitHub repository
138-
// the current directory is tracking.
139-
func CurrentRepository() (repo.Repository, error) {
140-
override := os.Getenv("GH_REPO")
141-
if override != "" {
142-
return repo.Parse(override)
143-
}
144-
145-
remotes, err := git.Remotes()
146-
if err != nil {
147-
return nil, err
148-
}
149-
if len(remotes) == 0 {
150-
return nil, errors.New("unable to determine current repository, no git remotes configured for this repository")
151-
}
152-
153-
translator := ssh.NewTranslator()
154-
for _, r := range remotes {
155-
if r.FetchURL != nil {
156-
r.FetchURL = translator.Translate(r.FetchURL)
157-
}
158-
if r.PushURL != nil {
159-
r.PushURL = translator.Translate(r.PushURL)
160-
}
161-
}
162-
163-
hosts := auth.KnownHosts()
164-
165-
filteredRemotes := remotes.FilterByHosts(hosts)
166-
if len(filteredRemotes) == 0 {
167-
return nil, errors.New("unable to determine current repository, none of the git remotes configured for this repository point to a known GitHub host")
168-
}
169-
170-
r := filteredRemotes[0]
171-
return irepo.New(r.Host, r.Owner, r.Repo), nil
172-
}
173-
174-
func optionsNeedResolution(opts *api.ClientOptions) bool {
175-
if opts.Host == "" {
176-
return true
177-
}
178-
if opts.AuthToken == "" {
179-
return true
180-
}
181-
if opts.UnixDomainSocket == "" && opts.Transport == nil {
182-
return true
183-
}
184-
return false
185-
}
186-
187-
func resolveOptions(opts *api.ClientOptions) error {
188-
cfg, _ := config.Read()
189-
if opts.Host == "" {
190-
opts.Host, _ = auth.DefaultHost()
191-
}
192-
if opts.AuthToken == "" {
193-
opts.AuthToken, _ = auth.TokenForHost(opts.Host)
194-
if opts.AuthToken == "" {
195-
return fmt.Errorf("authentication token not found for host %s", opts.Host)
196-
}
197-
}
198-
if opts.UnixDomainSocket == "" && cfg != nil {
199-
opts.UnixDomainSocket, _ = cfg.Get([]string{"http_unix_socket"})
200-
}
201-
return nil
202-
}

0 commit comments

Comments
 (0)