Skip to content

Commit

Permalink
feat: with shuttle available outside of a repository (#204)
Browse files Browse the repository at this point in the history
* feat: with shuttle available outside of a repository

Signed-off-by: Kasper J. Hermansen <contact@kjuulh.io>

* feat: add run command specifically

Signed-off-by: Kasper J. Hermansen <contact@kjuulh.io>

---------

Signed-off-by: Kasper J. Hermansen <contact@kjuulh.io>
  • Loading branch information
kjuulh committed Dec 12, 2023
1 parent afb9408 commit 64b0337
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 38 deletions.
92 changes: 68 additions & 24 deletions cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package cmd

import (
stdcontext "context"
"errors"
"fmt"
"io"
"log"
Expand Down Expand Up @@ -70,7 +71,7 @@ __shuttle_custom_func() {
}
`

func newRoot(uii *ui.UI) (*cobra.Command, contextProvider) {
func newRoot(uii *ui.UI) (*cobra.Command, contextProvider, repositoryContext) {
telemetry.Setup()

var (
Expand Down Expand Up @@ -117,7 +118,11 @@ If none of above is used, then the argument will expect a full plan spec.`)
return getProjectContext(rootCmd, uii, projectPath, clean, plan, skipGitPlanPulling)
}

return rootCmd, ctxProvider
repositoryCtxProvider := func() bool {
return getRepositoryContext(projectPath)
}

return rootCmd, ctxProvider, repositoryCtxProvider
}

func Execute(stdout, stderr io.Writer) {
Expand Down Expand Up @@ -145,7 +150,7 @@ func Execute(stdout, stderr io.Writer) {
func initializedRootFromArgs(stdout, stderr io.Writer, args []string) (*cobra.Command, *ui.UI, error) {
uii := ui.Create(stdout, stderr)

rootCmd, ctxProvider := newRoot(uii)
rootCmd, ctxProvider, isInRepoContext := newRoot(uii)
rootCmd.SetOut(stdout)
rootCmd.SetErr(stderr)

Expand All @@ -154,34 +159,48 @@ func initializedRootFromArgs(stdout, stderr io.Writer, args []string) (*cobra.Co
// Run and LS will not get closured variables from contextProvider
rootCmd.ParseFlags(args)

runCmd, initErr := newRun(uii, ctxProvider)
if initErr != nil {
return nil, nil, initErr
}
rootCmd.AddCommand(
newDocumentation(uii, ctxProvider),
newCompletion(uii),
newGet(uii, ctxProvider),
newGitPlan(uii, ctxProvider),
newHas(uii, ctxProvider),
newLs(uii, ctxProvider),
newPlan(uii, ctxProvider),
runCmd,
newPrepare(uii, ctxProvider),
newTemplate(uii, ctxProvider),
newVersion(uii),
newConfig(uii, ctxProvider),
newTelemetry(uii),
)
if isInRepoContext() {
runCmd, err := newRun(uii, ctxProvider)
if err != nil {
return nil, nil, err
}
rootCmd.AddCommand(
newDocumentation(uii, ctxProvider),
newCompletion(uii),
newGet(uii, ctxProvider),
newGitPlan(uii, ctxProvider),
newHas(uii, ctxProvider),
newLs(uii, ctxProvider),
newPlan(uii, ctxProvider),
runCmd,
newPrepare(uii, ctxProvider),
newTemplate(uii, ctxProvider),
newVersion(uii),
newConfig(uii, ctxProvider),
newTelemetry(uii),
)

return rootCmd, uii, nil
return rootCmd, uii, nil
} else {
rootCmd.AddCommand(
newNoContextRun(),
newCompletion(uii),
newVersion(uii),
newTelemetry(uii),
newHas(uii, ctxProvider),
newConfig(uii, ctxProvider),
)

return rootCmd, uii, nil
}
}

func initializedRoot(out, err io.Writer) (*cobra.Command, *ui.UI, error) {
return initializedRootFromArgs(out, err, os.Args[1:])
}

type contextProvider func() (config.ShuttleProjectContext, error)
type repositoryContext func() bool

func getProjectContext(
rootCmd *cobra.Command,
Expand All @@ -194,7 +213,6 @@ func getProjectContext(
dir, err := os.Getwd()
if err != nil {
log.Fatal(err)
os.Exit(1)
}

projectFlagSet := rootCmd.Flags().Changed("project")
Expand Down Expand Up @@ -260,3 +278,29 @@ func getProjectContext(

return c, nil
}

// getRepositoryContext makes sure that we're in a repository context, this is useful to add extra commands, which are only useful when in a repository with a shuttle file
func getRepositoryContext(projectPath string) bool {

var fullProjectPath string
if path.IsAbs(projectPath) {
fullProjectPath = projectPath
} else {
dir, err := os.Getwd()
if err != nil {
log.Fatal(err)
}

fullProjectPath = path.Join(dir, projectPath)
}

shuttleFile := path.Join(fullProjectPath, "shuttle.yaml")

if _, err := os.Stat(shuttleFile); err != nil {
if errors.Is(err, os.ErrNotExist) {
return false
}
}

return true
}
26 changes: 20 additions & 6 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,25 @@ import (
"github.com/lunarway/shuttle/pkg/ui"
)

func newNoopRun() *cobra.Command {
return &cobra.Command{
Use: "run [command]",
Short: "Run a plan script",
Long: `Specify which plan script to run`,
SilenceUsage: true,
}
}

func newNoContextRun() *cobra.Command {
runCmd := newNoopRun()

runCmd.RunE = func(cmd *cobra.Command, args []string) error {
return fmt.Errorf("shuttle run is not available in this context. To use shuttle run you need to be in a project with a shuttle.yaml file")
}

return runCmd
}

func newRun(uii *ui.UI, contextProvider contextProvider) (*cobra.Command, error) {
var (
flagTemplate string
Expand All @@ -31,12 +50,7 @@ func newRun(uii *ui.UI, contextProvider contextProvider) (*cobra.Command, error)

executorRegistry := executors.NewRegistry(executors.ShellExecutor, executors.TaskExecutor)

runCmd := &cobra.Command{
Use: "run [command]",
Short: "Run a plan script",
Long: `Specify which plan script to run`,
SilenceUsage: true,
}
runCmd := newNoopRun()

context, err := contextProvider()
if err != nil {
Expand Down
11 changes: 3 additions & 8 deletions cmd/run_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,9 @@ Global Flags:
name: "project without shuttle.yaml",
input: args("-p", "testdata/base", "run", "hello_stdout"),
stdoutput: "",
erroutput: `Error: exit code 2 - Failed to load shuttle configuration: shuttle.yaml file not found
Make sure you are in a project using shuttle and that a 'shuttle.yaml' file is available.
`,
initErr: errors.New(
`exit code 2 - Failed to load shuttle configuration: shuttle.yaml file not found
Make sure you are in a project using shuttle and that a 'shuttle.yaml' file is available.`,
erroutput: "Error: shuttle run is not available in this context. To use shuttle run you need to be in a project with a shuttle.yaml file\n",
err: errors.New(
"shuttle run is not available in this context. To use shuttle run you need to be in a project with a shuttle.yaml file",
),
},
{
Expand Down

0 comments on commit 64b0337

Please sign in to comment.