Skip to content

Commit

Permalink
feat: Support private app creation. (#870)
Browse files Browse the repository at this point in the history
This commit updates the create command to be able to support the
creation of private apps. This is only available for Tidbyt For Teams
customers at the moment and for the forseeable future.
  • Loading branch information
betterengineering authored Aug 21, 2023
1 parent d220618 commit 25e5e8f
Showing 1 changed file with 92 additions and 1 deletion.
93 changes: 92 additions & 1 deletion cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,44 @@
package cmd

import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"time"

"github.com/spf13/cobra"
"tidbyt.dev/pixlet/cmd/community"
"tidbyt.dev/pixlet/tools/generator"
"tidbyt.dev/pixlet/tools/repo"
)

var createPrivate bool
var createOrg string
var createURL string

type TidbytCreateAppRequest struct {
OrganizationID string `json:"organizationID"`
}

type TidbytCreateAppReply struct {
AppID string `json:"appID"`
}

func init() {
CreateCmd.Flags().StringVarP(&createOrg, "org", "o", "", "organization to create the app in")
CreateCmd.Flags().BoolVarP(&createPrivate, "private", "p", false, "create a private app")
CreateCmd.Flags().StringVarP(&createURL, "url", "u", "https://api.tidbyt.com", "base URL of the remote bundle store")
}

// CreateCmd prompts the user for info and generates a new app.
var CreateCmd = &cobra.Command{
Use: "create",
Short: "Creates a new app",
Long: `This command will prompt for all of the information we need to generate a new Tidbyt app.`,
Long: `This command will prompt for all of the information we need to generate a new Tidbyt app. No flags are necessary unless you are creating a private app, which is only available with our Tidbyt For Teams offering.`,
RunE: func(cmd *cobra.Command, args []string) error {
// Get the current working directory.
cwd, err := os.Getwd()
Expand Down Expand Up @@ -51,6 +74,23 @@ var CreateCmd = &cobra.Command{
return fmt.Errorf("app creation, couldn't get user input: %w", err)
}

if createPrivate {
// create a private app
apiToken := oauthTokenFromConfig(cmd.Context())
if apiToken == "" {
return fmt.Errorf("login with `pixlet login` or use `pixlet set-auth` to configure auth")
}

if createOrg == "" {
return fmt.Errorf("organization must not be blank")
}

app.ID, err = createPrivateApp(apiToken, createOrg)
if err != nil {
return fmt.Errorf("remote app creation failed: %w", err)
}
}

// Generate app.
g, err := generator.NewGenerator(appType, root)
if err != nil {
Expand Down Expand Up @@ -78,6 +118,57 @@ var CreateCmd = &cobra.Command{
fmt.Println("")
fmt.Println("For docs, head to:")
fmt.Printf("\thttps://tidbyt.dev\n")

if createPrivate {
fmt.Println("")
fmt.Println("To deploy your app:")
fmt.Printf("\tpixlet bundle ./\n")
fmt.Printf("\tpixlet upload bundle.tar.gz --app %s --version v0.0.1\n", app.ID)
fmt.Printf("\tpixlet deploy --app %s --version v0.0.1\n", app.ID)
}
return nil
},
}

func createPrivateApp(apiToken string, org string) (string, error) {
createAppRequest := &TidbytCreateAppRequest{
OrganizationID: org,
}

b, err := json.Marshal(createAppRequest)
if err != nil {
return "", fmt.Errorf("could not create http request: %w", err)
}

requestURL := fmt.Sprintf("%s/v0/apps", createURL)
req, err := http.NewRequest(http.MethodPost, requestURL, bytes.NewBuffer(b))
if err != nil {
return "", fmt.Errorf("could not create http request: %w", err)
}

req.Header.Set("Content-Type", "application/json")
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", apiToken))

client := http.Client{
Timeout: 30 * time.Second,
}

resp, err := client.Do(req)
if err != nil {
return "", fmt.Errorf("could not make HTTP request to %s: %w", requestURL, err)
}
defer resp.Body.Close()

if resp.StatusCode != 200 {
body, _ := io.ReadAll(resp.Body)
return "", fmt.Errorf("request returned status %d with message: %s", resp.StatusCode, body)
}

createAppReply := &TidbytCreateAppReply{}
err = json.NewDecoder(resp.Body).Decode(&createAppReply)
if err != nil {
return "", fmt.Errorf("could not decode response: %w", err)
}

return createAppReply.AppID, nil
}

0 comments on commit 25e5e8f

Please sign in to comment.