Skip to content

Commit 65ba5f7

Browse files
Merge pull request #244 from andresayej/feature/laravel-forge-plugin
Shell Plugin for Laravel Forge CLI
2 parents d5134e3 + 4d48951 commit 65ba5f7

File tree

5 files changed

+176
-0
lines changed

5 files changed

+176
-0
lines changed

plugins/laravelforge/api_token.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package laravelforge
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://forge.laravel.com/docs/1.0/accounts/api.html"),
18+
ManagementURL: sdk.URL("https://forge.laravel.com/user-profile/api"),
19+
Fields: []schema.CredentialField{
20+
{
21+
Name: fieldname.Token,
22+
MarkdownDescription: "API Token used to authenticate to Laravel Forge.",
23+
Secret: true,
24+
Composition: &schema.ValueComposition{
25+
Length: 987,
26+
Charset: schema.Charset{
27+
Uppercase: true,
28+
Lowercase: true,
29+
Digits: true,
30+
},
31+
},
32+
},
33+
},
34+
DefaultProvisioner: provision.EnvVars(defaultEnvVarMapping),
35+
Importer: importer.TryAll(
36+
importer.TryEnvVarPair(defaultEnvVarMapping),
37+
TryLaravelForgeConfigFile(),
38+
)}
39+
}
40+
41+
var defaultEnvVarMapping = map[string]sdk.FieldName{
42+
"FORGE_API_TOKEN": fieldname.Token,
43+
}
44+
45+
func TryLaravelForgeConfigFile() sdk.Importer {
46+
return importer.TryFile("~/.laravel-forge/config.json", func(ctx context.Context, contents importer.FileContents, in sdk.ImportInput, out *sdk.ImportAttempt) {
47+
var config Config
48+
if err := contents.ToJSON(&config); err != nil {
49+
out.AddError(err)
50+
return
51+
}
52+
53+
if config.Token == "" {
54+
return
55+
}
56+
57+
out.AddCandidate(sdk.ImportCandidate{
58+
Fields: map[sdk.FieldName]string{
59+
fieldname.Token: config.Token,
60+
},
61+
})
62+
})
63+
}
64+
65+
type Config struct {
66+
Token string `json:"token"`
67+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package laravelforge
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.Token: "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIxIiwianRpIjoiYWFhODU2M2NkYjU5YzQyMmRkMGFlOTRlNTVjZTFjYzRiNjEwNzE3MTBiMTIzYWEzMzczNzc3MjIxOGVjN2Q5Yzc1MjgxYWEwNTVhOTFkZWQiLCJpYXQiOjE2ODEzNzUyMTkuNDg1NTUzLCJuYmYiOjE2ODEzNzUyMTkuNDg1NTU2LCJleHAiOjE5OTY5OTQ0MTkuNDc5MzUyLCJzdWIiOiIxNjkyMzQiLCJzY29wZXMiOltdfQ.a1Ny2UAzgSkKZGaXjrFBmjFuBAWerLj73l-ktK1iGmdCukD_9AXo75rsOq-BV11GWbZb1ws0LX_hkcSBKwxaD7ou_l9cQlkOM8vWni1dq0Vjd1OwctqemBqFl1SD-Gyw7-st7phELyZK77BVpyUu0oTAtRAREx0ybDj3UE672JF9LwgtOo7Nv2TUTWT-rlZPUIvOcwxliE-sWA29tPZOviRIveQ3-O3Bh8-LKY7gVjQv0UDfR3SM4SEPPuacaVRR5rnklFKlaar4sfnL5WL6-iazQ8o1J7IuNsBfDf9OJqslvtzQFg6GWcSC0AzxWsho5tzyvmsbbhSA5iOFZ7NMB93V53fByBDz4gLWD90HS0jYQ-gOVqOQBWrTJMuPu4C2TDpuow27Kc4rJrH6cKd7mZnf8B910jHPzlkEY33ommCT9Oe6C-wDGpM4CnUaVb9jaNMl67j2Ak7-pUzv7iiAajt5_Rhb4C7Kx9wFTZR6AIbP2GAfc4gXhOXWxV8tXz5LBJ_JXwgTDIfnBfqqKeYZ-GyCMmly6w2suxLwR00e4JCu1_LjDGoWA8-VPOVafhwA51t5nQ0HVzeyuEpVfqwRhsjk2ln56CY8sLd2YU12fPJiitN88t8YccLDugc8Q79OelJTgIO17d50kzXZ1twzwpimWTjgCIS90K19EXAMPLE",
16+
},
17+
ExpectedOutput: sdk.ProvisionOutput{
18+
Environment: map[string]string{
19+
"FORGE_API_TOKEN": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIxIiwianRpIjoiYWFhODU2M2NkYjU5YzQyMmRkMGFlOTRlNTVjZTFjYzRiNjEwNzE3MTBiMTIzYWEzMzczNzc3MjIxOGVjN2Q5Yzc1MjgxYWEwNTVhOTFkZWQiLCJpYXQiOjE2ODEzNzUyMTkuNDg1NTUzLCJuYmYiOjE2ODEzNzUyMTkuNDg1NTU2LCJleHAiOjE5OTY5OTQ0MTkuNDc5MzUyLCJzdWIiOiIxNjkyMzQiLCJzY29wZXMiOltdfQ.a1Ny2UAzgSkKZGaXjrFBmjFuBAWerLj73l-ktK1iGmdCukD_9AXo75rsOq-BV11GWbZb1ws0LX_hkcSBKwxaD7ou_l9cQlkOM8vWni1dq0Vjd1OwctqemBqFl1SD-Gyw7-st7phELyZK77BVpyUu0oTAtRAREx0ybDj3UE672JF9LwgtOo7Nv2TUTWT-rlZPUIvOcwxliE-sWA29tPZOviRIveQ3-O3Bh8-LKY7gVjQv0UDfR3SM4SEPPuacaVRR5rnklFKlaar4sfnL5WL6-iazQ8o1J7IuNsBfDf9OJqslvtzQFg6GWcSC0AzxWsho5tzyvmsbbhSA5iOFZ7NMB93V53fByBDz4gLWD90HS0jYQ-gOVqOQBWrTJMuPu4C2TDpuow27Kc4rJrH6cKd7mZnf8B910jHPzlkEY33ommCT9Oe6C-wDGpM4CnUaVb9jaNMl67j2Ak7-pUzv7iiAajt5_Rhb4C7Kx9wFTZR6AIbP2GAfc4gXhOXWxV8tXz5LBJ_JXwgTDIfnBfqqKeYZ-GyCMmly6w2suxLwR00e4JCu1_LjDGoWA8-VPOVafhwA51t5nQ0HVzeyuEpVfqwRhsjk2ln56CY8sLd2YU12fPJiitN88t8YccLDugc8Q79OelJTgIO17d50kzXZ1twzwpimWTjgCIS90K19EXAMPLE",
20+
},
21+
},
22+
},
23+
})
24+
}
25+
26+
func TestAPITokenImporter(t *testing.T) {
27+
plugintest.TestImporter(t, APIToken().Importer, map[string]plugintest.ImportCase{
28+
"environment": {
29+
Environment: map[string]string{
30+
"FORGE_API_TOKEN": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIxIiwianRpIjoiYWFhODU2M2NkYjU5YzQyMmRkMGFlOTRlNTVjZTFjYzRiNjEwNzE3MTBiMTIzYWEzMzczNzc3MjIxOGVjN2Q5Yzc1MjgxYWEwNTVhOTFkZWQiLCJpYXQiOjE2ODEzNzUyMTkuNDg1NTUzLCJuYmYiOjE2ODEzNzUyMTkuNDg1NTU2LCJleHAiOjE5OTY5OTQ0MTkuNDc5MzUyLCJzdWIiOiIxNjkyMzQiLCJzY29wZXMiOltdfQ.a1Ny2UAzgSkKZGaXjrFBmjFuBAWerLj73l-ktK1iGmdCukD_9AXo75rsOq-BV11GWbZb1ws0LX_hkcSBKwxaD7ou_l9cQlkOM8vWni1dq0Vjd1OwctqemBqFl1SD-Gyw7-st7phELyZK77BVpyUu0oTAtRAREx0ybDj3UE672JF9LwgtOo7Nv2TUTWT-rlZPUIvOcwxliE-sWA29tPZOviRIveQ3-O3Bh8-LKY7gVjQv0UDfR3SM4SEPPuacaVRR5rnklFKlaar4sfnL5WL6-iazQ8o1J7IuNsBfDf9OJqslvtzQFg6GWcSC0AzxWsho5tzyvmsbbhSA5iOFZ7NMB93V53fByBDz4gLWD90HS0jYQ-gOVqOQBWrTJMuPu4C2TDpuow27Kc4rJrH6cKd7mZnf8B910jHPzlkEY33ommCT9Oe6C-wDGpM4CnUaVb9jaNMl67j2Ak7-pUzv7iiAajt5_Rhb4C7Kx9wFTZR6AIbP2GAfc4gXhOXWxV8tXz5LBJ_JXwgTDIfnBfqqKeYZ-GyCMmly6w2suxLwR00e4JCu1_LjDGoWA8-VPOVafhwA51t5nQ0HVzeyuEpVfqwRhsjk2ln56CY8sLd2YU12fPJiitN88t8YccLDugc8Q79OelJTgIO17d50kzXZ1twzwpimWTjgCIS90K19EXAMPLE",
31+
},
32+
ExpectedCandidates: []sdk.ImportCandidate{
33+
{
34+
Fields: map[sdk.FieldName]string{
35+
fieldname.Token: "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIxIiwianRpIjoiYWFhODU2M2NkYjU5YzQyMmRkMGFlOTRlNTVjZTFjYzRiNjEwNzE3MTBiMTIzYWEzMzczNzc3MjIxOGVjN2Q5Yzc1MjgxYWEwNTVhOTFkZWQiLCJpYXQiOjE2ODEzNzUyMTkuNDg1NTUzLCJuYmYiOjE2ODEzNzUyMTkuNDg1NTU2LCJleHAiOjE5OTY5OTQ0MTkuNDc5MzUyLCJzdWIiOiIxNjkyMzQiLCJzY29wZXMiOltdfQ.a1Ny2UAzgSkKZGaXjrFBmjFuBAWerLj73l-ktK1iGmdCukD_9AXo75rsOq-BV11GWbZb1ws0LX_hkcSBKwxaD7ou_l9cQlkOM8vWni1dq0Vjd1OwctqemBqFl1SD-Gyw7-st7phELyZK77BVpyUu0oTAtRAREx0ybDj3UE672JF9LwgtOo7Nv2TUTWT-rlZPUIvOcwxliE-sWA29tPZOviRIveQ3-O3Bh8-LKY7gVjQv0UDfR3SM4SEPPuacaVRR5rnklFKlaar4sfnL5WL6-iazQ8o1J7IuNsBfDf9OJqslvtzQFg6GWcSC0AzxWsho5tzyvmsbbhSA5iOFZ7NMB93V53fByBDz4gLWD90HS0jYQ-gOVqOQBWrTJMuPu4C2TDpuow27Kc4rJrH6cKd7mZnf8B910jHPzlkEY33ommCT9Oe6C-wDGpM4CnUaVb9jaNMl67j2Ak7-pUzv7iiAajt5_Rhb4C7Kx9wFTZR6AIbP2GAfc4gXhOXWxV8tXz5LBJ_JXwgTDIfnBfqqKeYZ-GyCMmly6w2suxLwR00e4JCu1_LjDGoWA8-VPOVafhwA51t5nQ0HVzeyuEpVfqwRhsjk2ln56CY8sLd2YU12fPJiitN88t8YccLDugc8Q79OelJTgIO17d50kzXZ1twzwpimWTjgCIS90K19EXAMPLE",
36+
},
37+
},
38+
},
39+
},
40+
"config file default path": {
41+
Files: map[string]string{
42+
"~/.laravel-forge/config.json": plugintest.LoadFixture(t, "config.json"),
43+
},
44+
ExpectedCandidates: []sdk.ImportCandidate{
45+
{
46+
Fields: map[sdk.FieldName]string{
47+
fieldname.Token: "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIxIiwianRpIjoiYWFhODU2M2NkYjU5YzQyMmRkMGFlOTRlNTVjZTFjYzRiNjEwNzE3MTBiMTIzYWEzMzczNzc3MjIxOGVjN2Q5Yzc1MjgxYWEwNTVhOTFkZWQiLCJpYXQiOjE2ODEzNzUyMTkuNDg1NTUzLCJuYmYiOjE2ODEzNzUyMTkuNDg1NTU2LCJleHAiOjE5OTY5OTQ0MTkuNDc5MzUyLCJzdWIiOiIxNjkyMzQiLCJzY29wZXMiOltdfQ.a1Ny2UAzgSkKZGaXjrFBmjFuBAWerLj73l-ktK1iGmdCukD_9AXo75rsOq-BV11GWbZb1ws0LX_hkcSBKwxaD7ou_l9cQlkOM8vWni1dq0Vjd1OwctqemBqFl1SD-Gyw7-st7phELyZK77BVpyUu0oTAtRAREx0ybDj3UE672JF9LwgtOo7Nv2TUTWT-rlZPUIvOcwxliE-sWA29tPZOviRIveQ3-O3Bh8-LKY7gVjQv0UDfR3SM4SEPPuacaVRR5rnklFKlaar4sfnL5WL6-iazQ8o1J7IuNsBfDf9OJqslvtzQFg6GWcSC0AzxWsho5tzyvmsbbhSA5iOFZ7NMB93V53fByBDz4gLWD90HS0jYQ-gOVqOQBWrTJMuPu4C2TDpuow27Kc4rJrH6cKd7mZnf8B910jHPzlkEY33ommCT9Oe6C-wDGpM4CnUaVb9jaNMl67j2Ak7-pUzv7iiAajt5_Rhb4C7Kx9wFTZR6AIbP2GAfc4gXhOXWxV8tXz5LBJ_JXwgTDIfnBfqqKeYZ-GyCMmly6w2suxLwR00e4JCu1_LjDGoWA8-VPOVafhwA51t5nQ0HVzeyuEpVfqwRhsjk2ln56CY8sLd2YU12fPJiitN88t8YccLDugc8Q79OelJTgIO17d50kzXZ1twzwpimWTjgCIS90K19EXAMPLE",
48+
},
49+
},
50+
},
51+
},
52+
})
53+
}

