Skip to content

Commit 7d0de33

Browse files
committed
fixup! feat: Add new gh client implementation
1 parent ded4e69 commit 7d0de33

15 files changed

Lines changed: 942 additions & 158 deletions

.github/workflows/dotcom-acceptance-tests.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ jobs:
109109
GITHUB_OWNER: ${{ case(matrix.mode == 'individual', vars.GH_TEST_LOGIN, matrix.mode == 'organization', vars.GH_TEST_ORG_NAME, '') }}
110110
GITHUB_USERNAME: ${{ vars.GH_TEST_LOGIN }}
111111
GITHUB_ENTERPRISE_SLUG: ${{ vars.GH_TEST_ENTERPRISE_SLUG }}
112+
GITHUB_LEGACY_CLIENT: "false"
112113
GH_TEST_AUTH_MODE: ${{ matrix.mode }}
113114
GH_TEST_USER_REPOSITORY: ${{ vars.GH_TEST_USER_REPOSITORY }}
114115
GH_TEST_ORG_USER: ${{ vars.GH_TEST_ORG_USER }}

.github/workflows/ghes-acceptance-tests.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ jobs:
120120
GITHUB_OWNER: ""
121121
GITHUB_USERNAME: ""
122122
GITHUB_ENTERPRISE_SLUG: ""
123+
GITHUB_LEGACY_CLIENT: "false"
123124
GH_TEST_AUTH_MODE: enterprise
124125
run: |
125126
set -eou pipefail

