cmd

package
v0.25.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 14, 2023 License: Apache-2.0 Imports: 43 Imported by: 0

Documentation

Index

Constants

View Source
const (
	TidbytAPIPush = "https://api.tidbyt.com/v0/devices/%s/push"
	APITokenEnv   = "TIDBYT_API_TOKEN"
)
View Source
const PublicKeysetJSON = `` /* 543-byte string literal not displayed */
View Source
const (
	TidbytAPIListDevices = "https://api.tidbyt.com/v0/devices"
)

Variables

View Source
var BundleCmd = &cobra.Command{
	Use:     "bundle",
	Short:   "Creates a new app bundle",
	Example: `  pixlet bundle apps/fuzzyclock/`,
	Long: `This command will create a new app bundle from an app directory. The directory
should contain an app manifest and source file. The output of this command will
be a gzip compressed tar file that can be uploaded to Tidbyt for deployment.`,
	Args: cobra.ExactArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		bundleInput := args[0]
		info, err := os.Stat(bundleInput)
		if err != nil {
			return fmt.Errorf("input directory invalid: %w", err)
		}

		if !info.IsDir() {
			return fmt.Errorf("input must be a directory")
		}

		info, err = os.Stat(bundleOutput)
		if err != nil {
			return fmt.Errorf("output directory invalid: %w", err)
		}

		if !info.IsDir() {
			return fmt.Errorf("output must be a directory")
		}

		ab, err := bundle.InitFromPath(bundleInput)
		if err != nil {
			return fmt.Errorf("could not init bundle: %w", err)
		}

		return ab.WriteBundleToPath(bundleOutput)
	},
}
View Source
var CheckCmd = &cobra.Command{
	Use:     "check <pathspec>...",
	Example: `  pixlet check app.star`,
	Short:   "Checks if an app is ready to publish",
	Long: `The check command runs a series of checks to ensure your app is ready
to publish in the community repo. Every failed check will have a solution
provided. If your app fails a check, try the provided solution and reach out on
Discord if you get stuck.`,
	Args: cobra.MinimumNArgs(1),
	RunE: checkCmd,
}
View Source
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.`,
	RunE: func(cmd *cobra.Command, args []string) error {

		cwd, err := os.Getwd()
		if err != nil {
			return fmt.Errorf("app creation failed, something went wrong with your local filesystem: %w", err)
		}

		// Determine what type of app this is an what the root should be.
		var root string
		var appType generator.AppType
		if repo.IsInRepo(cwd, "community") {
			appType = generator.Community
			root, err = repo.RepoRoot(cwd)
			if err != nil {
				return fmt.Errorf("app creation failed, something went wrong with your community repo: %w", err)
			}
		} else if repo.IsInRepo(cwd, "tidbyt") {
			appType = generator.Internal
			root, err = repo.RepoRoot(cwd)
			if err != nil {
				return fmt.Errorf("app creation failed, something went wrong with your tidbyt repo: %w", err)
			}
		} else {
			appType = generator.Local
			root = cwd
		}

		app, err := community.ManifestPrompt()
		if err != nil {
			return fmt.Errorf("app creation, couldn't get user input: %w", err)
		}

		g, err := generator.NewGenerator(appType, root)
		if err != nil {
			return fmt.Errorf("app creation failed %w", err)
		}
		absolutePath, err := g.GenerateApp(app)
		if err != nil {
			return fmt.Errorf("app creation failed: %w", err)
		}

		relativePath, err := filepath.Rel(cwd, absolutePath)
		if err != nil {
			return fmt.Errorf("app was created, but we don't know where: %w", err)
		}

		fmt.Println("")
		fmt.Println("App created at:")
		fmt.Printf("\t%s\n", absolutePath)
		fmt.Println("")
		fmt.Println("To start the app, run:")
		fmt.Printf("\tpixlet serve %s\n", relativePath)
		fmt.Println("")
		fmt.Println("For docs, head to:")
		fmt.Printf("\thttps://tidbyt.dev\n")
		return nil
	},
}

CreateCmd prompts the user for info and generates a new app.

View Source
var DeployCmd = &cobra.Command{
	Use:     "deploy",
	Short:   "Deploys an app to production (internal only)",
	Example: `  pixlet deploy --app fuzzy-clock --version v0.0.1`,
	Long: `This command will deploy an app to production in the Tidbyt backend. Note, this