plugins/laravelforge/forge.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package laravelforge
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 LaravelForgeCLI() schema.Executable {
11+
return schema.Executable{
12+
Name: "Laravel Forge CLI",
13+
Runs: []string{"forge"},
14+
DocsURL: sdk.URL("https://forge.laravel.com/docs/1.0/cli.html"),
15+
NeedsAuth: needsauth.IfAll(
16+
needsauth.NotForHelpOrVersion(),
17+
needsauth.NotWithoutArgs(),
18+
needsauth.NotForExactArgs("login"),
19+
needsauth.NotForExactArgs("logout"),
20+
needsauth.NotForExactArgs("list"),
21+
),
22+
Uses: []schema.CredentialUsage{
23+
{
24+
Name: credname.APIToken,
25+
},
26+
},
27+
}
28+
}

plugins/laravelforge/plugin.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package laravelforge
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: "laravelforge",
11+
Platform: schema.PlatformInfo{
12+
Name: "Laravel Forge",
13+
Homepage: sdk.URL("https://forge.laravel.com/"),
14+
},
15+
Credentials: []schema.CredentialType{
16+
APIToken(),
17+
},
18+
Executables: []schema.Executable{
19+
LaravelForgeCLI(),
20+
},
21+
}
22+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"latest_version_verified_at": 1681372610,
3+
"latest_version": "v1.7.0",
4+
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJhdWQiOiIxIiwianRpIjoiYWFhODU2M2NkYjU5YzQyMmRkMGFlOTRlNTVjZTFjYzRiNjEwNzE3MTBiMTIzYWEzMzczNzc3MjIxOGVjN2Q5Yzc1MjgxYWEwNTVhOTFkZWQiLCJpYXQiOjE2ODEzNzUyMTkuNDg1NTUzLCJuYmYiOjE2ODEzNzUyMTkuNDg1NTU2LCJleHAiOjE5OTY5OTQ0MTkuNDc5MzUyLCJzdWIiOiIxNjkyMzQiLCJzY29wZXMiOltdfQ.a1Ny2UAzgSkKZGaXjrFBmjFuBAWerLj73l-ktK1iGmdCukD_9AXo75rsOq-BV11GWbZb1ws0LX_hkcSBKwxaD7ou_l9cQlkOM8vWni1dq0Vjd1OwctqemBqFl1SD-Gyw7-st7phELyZK77BVpyUu0oTAtRAREx0ybDj3UE672JF9LwgtOo7Nv2TUTWT-rlZPUIvOcwxliE-sWA29tPZOviRIveQ3-O3Bh8-LKY7gVjQv0UDfR3SM4SEPPuacaVRR5rnklFKlaar4sfnL5WL6-iazQ8o1J7IuNsBfDf9OJqslvtzQFg6GWcSC0AzxWsho5tzyvmsbbhSA5iOFZ7NMB93V53fByBDz4gLWD90HS0jYQ-gOVqOQBWrTJMuPu4C2TDpuow27Kc4rJrH6cKd7mZnf8B910jHPzlkEY33ommCT9Oe6C-wDGpM4CnUaVb9jaNMl67j2Ak7-pUzv7iiAajt5_Rhb4C7Kx9wFTZR6AIbP2GAfc4gXhOXWxV8tXz5LBJ_JXwgTDIfnBfqqKeYZ-GyCMmly6w2suxLwR00e4JCu1_LjDGoWA8-VPOVafhwA51t5nQ0HVzeyuEpVfqwRhsjk2ln56CY8sLd2YU12fPJiitN88t8YccLDugc8Q79OelJTgIO17d50kzXZ1twzwpimWTjgCIS90K19EXAMPLE",
5+
"server": 0
6+
}

0 commit comments

Comments
 (0)