CONTRIBUTING.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ Once you have the repository cloned, there's a couple of additional steps you'll
107107
export GITHUB_OWNER="<name of an organization>"
108108
export GITHUB_USERNAME="<username of the user who created the token>"
109109
export GITHUB_TOKEN="<token of a user with an organization account>"
110+
export GITHUB_LEGACY_CLIENT="false"
110111
```
111112

112113
- Build the project with `make build`
@@ -239,6 +240,9 @@ export TF_ACC="1"
239240
# Configure the URL override for GHES.
240241
export GITHUB_BASE_URL=
241242

243+
# Use the modern client for testing.
244+
export GITHUB_LEGACY_CLIENT="false"
245+
242246
# Configure acceptance testing mode; one of anonymous, individual, organization, team or enterprise. If not set will default to anonymous
243247
export GH_TEST_AUTH_MODE=
244248

@@ -286,6 +290,7 @@ To run acceptance tests the `TF_ACC` environment variable must be set. Below is
286290
"GITHUB_ENTERPRISE_SLUG": "",
287291
"GITHUB_OWNER": "<ORGANIZATION>",
288292
"GITHUB_USERNAME": "<USERNAME>",
293+
"GITHUB_LEGACY_CLIENT": "false",
289294
"GH_TEST_AUTH_MODE": "organization",
290295
"GH_TEST_USER_REPOSITORY": "",
291296
"GH_TEST_ORG_USER": "",

github/acc_test.go

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -190,18 +190,15 @@ func TestMain(m *testing.M) {
190190
}
191191

192192
func getTestMeta() (*Owner, error) {
193-
config := Config{
194-
Token: testAccConf.token,
195-
Owner: testAccConf.owner,
196-
BaseURL: testAccConf.baseURL,
193+
config := &Config{
194+
GraphQLAPIPath: "graphql",
195+
Token: testAccConf.token,
196+
Owner: testAccConf.owner,
197+
BaseURL: testAccConf.baseURL,
198+
LegacyClient: os.Getenv("GITHUB_LEGACY_CLIENT") != "false",
197199
}
198200

199-
meta, err := config.Meta()
200-
if err != nil {
201-
return nil, fmt.Errorf("error getting GitHub meta parameter")
202-
}
203-
204-
return meta.(*Owner), nil
201+
return configureProviderMeta(context.Background(), config)
205202
}
206203

207204
func configureSweepers() {

github/config_test.go

Lines changed: 0 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import (
44
"net/http"
55
"net/http/httptest"
66
"testing"
7-
8-
"github.com/shurcooL/githubv4"
97
)
108

119
func Test_getBaseURL(t *testing.T) {
@@ -157,151 +155,6 @@ func Test_getBaseURL(t *testing.T) {
157155
}
158156
}
159157

160-
func TestAccConfigMeta(t *testing.T) {
161-
baseURL, _, err := getBaseURL(DotComAPIURL)
162-
if err != nil {
163-
t.Fatalf("failed to parse test base URL: %s", err.Error())
164-
}
165-
166-
t.Run("returns an anonymous client for the v3 REST API", func(t *testing.T) {
167-
config := Config{BaseURL: baseURL}
168-
meta, err := config.Meta()
169-
if err != nil {
170-
t.Fatalf("failed to return meta without error: %s", err.Error())
171-
}
172-
173-
ctx := t.Context()
174-
client := meta.(*Owner).v3client
175-
_, _, err = client.Meta.Get(ctx)
176-
if err != nil {
177-
t.Fatalf("failed to validate returned client without error: %s", err.Error())
178-
}
179-
})
180-
181-
t.Run("returns a v3 REST API client to manage individual resources", func(t *testing.T) {
182-
skipUnlessMode(t, individual)
183-
184-
config := Config{
185-
Token: testAccConf.token,
186-
BaseURL: baseURL,
187-
}
188-
meta, err := config.Meta()
189-
if err != nil {
190-
t.Fatalf("failed to return meta without error: %s", err.Error())
191-
}
192-
193-
ctx := t.Context()
194-
client := meta.(*Owner).v3client
195-
_, _, err = client.Meta.Get(ctx)
196-
if err != nil {
197-
t.Fatalf("failed to validate returned client without error: %s", err.Error())
198-
}
199-
})
200-
201-
t.Run("returns a v3 REST API client with max retries", func(t *testing.T) {
202-
skipUnlessMode(t, individual)
203-
204-
config := Config{
205-
Token: testAccConf.token,
206-
BaseURL: baseURL,
207-
RetryableErrors: map[int]bool{
208-
500: true,
209-
502: true,
210-
},
211-
MaxRetries: 3,
212-
}
213-
meta, err := config.Meta()
214-
if err != nil {
215-
t.Fatalf("failed to return meta without error: %s", err.Error())
216-
}
217-
218-
ctx := t.Context()
219-
client := meta.(*Owner).v3client
220-
_, _, err = client.Meta.Get(ctx)
221-
if err != nil {
222-
t.Fatalf("failed to validate returned client without error: %s", err.Error())
223-
}
224-
})
225-
226-
t.Run("returns a v4 GraphQL API client to manage individual resources", func(t *testing.T) {
227-
skipUnlessMode(t, individual)
228-
229-
config := Config{
230-
Token: testAccConf.token,
231-
BaseURL: baseURL,
232-
}
233-
meta, err := config.Meta()
234-
if err != nil {
235-
t.Fatalf("failed to return meta without error: %s", err.Error())
236-
}
237-
238-
client := meta.(*Owner).v4client
239-
var query struct {
240-
Meta struct {
241-
GitHubServicesSha githubv4.String
242-
}
243-
}
244-
err = client.Query(t.Context(), &query, nil)
245-
if err != nil {
246-
t.Fatalf("failed to validate returned client without error: %s", err.Error())
247-
}
248-
})
249-
250-
t.Run("returns a v3 REST API client to manage organization resources", func(t *testing.T) {
251-
skipUnlessHasOrgs(t)
252-
253-
config := Config{
254-
Token: testAccConf.token,
255-
BaseURL: baseURL,
256-
Owner: testAccConf.owner,
257-
}
258-
meta, err := config.Meta()
259-
if err != nil {
260-
t.Fatalf("failed to return meta without error: %s", err.Error())
261-
}
262-
263-
ctx := t.Context()
264-
client := meta.(*Owner).v3client
265-
_, _, err = client.Organizations.Get(ctx, testAccConf.owner)
266-
if err != nil {
267-
t.Fatalf("failed to validate returned client without error: %s", err.Error())
268-
}
269-
})
270-
271-
t.Run("returns a v4 GraphQL API client to manage organization resources", func(t *testing.T) {
272-
skipUnlessHasOrgs(t)
273-
274-
config := Config{
275-
Token: testAccConf.token,
276-
BaseURL: baseURL,
277-
Owner: testAccConf.owner,
278-
}
279-
meta, err := config.Meta()
280-
if err != nil {
281-
t.Fatalf("failed to return meta without error: %s", err.Error())
282-
}
283-
284-
client := meta.(*Owner).v4client
285-
286-
var query struct {
287-
Organization struct {
288-
ViewerCanAdminister githubv4.Boolean
289-
} `graphql:"organization(login: $login)"`
290-
}
291-
variables := map[string]any{
292-
"login": githubv4.String(testAccConf.owner),
293-
}
294-
err = client.Query(t.Context(), &query, variables)
295-
if err != nil {
296-
t.Fatalf("failed to validate returned client without error: %s", err.Error())
297-
}
298-
299-
if query.Organization.ViewerCanAdminister != true {
300-
t.Fatalf("unexpected response when validating client")
301-
}
302-
})
303-
}
304-
305158
func TestPreviewHeaderInjectorTransport_RoundTrip(t *testing.T) {
306159
tests := []struct {
307160
name string

github/provider.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ func configureProvider() func(context.Context, *schema.ResourceData) (any, diag.
505505
}
506506

507507
// configureProviderMeta initializes the provider metadata, including setting up the GitHub API clients based on the provided configuration. It returns the initialized metadata or an error if the configuration is invalid or if there are issues initializing the clients.
508-
func configureProviderMeta(ctx context.Context, c *Config) (any, error) {
508+
func configureProviderMeta(ctx context.Context, c *Config) (*Owner, error) {
509509
owner := &Owner{
510510
name: c.Owner,
511511
}

github/provider_test.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
99
"github.com/hashicorp/terraform-plugin-testing/terraform"
10+
"github.com/shurcooL/githubv4"
1011
)
1112

1213
func TestProvider(t *testing.T) {
@@ -260,6 +261,83 @@ data "github_ip_ranges" "test" {}
260261
})
261262
}
262263

264+
func Test_configureProviderMeta(t *testing.T) {
265+
baseURL, _, err := getBaseURL(DotComAPIURL)
266+
if err != nil {
267+
t.Fatalf("failed to parse test base URL: %s", err.Error())
268+
}
269+
270+
for _, tt := range []struct {
271+
name string
272+
legacyClient bool
273+
}{
274+
{
275+
name: "client",
276+
legacyClient: false,
277+
},
278+
{
279+
name: "legacy_client",
280+
legacyClient: true,
281+
},
282+
} {
283+
t.Run(tt.name, func(t *testing.T) {
284+
t.Run("anonymous", func(t *testing.T) {
285+
config := &Config{
286+
BaseURL: baseURL,
287+
LegacyClient: tt.legacyClient,
288+
}
289+
290+
meta, err := configureProviderMeta(t.Context(), config)
291+
if err != nil {
292+
t.Fatalf("failed to return meta without error: %s", err.Error())
293+
}
294+
295+
t.Run("rest_client", func(t *testing.T) {
296+
_, _, err = meta.v3client.Meta.Get(t.Context())
297+
if err != nil {
298+
t.Fatalf("failed to validate returned client without error: %s", err.Error())
299+
}
300+
})
301+
})
302+
303+
t.Run("authenticated", func(t *testing.T) {
304+
skipUnauthenticated(t)
305+
306+
config := &Config{
307+
GraphQLAPIPath: "graphql",
308+
BaseURL: baseURL,
309+
Owner: testAccConf.owner,
310+
Token: testAccConf.token,
311+
LegacyClient: tt.legacyClient,
312+
}
313+
314+
meta, err := configureProviderMeta(t.Context(), config)
315+
if err != nil {
316+
t.Fatalf("failed to return meta without error: %s", err.Error())
317+
}
318+
319+
t.Run("rest_client", func(t *testing.T) {
320+
if _, _, err = meta.v3client.Meta.Get(t.Context()); err != nil {
321+
t.Fatalf("failed to validate returned client without error: %s", err.Error())
322+
}
323+
})
324+
325+
t.Run("graphql_client", func(t *testing.T) {
326+
client := meta.v4client
327+
var query struct {
328+
Meta struct {
329+
GitHubServicesSha githubv4.String
330+
}
331+
}
332+
if err := client.Query(t.Context(), &query, nil); err != nil {
333+
t.Fatalf("failed to validate returned client without error: %s", err.Error())
334+
}
335+
})
336+
})
337+
})
338+
}
339+
}
340+
263341
func Test_ghCLIHostFromAPIHost(t *testing.T) {
264342
testCases := []struct {
265343
name string

0 commit comments

Comments
 (0)