Skip to content

Commit 4f3af47

Browse files
authored
Merge pull request #610 from 1Password/feature/github-enterprise-support
Add GitHub Enterprise support to the gh CLI provisioner.
2 parents af9327a + 2493ba2 commit 4f3af47

4 files changed

Lines changed: 142 additions & 2 deletions

File tree

plugins/github/personal_access_token.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66

77
"github.com/1Password/shell-plugins/sdk"
88
"github.com/1Password/shell-plugins/sdk/importer"
9-
"github.com/1Password/shell-plugins/sdk/provision"
109
"github.com/1Password/shell-plugins/sdk/schema"
1110
"github.com/1Password/shell-plugins/sdk/schema/credname"
1211
"github.com/1Password/shell-plugins/sdk/schema/fieldname"
@@ -38,7 +37,7 @@ func PersonalAccessToken() schema.CredentialType {
3837
Optional: true,
3938
},
4039
},
41-
DefaultProvisioner: provision.EnvVars(defaultEnvVarMapping),
40+
DefaultProvisioner: GitHubCLIProvisioner{},
4241
Importer: importer.TryAll(
4342
importer.TryEnvVarPair(defaultEnvVarMapping),
4443
importer.TryAllEnvVars(fieldname.Token, "GH_TOKEN", "GITHUB_PAT"),

plugins/github/personal_access_token_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ func TestPersonalAccessTokenProvisioner(t *testing.T) {
121121
},
122122
ExpectedOutput: sdk.ProvisionOutput{
123123
Environment: map[string]string{
124+
"GH_TOKEN": "github_pat_OYXGsaLFxgNy9msXs44LFNzg3wh0VsXRGycViVc0iKPOqczc1QKlB3ZVVrm5ESukqKR8nE3jzPBEXAMPLE",
124125
"GITHUB_TOKEN": "github_pat_OYXGsaLFxgNy9msXs44LFNzg3wh0VsXRGycViVc0iKPOqczc1QKlB3ZVVrm5ESukqKR8nE3jzPBEXAMPLE",
125126
},
126127
},

plugins/github/provisioner.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package github
2+
3+
import (
4+
"context"
5+
"strings"
6+
7+
"github.com/1Password/shell-plugins/sdk"
8+
"github.com/1Password/shell-plugins/sdk/schema/fieldname"
9+
)
10+
11+
const (
12+
githubHost = "github.com"
13+
localhostHost = "github.localhost"
14+
tenancyHost = "ghe.com"
15+
)
16+
17+
// GitHubCLIProvisioner provisions auth tokens using the environment variables expected by the GitHub CLI.
18+
// GitHub.com and GitHub Enterprise Cloud (*.ghe.com) use GH_TOKEN and GITHUB_TOKEN.
19+
// GitHub Enterprise Server uses GH_ENTERPRISE_TOKEN and GITHUB_ENTERPRISE_TOKEN with GH_HOST.
20+
type GitHubCLIProvisioner struct{}
21+
22+
func (p GitHubCLIProvisioner) Provision(ctx context.Context, in sdk.ProvisionInput, out *sdk.ProvisionOutput) {
23+
token, ok := in.ItemFields[fieldname.Token]
24+
if !ok {
25+
return
26+
}
27+
28+
host := strings.ToLower(strings.TrimSpace(in.ItemFields[fieldname.Host]))
29+
30+
if usesEnterpriseToken(host) {
31+
out.AddEnvVar("GH_ENTERPRISE_TOKEN", token)
32+
out.AddEnvVar("GITHUB_ENTERPRISE_TOKEN", token)
33+
if host != "" {
34+
out.AddEnvVar("GH_HOST", host)
35+
}
36+
return
37+
}
38+
39+
out.AddEnvVar("GH_TOKEN", token)
40+
out.AddEnvVar("GITHUB_TOKEN", token)
41+
if host != "" && host != githubHost {
42+
out.AddEnvVar("GH_HOST", host)
43+
}
44+
}
45+
46+
func usesEnterpriseToken(host string) bool {
47+
if host == "" || host == githubHost || host == localhostHost {
48+
return false
49+
}
50+
51+
return !isTenancyHost(host)
52+
}
53+
54+
func isTenancyHost(host string) bool {
55+
return strings.HasSuffix(host, "."+tenancyHost)
56+
}
57+
58+
func (p GitHubCLIProvisioner) Deprovision(ctx context.Context, in sdk.DeprovisionInput, out *sdk.DeprovisionOutput) {
59+
// Environment variables get wiped automatically when the process exits.
60+
}
61+
62+
func (p GitHubCLIProvisioner) Description() string {
63+
return "Provision GitHub CLI environment variables: GH_TOKEN, GITHUB_TOKEN, GH_ENTERPRISE_TOKEN, GITHUB_ENTERPRISE_TOKEN, GH_HOST"
64+
}

plugins/github/provisioner_test.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package github
2+
3+
import (
4+
"testing"
5+
6+
"github.com/1Password/shell-plugins/sdk"
7+
"github.com/1Password/shell-plugins/sdk/plugintest"
8+
"github.com/1Password/shell-plugins/sdk/schema/fieldname"
9+
)
10+
11+
func TestGitHubCLIProvisioner(t *testing.T) {
12+
plugintest.TestProvisioner(t, GitHubCLIProvisioner{}, map[string]plugintest.ProvisionCase{
13+
"github.com": {
14+
ItemFields: map[sdk.FieldName]string{
15+
fieldname.Token: "github_pat_OYXGsaLFxgNy9msXs44LFNzg3wh0VsXRGycViVc0iKPOqczc1QKlB3ZVVrm5ESukqKR8nE3jzPBEXAMPLE",
16+
},
17+
ExpectedOutput: sdk.ProvisionOutput{
18+
Environment: map[string]string{
19+
"GH_TOKEN": "github_pat_OYXGsaLFxgNy9msXs44LFNzg3wh0VsXRGycViVc0iKPOqczc1QKlB3ZVVrm5ESukqKR8nE3jzPBEXAMPLE",
20+
"GITHUB_TOKEN": "github_pat_OYXGsaLFxgNy9msXs44LFNzg3wh0VsXRGycViVc0iKPOqczc1QKlB3ZVVrm5ESukqKR8nE3jzPBEXAMPLE",
21+
},
22+
},
23+
},
24+
"github.com with explicit host": {
25+
ItemFields: map[sdk.FieldName]string{
26+
fieldname.Token: "github_pat_OYXGsaLFxgNy9msXs44LFNzg3wh0VsXRGycViVc0iKPOqczc1QKlB3ZVVrm5ESukqKR8nE3jzPBEXAMPLE",
27+
fieldname.Host: "github.com",
28+
},
29+
ExpectedOutput: sdk.ProvisionOutput{
30+
Environment: map[string]string{
31+
"GH_TOKEN": "github_pat_OYXGsaLFxgNy9msXs44LFNzg3wh0VsXRGycViVc0iKPOqczc1QKlB3ZVVrm5ESukqKR8nE3jzPBEXAMPLE",
32+
"GITHUB_TOKEN": "github_pat_OYXGsaLFxgNy9msXs44LFNzg3wh0VsXRGycViVc0iKPOqczc1QKlB3ZVVrm5ESukqKR8nE3jzPBEXAMPLE",
33+
},
34+
},
35+
},
36+
"GitHub Enterprise Server": {
37+
ItemFields: map[sdk.FieldName]string{
38+
fieldname.Token: "github_pat_OYXGsaLFxgNy9msXs44LFNzg3wh0VsXRGycViVc0iKPOqczc1QKlB3ZVVrm5ESukqKR8nE3jzPBEXAMPLE",
39+
fieldname.Host: "enterprise.github.com",
40+
},
41+
ExpectedOutput: sdk.ProvisionOutput{
42+
Environment: map[string]string{
43+
"GH_ENTERPRISE_TOKEN": "github_pat_OYXGsaLFxgNy9msXs44LFNzg3wh0VsXRGycViVc0iKPOqczc1QKlB3ZVVrm5ESukqKR8nE3jzPBEXAMPLE",
44+
"GITHUB_ENTERPRISE_TOKEN": "github_pat_OYXGsaLFxgNy9msXs44LFNzg3wh0VsXRGycViVc0iKPOqczc1QKlB3ZVVrm5ESukqKR8nE3jzPBEXAMPLE",
45+
"GH_HOST": "enterprise.github.com",
46+
},
47+
},
48+
},
49+
"GitHub Enterprise Cloud": {
50+
ItemFields: map[sdk.FieldName]string{
51+
fieldname.Token: "github_pat_OYXGsaLFxgNy9msXs44LFNzg3wh0VsXRGycViVc0iKPOqczc1QKlB3ZVVrm5ESukqKR8nE3jzPBEXAMPLE",
52+
fieldname.Host: "company.ghe.com",
53+
},
54+
ExpectedOutput: sdk.ProvisionOutput{
55+
Environment: map[string]string{
56+
"GH_TOKEN": "github_pat_OYXGsaLFxgNy9msXs44LFNzg3wh0VsXRGycViVc0iKPOqczc1QKlB3ZVVrm5ESukqKR8nE3jzPBEXAMPLE",
57+
"GITHUB_TOKEN": "github_pat_OYXGsaLFxgNy9msXs44LFNzg3wh0VsXRGycViVc0iKPOqczc1QKlB3ZVVrm5ESukqKR8nE3jzPBEXAMPLE",
58+
"GH_HOST": "company.ghe.com",
59+
},
60+
},
61+
},
62+
"github.localhost": {
63+
ItemFields: map[sdk.FieldName]string{
64+
fieldname.Token: "github_pat_OYXGsaLFxgNy9msXs44LFNzg3wh0VsXRGycViVc0iKPOqczc1QKlB3ZVVrm5ESukqKR8nE3jzPBEXAMPLE",
65+
fieldname.Host: "github.localhost",
66+
},
67+
ExpectedOutput: sdk.ProvisionOutput{
68+
Environment: map[string]string{
69+
"GH_TOKEN": "github_pat_OYXGsaLFxgNy9msXs44LFNzg3wh0VsXRGycViVc0iKPOqczc1QKlB3ZVVrm5ESukqKR8nE3jzPBEXAMPLE",
70+
"GITHUB_TOKEN": "github_pat_OYXGsaLFxgNy9msXs44LFNzg3wh0VsXRGycViVc0iKPOqczc1QKlB3ZVVrm5ESukqKR8nE3jzPBEXAMPLE",
71+
"GH_HOST": "github.localhost",
72+
},
73+
},
74+
},
75+
})
76+
}

0 commit comments

Comments
 (0)