diff --git a/internal/cmd/stack/flags.go b/internal/cmd/stack/flags.go index 0702541..25f92d4 100644 --- a/internal/cmd/stack/flags.go +++ b/internal/cmd/stack/flags.go @@ -52,7 +52,12 @@ var flagRequiredRun = &cli.StringFlag{ var flagRun = &cli.StringFlag{ Name: "run", - Usage: "`ID` of the run", + Usage: "[Optional] `ID` of the run", +} + +var flagRunLatest = &cli.BoolFlag{ + Name: "run-latest", + Usage: "[Optional] Indicates that the latest run should be used", } var flagNoInit = &cli.BoolFlag{ diff --git a/internal/cmd/stack/run_logs.go b/internal/cmd/stack/run_logs.go index 3880570..79004ba 100644 --- a/internal/cmd/stack/run_logs.go +++ b/internal/cmd/stack/run_logs.go @@ -5,7 +5,9 @@ import ( "fmt" "time" + "github.com/pkg/errors" "github.com/shurcooL/graphql" + "github.com/urfave/cli/v2" "github.com/spacelift-io/spacectl/client/structs" "github.com/spacelift-io/spacectl/internal/cmd/authenticated" @@ -17,6 +19,49 @@ import ( // for example to confirm a run. type actionOnRunState func(state structs.RunState, stackID, runID string) error +func runLogs(cliCtx *cli.Context) error { + stackID, err := getStackID(cliCtx) + if err != nil { + return err + } + + if (!cliCtx.IsSet(flagRun.Name) && !cliCtx.IsSet(flagRunLatest.Name)) || + (cliCtx.IsSet(flagRun.Name) && cliCtx.IsSet(flagRunLatest.Name)) { + return errors.New("you must specify either --run or --run-latest") + } + + runID := cliCtx.String(flagRun.Name) + if cliCtx.IsSet(flagRunLatest.Name) { + type runsQuery struct { + ID string `graphql:"id"` + } + + var query struct { + Stack *struct { + Runs []runsQuery `graphql:"runs(before: $before)"` + } `graphql:"stack(id: $stackId)"` + } + + var before *string + if err := authenticated.Client.Query(cliCtx.Context, &query, map[string]interface{}{"stackId": stackID, "before": before}); err != nil { + return errors.Wrap(err, "failed to query run list") + } + + if query.Stack == nil { + return fmt.Errorf("failed to lookup logs with flag --run-latest, stack %q not found", stackID) + } + + if len(query.Stack.Runs) == 0 { + return errors.New("failed to lookup logs with flag --run-latest, no runs found") + } + + runID = query.Stack.Runs[0].ID + } + + _, err = runLogsWithAction(context.Background(), stackID, runID, nil) + return err +} + func runLogsWithAction(ctx context.Context, stack, run string, acFn actionOnRunState) (terminal *structs.RunStateTransition, err error) { lines := make(chan string) diff --git a/internal/cmd/stack/stack.go b/internal/cmd/stack/stack.go index 080bed9..1babe1f 100644 --- a/internal/cmd/stack/stack.go +++ b/internal/cmd/stack/stack.go @@ -1,8 +1,6 @@ package stack import ( - "context" - "github.com/urfave/cli/v2" "github.com/spacelift-io/spacectl/internal/cmd" @@ -133,16 +131,10 @@ func Command() *cli.Command { Usage: "Show logs for a particular run", Flags: []cli.Flag{ flagStackID, - flagRequiredRun, - }, - Action: func(cliCtx *cli.Context) error { - stackID, err := getStackID(cliCtx) - if err != nil { - return err - } - _, err = runLogsWithAction(context.Background(), stackID, cliCtx.String(flagRequiredRun.Name), nil) - return err + flagRun, + flagRunLatest, }, + Action: runLogs, Before: authenticated.Ensure, ArgsUsage: cmd.EmptyArgsUsage, },