Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions cmd/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/MakeNowJust/heredoc"
"github.com/cli/go-gh/v2/pkg/api"
"github.com/github/gh-runtime-cli/internal/config"
"github.com/spf13/cobra"
)

Expand All @@ -19,6 +20,7 @@ type deployCmdFlags struct {
app string
revisionName string
sha string
config string
}

func zipDirectory(sourceDir, destinationZip string) error {
Expand Down Expand Up @@ -91,25 +93,35 @@ func init() {
Use: "deploy",
Short: "Deploy app to GitHub Runtime",
Long: heredoc.Doc(`
Deploys a directory to a GitHub Runtime app
Deploys a directory to a GitHub Runtime app.
You can specify the app name using --app flag, --config flag to read from a runtime config file,
or it will automatically read from runtime.config.json in the current directory if it exists.
`),
Example: heredoc.Doc(`
$ gh runtime deploy --dir ./dist --app my-app [--sha <sha>]
# => Deploys the contents of the 'dist' directory to the app named 'my-app'.

$ gh runtime deploy --dir ./dist --config runtime.config.json
# => Deploys using app name from the config file.

$ gh runtime deploy --dir ./dist
# => Deploys using app name from runtime.config.json in current directory (if it exists).
`),
RunE: func(cmd *cobra.Command, args []string) error {
if deployCmdFlags.dir == "" {
return fmt.Errorf("--dir flag is required")
}
if deployCmdFlags.app == "" {
return fmt.Errorf("--app flag is required")

appName, err := config.ResolveAppName(deployCmdFlags.app, deployCmdFlags.config)
if err != nil {
return err
}

if _, err := os.Stat(deployCmdFlags.dir); os.IsNotExist(err) {
return fmt.Errorf("directory '%s' does not exist", deployCmdFlags.dir)
}

_, err := os.ReadDir(deployCmdFlags.dir)
_, err = os.ReadDir(deployCmdFlags.dir)
if err != nil {
return fmt.Errorf("error reading directory '%s': %v", deployCmdFlags.dir, err)
}
Expand All @@ -127,7 +139,7 @@ func init() {
return fmt.Errorf("error creating REST client: %v", err)
}

deploymentsUrl := fmt.Sprintf("runtime/%s/deployment/bundle", deployCmdFlags.app)
deploymentsUrl := fmt.Sprintf("runtime/%s/deployment/bundle", appName)
params := url.Values{}

if deployCmdFlags.revisionName != "" {
Expand Down Expand Up @@ -161,6 +173,7 @@ func init() {
}
deployCmd.Flags().StringVarP(&deployCmdFlags.dir, "dir", "d", "", "The directory to deploy")
deployCmd.Flags().StringVarP(&deployCmdFlags.app, "app", "a", "", "The app to deploy")
deployCmd.Flags().StringVarP(&deployCmdFlags.config, "config", "c", "", "Path to runtime config file")
deployCmd.Flags().StringVarP(&deployCmdFlags.revisionName, "revision-name", "r", "", "The revision name to deploy")
deployCmd.Flags().StringVarP(&deployCmdFlags.sha, "sha", "s", "", "SHA of the app being deployed")

Expand Down
25 changes: 19 additions & 6 deletions cmd/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@ package cmd
import (
"fmt"
"net/url"

"github.com/MakeNowJust/heredoc"
"github.com/cli/go-gh/v2/pkg/api"
"github.com/github/gh-runtime-cli/internal/config"
"github.com/spf13/cobra"
)

type getCmdFlags struct {
app string
revisionName string
app string
revisionName string
config string
}

type serverResponse struct {
Expand All @@ -23,18 +26,27 @@ func init() {
Use: "get",
Short: "Get details of a GitHub Runtime app",
Long: heredoc.Doc(`
Get details of a GitHub Runtime app
Get details of a GitHub Runtime app.
You can specify the app name using --app flag, --config flag to read from a runtime config file,
or it will automatically read from runtime.config.json in the current directory if it exists.
`),
Example: heredoc.Doc(`
$ gh runtime get --app my-app
# => Retrieves details of the app named 'my-app'

$ gh runtime get --config runtime.config.json
# => Retrieves details using app name from the config file.

$ gh runtime get
# => Retrieves details using app name from runtime.config.json in current directory (if it exists).
`),
RunE: func(cmd *cobra.Command, args []string) error {
if getCmdFlags.app == "" {
return fmt.Errorf("--app flag is required")
appName, err := config.ResolveAppName(getCmdFlags.app, getCmdFlags.config)
if err != nil {
return err
}

getUrl := fmt.Sprintf("runtime/%s/deployment", getCmdFlags.app)
getUrl := fmt.Sprintf("runtime/%s/deployment", appName)
params := url.Values{}
if getCmdFlags.revisionName != "" {
params.Add("revision_name", getCmdFlags.revisionName)
Expand All @@ -60,6 +72,7 @@ func init() {
}

getCmd.Flags().StringVarP(&getCmdFlags.app, "app", "a", "", "The app to retrieve details for")
getCmd.Flags().StringVarP(&getCmdFlags.config, "config", "c", "", "Path to runtime config file")
getCmd.Flags().StringVarP(&getCmdFlags.revisionName, "revision-name", "r", "", "The revision name to use for the app")
rootCmd.AddCommand(getCmd)
}
9 changes: 3 additions & 6 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/MakeNowJust/heredoc"
"github.com/cli/go-gh/v2/pkg/api"
"github.com/github/gh-runtime-cli/internal/config"
"github.com/spf13/cobra"
)

Expand All @@ -16,10 +17,6 @@ type initCmdFlags struct {
out string
}

type runtimeConfig struct {
App string `json:"app"`
}

type appResponse struct {
AppUrl string `json:"app_url"`
}
Expand Down Expand Up @@ -67,7 +64,7 @@ func init() {
}

// Create runtime config
config := runtimeConfig{
configStruct := config.RuntimeConfig{
App: initCmdFlags.app,
}

Expand All @@ -84,7 +81,7 @@ func init() {
}
}

configBytes, err := json.MarshalIndent(config, "", " ")
configBytes, err := json.MarshalIndent(configStruct, "", " ")
if err != nil {
return fmt.Errorf("error creating configuration: %v", err)
}
Expand Down
57 changes: 57 additions & 0 deletions internal/config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package config

import (
"encoding/json"
"fmt"
"os"
)

// RuntimeConfig represents the structure of the runtime configuration file
type RuntimeConfig struct {
App string `json:"app"`
}

// ReadRuntimeConfig reads and parses a runtime configuration file
func ReadRuntimeConfig(configPath string) (string, error) {
configBytes, err := os.ReadFile(configPath)
if err != nil {
return "", fmt.Errorf("error reading config file '%s': %w", configPath, err)
}

var config RuntimeConfig
err = json.Unmarshal(configBytes, &config)
if err != nil {
return "", fmt.Errorf("error parsing config file '%s': %w", configPath, err)
}

return config.App, nil
}

// ResolveAppName resolves the app name using the priority order:
// 1. appFlag (--app) if provided
// 2. configPath (--config) if provided
// 3. runtime.config.json in current directory if it exists
// Returns an error if no app name can be resolved
func ResolveAppName(appFlag, configPath string) (string, error) {
// Priority 1: Use --app flag if provided
if appFlag != "" {
return appFlag, nil
}

// Priority 2: Use --config file if provided
if configPath != "" {
return ReadRuntimeConfig(configPath)
}

// Priority 3: Try default runtime.config.json
if _, err := os.Stat("runtime.config.json"); err == nil {
appName, err := ReadRuntimeConfig("runtime.config.json")
if err != nil {
return "", fmt.Errorf("found runtime.config.json but failed to read it: %v", err)
}
return appName, nil
}

// No app name could be resolved
return "", fmt.Errorf("--app flag is required, --config must be specified, or runtime.config.json must exist in current directory")
}
Loading