command is for internal use only at the moment, and normal API tokens will not
be able to deploy apps. We fully intend to make this command generally available
once our backend can support public deploys.`,
	RunE: func(cmd *cobra.Command, args []string) error {
		apiToken := oauthTokenFromConfig(cmd.Context())
		if apiToken == "" {
			return fmt.Errorf("login with `pixlet login` or use `pixlet set-auth` to configure auth")
		}

		if deployAppID == "" {
			return fmt.Errorf("app must not be blank")
		}

		if deployVersion == "" {
			return fmt.Errorf("version must not be blank")
		}

		d := &TidbytAppDeploy{
			AppID:   deployAppID,
			Version: deployVersion,
		}

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

		requestURL := fmt.Sprintf("%s/v0/apps/%s/deploy", deployURL, deployAppID)
		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)
		}

		return nil
	},
}
View Source
var DevicesCmd = &cobra.Command{
	Use:   "devices",
	Short: "List devices in your Tidbyt account",
	Run:   devices,
}
View Source
var EncryptCmd = &cobra.Command{
	Use:     "encrypt [app name] [secret value]...",
	Short:   "Encrypt a secret for use in the Tidbyt community repo",
	Example: "encrypt weather my-top-secretweather-api-key-123456",
	Args:    cobra.MinimumNArgs(2),
	Run:     encrypt,
}
View Source
var FormatCmd = &cobra.Command{
	Use:   "format <pathspec>...",
	Short: "Formats Tidbyt apps",
	Example: `  pixlet format app.star
  pixlet format app.star --dry-run
  pixlet format --recursive ./`,
	Long: `The format command provides a code formatter for Tidbyt apps. By default, it
will format your starlark source code in line. If you wish you see the output
before applying, add the --dry-run flag.`,
	Args: cobra.MinimumNArgs(1),
	RunE: formatCmd,
}
View Source
var LintCmd = &cobra.Command{
	Use: "lint <pathspec>...",
	Example: `  pixlet lint app.star
  pixlet lint --recursive --fix ./`,
	Short: "Lints Tidbyt apps",
	Long: `The lint command provides a linter for Tidbyt apps. It's capable of linting a
file, a list of files, or directory with the recursive option. Additionally, it
provides an option to automatically fix resolvable linter issues.`,
	Args: cobra.MinimumNArgs(1),
	RunE: lintCmd,
}
View Source
var LoginCmd = &cobra.Command{
	Use:     "login",
	Short:   "Login to your Tidbyt account",
	Example: "login",
	Run:     login,
}
View Source
var ProfileCmd = &cobra.Command{
	Use:   "profile [script] [<key>=value>]...",
	Short: "Run a Pixlet script and print its execution-time profile",
	Args:  cobra.MinimumNArgs(1),
	RunE:  profile,
}
View Source
var PushCmd = &cobra.Command{
	Use:   "push [device ID] [webp image]",
	Short: "Render a Pixlet script and push the WebP output to a Tidbyt",
	Args:  cobra.MinimumNArgs(2),
	RunE:  push,
}
View Source
var RenderCmd = &cobra.Command{
	Use:   "render [script] [<key>=value>]...",
	Short: "Run a Pixlet script with provided config parameters",
	Args:  cobra.MinimumNArgs(1),
	RunE:  render,
}
View Source
var ServeCmd = &cobra.Command{
	Use:   "serve [script]",
	Short: "Serve a Pixlet app in a web server",
	Args:  cobra.ExactArgs(1),
	RunE:  serve,
}
View Source
var SetAuthCmd = &cobra.Command{
	Use:     "set-auth",
	Short:   "Sets a custom access token in the private pixlet config.",
	Example: `  pixlet set-auth <token_json>`,
	Long: `This command sets a custom access token for use in subsequent runs. Normal users
