Skip to content

Commit aedd05e

Browse files
committed
Add Buildkite plugin
1 parent 49810df commit aedd05e

File tree

5 files changed

+240
-0
lines changed

5 files changed

+240
-0
lines changed

plugins/buildkite/api_token.go

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
package buildkite
2+
3+
import (
4+
"context"
5+
6+
"github.com/1Password/shell-plugins/sdk"
7+
"github.com/1Password/shell-plugins/sdk/importer"
8+
"github.com/1Password/shell-plugins/sdk/provision"
9+
"github.com/1Password/shell-plugins/sdk/schema"
10+
"github.com/1Password/shell-plugins/sdk/schema/credname"
11+
"github.com/1Password/shell-plugins/sdk/schema/fieldname"
12+
)
13+
14+
func APIToken() schema.CredentialType {
15+
return schema.CredentialType{
16+
Name: credname.APIToken,
17+
DocsURL: sdk.URL("https://buildkite.com/docs/platform/cli"),
18+
ManagementURL: sdk.URL("https://buildkite.com/user/api-access-tokens"),
19+
Fields: []schema.CredentialField{
20+
{
21+
Name: fieldname.Organization,
22+
MarkdownDescription: "Organization slug for your Buildkite account.",
23+
Secret: false,
24+
Composition: &schema.ValueComposition{
25+
Charset: schema.Charset{
26+
Uppercase: true,
27+
Lowercase: true,
28+
Digits: true,
29+
Symbols: false,
30+
},
31+
},
32+
},
33+
{
34+
Name: fieldname.Token,
35+
MarkdownDescription: "API Token used to authenticate with Buildkite.",
36+
Secret: true,
37+
Composition: &schema.ValueComposition{
38+
Length: 45,
39+
Prefix: "bkua_",
40+
Charset: schema.Charset{
41+
Lowercase: true,
42+
Digits: true,
43+
},
44+
},
45+
},
46+
},
47+
DefaultProvisioner: provision.EnvVars(defaultEnvVarMapping),
48+
Importer: importer.TryAll(
49+
importer.TryEnvVarPair(defaultEnvVarMapping),
50+
TryBuildkiteConfigFile(),
51+
)}
52+
}
53+
54+
var defaultEnvVarMapping = map[string]sdk.FieldName{
55+
"BUILDKITE_ORGANIZATION_SLUG": fieldname.Organization,
56+
"BUILDKITE_API_TOKEN": fieldname.Token,
57+
}
58+
59+
// Check if the platform stores the API Token in a local config file, and if so,
60+
// implement the function below to add support for importing it.
61+
func TryBuildkiteConfigFile() sdk.Importer {
62+
return importer.TryFile("~/.config/bk.yaml", func(ctx context.Context, contents importer.FileContents, in sdk.ImportInput, out *sdk.ImportAttempt) {
63+
var config Config
64+
if err := contents.ToYAML(&config); err != nil {
65+
out.AddError(err)
66+
return
67+
}
68+
69+
if len(config.Organizations) == 0 {
70+
return
71+
}
72+
73+
for organizationSlug, organization := range config.Organizations {
74+
75+
if organizationSlug == "" || organization.Token == "" {
76+
return
77+
}
78+
79+
out.AddCandidate(sdk.ImportCandidate{
80+
Fields: map[sdk.FieldName]string{
81+
fieldname.Token: organization.Token,
82+
fieldname.Organization: organizationSlug,
83+
},
84+
NameHint: importer.SanitizeNameHint(organizationSlug),
85+
})
86+
}
87+
})
88+
}
89+
90+
type Config struct {
91+
Organizations map[string]Organization `yaml:"organizations"`
92+
}
93+
94+
type Organization struct {
95+
Token string `yaml:"api_token"`
96+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package buildkite
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 TestAPITokenProvisioner(t *testing.T) {
12+
plugintest.TestProvisioner(t, APIToken().DefaultProvisioner, map[string]plugintest.ProvisionCase{
13+
"default": {
14+
ItemFields: map[sdk.FieldName]string{
15+
fieldname.Organization: "example",
16+
fieldname.Token: "bkua_abcdefghijklmnopqrstuvwxyz1234567890abcd",
17+
},
18+
ExpectedOutput: sdk.ProvisionOutput{
19+
Environment: map[string]string{
20+
"BUILDKITE_ORGANIZATION_SLUG": "example",
21+
"BUILDKITE_API_TOKEN": "bkua_abcdefghijklmnopqrstuvwxyz1234567890abcd",
22+
},
23+
},
24+
},
25+
})
26+
}
27+
28+
func TestAPITokenImporter(t *testing.T) {
29+
plugintest.TestImporter(t, APIToken().Importer, map[string]plugintest.ImportCase{
30+
"environment": {
31+
Environment: map[string]string{
32+
"BUILDKITE_ORGANIZATION_SLUG": "example",
33+
"BUILDKITE_API_TOKEN": "bkua_abcdefghijklmnopqrstuvwxyz1234567890abcd",
34+
},
35+
ExpectedCandidates: []sdk.ImportCandidate{
36+
{
37+
Fields: map[sdk.FieldName]string{
38+
fieldname.Organization: "example",
39+
fieldname.Token: "bkua_abcdefghijklmnopqrstuvwxyz1234567890abcd",
40+
},
41+
},
42+
},
43+
},
44+
"config file default path": {
45+
Files: map[string]string{
46+
"~/.config/bk.yaml": plugintest.LoadFixture(t, "bk.yaml"),
47+
},
48+
ExpectedCandidates: []sdk.ImportCandidate{
49+
{
50+
Fields: map[sdk.FieldName]string{
51+
fieldname.Organization: "example",
52+
fieldname.Token: "bkua_abcdefghijklmnopqrstuvwxyz1234567890abcd",
53+
},
54+
NameHint: "example",
55+
},
56+
{
57+
Fields: map[sdk.FieldName]string{
58+
fieldname.Organization: "example2",
59+
fieldname.Token: "bkua_abcdefghijklmnopqrstuvwxyz1234567890defg",
60+
},
61+
NameHint: "example2",
62+
},
63+
},
64+
},
65+
})
66+
}
67+
68+
func TestAPIKeyNeedsAuth(t *testing.T) {
69+
plugintest.TestNeedsAuth(t, BuildkiteCLI().NeedsAuth, map[string]plugintest.NeedsAuthCase{
70+
"no for --help": {
71+
Args: []string{"--help"},
72+
ExpectedNeedsAuth: false,
73+
},
74+
"no for --version": {
75+
Args: []string{"--version"},
76+
ExpectedNeedsAuth: false,
77+
},
78+
"no for configure": {
79+
Args: []string{"configure"},
80+
ExpectedNeedsAuth: false,
81+
},
82+
"no for without args": {
83+
Args: []string{},
84+
ExpectedNeedsAuth: false,
85+
},
86+
"yes for all other commands": {
87+
Args: []string{"example"},
88+
ExpectedNeedsAuth: true,
89+
},
90+
})
91+
}

plugins/buildkite/bk.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package buildkite
2+
3+
import (
4+
"github.com/1Password/shell-plugins/sdk"
5+
"github.com/1Password/shell-plugins/sdk/needsauth"
6+
"github.com/1Password/shell-plugins/sdk/schema"
7+
"github.com/1Password/shell-plugins/sdk/schema/credname"
8+
)
9+
10+
func BuildkiteCLI() schema.Executable {
11+
return schema.Executable{
12+
Name: "Buildkite CLI",
13+
Runs: []string{"bk"},
14+
DocsURL: sdk.URL("https://buildkite.com/docs/cli"),
15+
NeedsAuth: needsauth.IfAll(
16+
needsauth.NotForHelpOrVersion(),
17+
needsauth.NotWithoutArgs(),
18+
needsauth.NotForExactArgs("configure"),
19+
),
20+
Uses: []schema.CredentialUsage{
21+
{
22+
Name: credname.APIToken,
23+
},
24+
},
25+
}
26+
}

plugins/buildkite/plugin.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package buildkite
2+
3+
import (
4+
"github.com/1Password/shell-plugins/sdk"
5+
"github.com/1Password/shell-plugins/sdk/schema"
6+
)
7+
8+
func New() schema.Plugin {
9+
return schema.Plugin{
10+
Name: "buildkite",
11+
Platform: schema.PlatformInfo{
12+
Name: "Buildkite",
13+
Homepage: sdk.URL("https://buildkite.com"),
14+
},
15+
Credentials: []schema.CredentialType{
16+
APIToken(),
17+
},
18+
Executables: []schema.Executable{
19+
BuildkiteCLI(),
20+
},
21+
}
22+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
organizations:
2+
example:
3+
api_token: bkua_abcdefghijklmnopqrstuvwxyz1234567890abcd
4+
example2:
5+
api_token: bkua_abcdefghijklmnopqrstuvwxyz1234567890defg

0 commit comments

Comments
 (0)