diff --git a/cmd/create.go b/cmd/create.go index 774a6f6..2d72ec5 100644 --- a/cmd/create.go +++ b/cmd/create.go @@ -16,6 +16,7 @@ type createCmdFlags struct { app string name string visibility string + org string environmentVariables []string secrets []string revisionName string @@ -25,6 +26,7 @@ type createCmdFlags struct { type createReq struct { Name string `json:"friendly_name,omitempty"` Visibility string `json:"visibility,omitempty"` + OrganizationLogin string `json:"organization_login,omitempty"` EnvironmentVariables map[string]string `json:"environment_variables"` Secrets map[string]string `json:"secrets"` } @@ -40,7 +42,7 @@ func init() { Use: "create", Short: "Create a GitHub Runtime app", Long: heredoc.Doc(` - Create a GitHub Runtime app + Create a GitHub Runtime app. `), Example: heredoc.Doc(` $ gh runtime create --app my-app --env key1=value1 --env key2=value2 --secret key3=value3 --secret key4=value4 @@ -48,6 +50,15 @@ func init() { $ gh runtime create --name my-new-app # => Creates a new app with the given name + + $ gh runtime create --app my-app --visibility only_owner + # => Creates the app visible only to the owner + + $ gh runtime create --app my-app --visibility github + # => Creates the app visible to all GitHub users + + $ gh runtime create --app my-app --visibility selected_orgs --org my-org + # => Creates the app visible to 'my-org' organization `), RunE: func(cmd *cobra.Command, args []string) error { client, err := api.DefaultRESTClient() @@ -70,7 +81,8 @@ func init() { createCmd.Flags().StringVarP(&createCmdFlags.app, "app", "a", "", "The app ID to create") createCmd.Flags().StringVarP(&createCmdFlags.name, "name", "n", "", "The name for the app") - createCmd.Flags().StringVarP(&createCmdFlags.visibility, "visibility", "v", "", "The visibility of the app (e.g. 'only_owner' or 'github')") + createCmd.Flags().StringVarP(&createCmdFlags.visibility, "visibility", "v", "", "The visibility of the app (e.g. 'only_owner', 'github', or 'selected_orgs')") + createCmd.Flags().StringVarP(&createCmdFlags.org, "org", "o", "", "The organization login to grant access (only valid with --visibility=selected_orgs)") createCmd.Flags().StringSliceVarP(&createCmdFlags.environmentVariables, "env", "e", []string{}, "Environment variables to set on the app in the form 'key=value'") createCmd.Flags().StringSliceVarP(&createCmdFlags.secrets, "secret", "s", []string{}, "Secrets to set on the app in the form 'key=value'") createCmd.Flags().StringVarP(&createCmdFlags.revisionName, "revision-name", "r", "", "The revision name to use for the app") @@ -83,9 +95,18 @@ func runCreate(client restClient, flags createCmdFlags) (createResp, error) { return createResp{}, fmt.Errorf("either --app or --name flag is required") } + if flags.org != "" && flags.visibility != "selected_orgs" { + return createResp{}, fmt.Errorf("--org can only be used with --visibility=selected_orgs") + } + + if flags.visibility == "selected_orgs" && flags.org == "" { + return createResp{}, fmt.Errorf("--org is required when --visibility=selected_orgs") + } + requestBody := createReq{ Name: flags.name, Visibility: flags.visibility, + OrganizationLogin: flags.org, EnvironmentVariables: map[string]string{}, Secrets: map[string]string{}, } diff --git a/cmd/create_test.go b/cmd/create_test.go index f101cba..26dab02 100644 --- a/cmd/create_test.go +++ b/cmd/create_test.go @@ -220,6 +220,40 @@ func TestRunCreate_WithVisibility(t *testing.T) { assert.Equal(t, "github", req.Visibility) } +func TestRunCreate_OrgWithoutSelectedOrgsVisibility(t *testing.T) { + client := &mockRESTClient{} + _, err := runCreate(client, createCmdFlags{app: "my-app", org: "my-org"}) + require.ErrorContains(t, err, "--org can only be used with --visibility=selected_orgs") + + _, err = runCreate(client, createCmdFlags{app: "my-app", visibility: "github", org: "my-org"}) + require.ErrorContains(t, err, "--org can only be used with --visibility=selected_orgs") +} + +func TestRunCreate_SelectedOrgsVisibilityWithoutOrg(t *testing.T) { + client := &mockRESTClient{} + _, err := runCreate(client, createCmdFlags{app: "my-app", visibility: "selected_orgs"}) + require.ErrorContains(t, err, "--org is required when --visibility=selected_orgs") +} + +func TestRunCreate_WithOrgAndSelectedOrgsVisibility(t *testing.T) { + var capturedBody []byte + client := &mockRESTClient{ + putFunc: func(_ string, body io.Reader, resp interface{}) error { + capturedBody, _ = io.ReadAll(body) + buildCreateResponse(createResp{AppUrl: "https://my-app.example.com"}, resp) + return nil + }, + } + + _, err := runCreate(client, createCmdFlags{app: "my-app", visibility: "selected_orgs", org: "my-org"}) + require.NoError(t, err) + + var req createReq + json.Unmarshal(capturedBody, &req) + assert.Equal(t, "selected_orgs", req.Visibility) + assert.Equal(t, "my-org", req.OrganizationLogin) +} + func TestRunCreate_ResponseWithID(t *testing.T) { client := &mockRESTClient{ putFunc: func(_ string, _ io.Reader, resp interface{}) error { diff --git a/go.mod b/go.mod index 0fd94dd..59d3871 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/MakeNowJust/heredoc v1.0.0 github.com/cli/go-gh/v2 v2.12.2 github.com/spf13/cobra v1.10.1 + github.com/stretchr/testify v1.10.0 ) require ( @@ -23,7 +24,6 @@ require ( github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rivo/uniseg v0.4.7 // indirect github.com/spf13/pflag v1.0.9 // indirect - github.com/stretchr/testify v1.10.0 // indirect github.com/thlib/go-timezone-local v0.0.0-20210907160436-ef149e42d28e // indirect golang.org/x/sys v0.31.0 // indirect golang.org/x/term v0.30.0 // indirect