should not need this - use 'pixlet login' instead.`,
	Args: cobra.ExactArgs(1),
	RunE: SetAuth,
}
View Source
var UploadCmd = &cobra.Command{
	Use:     "upload",
	Short:   "Uploads an app bundle to Tidbyt (internal only)",
	Example: `  pixlet upload bundle.tar.gz --app fuzzy-clock --version v0.0.1 --token {{ api_token }}`,
	Long: `This command will upload an app bundle (see pixlet bundle) using the specified
app ID and version. Note, this is for internal use only at the moment, and
normal API tokens will not work with this command. We fully intend to make this
command public once our backend is well positioned to support it.`,
	Args: cobra.ExactArgs(1),
	RunE: func(cmd *cobra.Command, args []string) error {
		bundleFile := args[0]
		info, err := os.Stat(bundleFile)
		if err != nil {
			return fmt.Errorf("input bundle file invalid: %w", err)
		}

		if info.IsDir() {
			return fmt.Errorf("input bundle must be a file")
		}

		if !strings.HasSuffix(bundleFile, "tar.gz") {
			return fmt.Errorf("input bundle format is not correct, did you create it with `pixlet bundle`?")
		}

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

		if uploadAppID == "" {
			return fmt.Errorf("app must not be blank")
		}

		if uploadVersion == "" {
			return fmt.Errorf("version must not be blank")
		}

		f, err := os.Open(bundleFile)
		if err != nil {
			return fmt.Errorf("could not open bundle: %w", err)
		}
		defer f.Close()

		ab, err := bundle.LoadBundle(f)
		if err != nil {
			return fmt.Errorf("could not load bundle: %w", err)
		}

		buf := &bytes.Buffer{}
		err = ab.WriteBundle(buf)
		if err != nil {
			return fmt.Errorf("could not re-create bundle: %w", err)
		}

		uploadBundle := &TidbytBundleUpload{
			AppID:   uploadAppID,
			Version: uploadVersion,
			Bundle:  base64.StdEncoding.EncodeToString(buf.Bytes()),
		}

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

		requestURL := fmt.Sprintf("%s/v0/apps/%s/upload", uploadURL, uploadAppID)
		req, err := http.NewRequest(http.MethodPost, requestURL, bytes.NewReader(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)
		}

		return nil
	},
}
View Source
var Version string
View Source
var VersionCmd = &cobra.Command{
	Use:   "version",
	Short: "Show the version of Pixlet",
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Printf("Pixlet version: %s\n", Version)
	},
}

Functions

func SetAuth added in v0.25.0

func SetAuth(cmd *cobra.Command, args []string) error

Types

type FetchFunc added in v0.17.16

type FetchFunc func(src string, duration, timeout time.Duration) (*pprof_profile.Profile, string, error)

We save the profile into an in-memory buffer, which is simpler than the tool expects. Simple adapter to pipe it through.

func MakeFetchFunc added in v0.17.16

func MakeFetchFunc(prof *pprof_profile.Profile) FetchFunc

func (FetchFunc) Fetch added in v0.17.16

func (f FetchFunc) Fetch(src string, duration, timeout time.Duration) (*pprof_profile.Profile, string, error)

type TidbytAppDeploy added in v0.25.0

type TidbytAppDeploy struct {
	AppID   string `json:"appID"`
	Version string `json:"version"`
}

type TidbytBundleUpload added in v0.25.0

type TidbytBundleUpload struct {
	AppID   string `json:"appID"`
	Version string `json:"version"`
	Bundle  string `json:"bundle"`
}

type TidbytPushJSON

type TidbytPushJSON struct {
	DeviceID       string `json:"deviceID"`
	Image          string `json:"image"`
	InstallationID string `json:"installationID"`
	Background     bool   `json:"background"`
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL