Skip to content

Commit

Permalink
feat: allow spacectl usage in hooks
Browse files Browse the repository at this point in the history
Signed-off-by: Jakub <[email protected]>
  • Loading branch information
sephriot committed Jan 31, 2025
1 parent fa1efbb commit 524502b
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 31 deletions.
28 changes: 27 additions & 1 deletion internal/cmd/stack/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ func searchAllStacks(ctx context.Context, input structs.SearchInput) ([]stack, e
)
}

result, err := searchStacks(ctx, pageInput)
result, err := searchStacks[stack](ctx, pageInput)
if err != nil {
return nil, err
}
Expand All @@ -179,6 +179,24 @@ func searchAllStacks(ctx context.Context, input structs.SearchInput) ([]stack, e
return out, nil
}

type hasIDAndName interface {
GetID() string
GetName() string
}

type stackID struct {
ID string `graphql:"id" json:"id,omitempty"`
Name string `graphql:"name" json:"name,omitempty"`
}

func (s stackID) GetID() string {
return s.ID
}

func (s stackID) GetName() string {
return s.Name
}

type stack struct {
ID string `graphql:"id" json:"id,omitempty"`
Administrative bool `graphql:"administrative" json:"administrative,omitempty"`
Expand Down Expand Up @@ -237,3 +255,11 @@ type stack struct {
Name string `graphql:"name" json:"name,omitempty"`
} `graphql:"workerPool" json:"workerPool,omitempty"`
}

func (s stack) GetID() string {
return s.ID
}

func (s stack) GetName() string {
return s.Name
}
2 changes: 1 addition & 1 deletion internal/cmd/stack/local_preview.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ func localPreview() cli.ActionFunc {
})
}

stack, err := getStack(cliCtx)
stack, err := getStack[stack](cliCtx)
if err != nil {
return err
}
Expand Down
16 changes: 8 additions & 8 deletions internal/cmd/stack/open_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ func openCommandInBrowser(cliCtx *cli.Context) error {
}

func findAndOpenStackInBrowser(ctx context.Context, p *stackSearchParams) error {
got, err := findAndSelectStack(ctx, p, false)
got, err := findAndSelectStack[stack](ctx, p, false)
if errors.Is(err, errNoStackFound) {
return errors.New("No stacks using the provided search parameters, maybe it's in a different subdir?")
}
Expand Down Expand Up @@ -163,16 +163,16 @@ type stackSearchParams struct {
branch *string
}

type searchStacksResult struct {
Stacks []stack
type searchStacksResult[T hasIDAndName] struct {
Stacks []T
PageInfo structs.PageInfo
}

func searchStacks(ctx context.Context, input structs.SearchInput) (searchStacksResult, error) {
func searchStacks[T hasIDAndName](ctx context.Context, input structs.SearchInput) (searchStacksResult[T], error) {
var query struct {
SearchStacksOutput struct {
Edges []struct {
Node stack `graphql:"node"`
Node T `graphql:"node"`
} `graphql:"edges"`
PageInfo structs.PageInfo `graphql:"pageInfo"`
} `graphql:"searchStacks(input: $input)"`
Expand All @@ -184,15 +184,15 @@ func searchStacks(ctx context.Context, input structs.SearchInput) (searchStacksR
map[string]interface{}{"input": input},
graphql.WithHeader("Spacelift-GraphQL-Query", "StacksPage"),
); err != nil {
return searchStacksResult{}, errors.Wrap(err, "failed search for stacks")
return searchStacksResult[T]{}, errors.Wrap(err, "failed search for stacks")
}

stacks := make([]stack, 0)
stacks := make([]T, 0)
for _, q := range query.SearchStacksOutput.Edges {
stacks = append(stacks, q.Node)
}

return searchStacksResult{
return searchStacksResult[T]{
Stacks: stacks,
PageInfo: query.SearchStacksOutput.PageInfo,
}, nil
Expand Down
38 changes: 17 additions & 21 deletions internal/cmd/stack/stack_selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ const (
// 2. Check the --run flag, if set, try to get the stack associated with the run.
// 2. Check the current directory to determine repository and subdirectory and search for a stack.
func getStackID(cliCtx *cli.Context) (string, error) {
stack, err := getStack(cliCtx)
stack, err := getStack[stackID](cliCtx)
if err != nil {
return "", err
}

return stack.ID, nil
}

func getStack(cliCtx *cli.Context) (*stack, error) {
func getStack[T hasIDAndName](cliCtx *cli.Context) (*T, error) {
if cliCtx.IsSet(flagStackID.Name) {
stackID := cliCtx.String(flagStackID.Name)
stack, err := stackGetByID(cliCtx.Context, stackID)
stack, err := stackGetByID[T](cliCtx.Context, stackID)
if errors.Is(err, errNoStackFound) {
return nil, fmt.Errorf("stack with id %q could not be found. Please check that the stack exists and that you have access to it. To list available stacks run: spacectl stack list", stackID)
}
Expand All @@ -50,7 +50,7 @@ func getStack(cliCtx *cli.Context) (*stack, error) {
return stack, nil
} else if cliCtx.IsSet(flagRun.Name) {
runID := cliCtx.String(flagRun.Name)
stack, err := stackGetByRunID(cliCtx.Context, runID)
stack, err := stackGetByRunID[T](cliCtx.Context, runID)
if errors.Is(err, errNoStackFound) {
return nil, fmt.Errorf("run with id %q was not found. Please check that the run exists and that you have access to it. To list available stacks run: spacectl stack run list", runID)
}
Expand All @@ -73,7 +73,7 @@ func getStack(cliCtx *cli.Context) (*stack, error) {

skip := os.Getenv(envPromptSkipKey) == "true"

got, err := findAndSelectStack(cliCtx.Context, &stackSearchParams{
got, err := findAndSelectStack[T](cliCtx.Context, &stackSearchParams{
count: 50,
projectRoot: &subdir,
repositoryName: name,
Expand All @@ -89,11 +89,9 @@ func getStack(cliCtx *cli.Context) (*stack, error) {
return got, nil
}

func stackGetByID(ctx context.Context, stackID string) (*stack, error) {
func stackGetByID[T hasIDAndName](ctx context.Context, stackID string) (*T, error) {
var query struct {
Stack struct {
stack
} `graphql:"stack(id: $id)"`
Stack T `graphql:"stack(id: $id)"`
}

variables := map[string]interface{}{
Expand All @@ -105,18 +103,16 @@ func stackGetByID(ctx context.Context, stackID string) (*stack, error) {
return nil, fmt.Errorf("failed to query GraphQL API when checking if a stack exists: %w", err)
}

if query.Stack.ID != stackID {
if query.Stack.GetID() != stackID {
return nil, errNoStackFound
}

return &query.Stack.stack, nil
return &query.Stack, nil
}

func stackGetByRunID(ctx context.Context, runID string) (*stack, error) {
func stackGetByRunID[T hasIDAndName](ctx context.Context, runID string) (*T, error) {
var query struct {
RunStack struct {
stack
} `graphql:"runStack(runId: $runId)"`
RunStack T `graphql:"runStack(runId: $runId)"`
}

variables := map[string]interface{}{
Expand All @@ -132,10 +128,10 @@ func stackGetByRunID(ctx context.Context, runID string) (*stack, error) {
return nil, fmt.Errorf("failed to query GraphQL API when getting stack by run id: %w", err)
}

return &query.RunStack.stack, nil
return &query.RunStack, nil
}

func findAndSelectStack(ctx context.Context, p *stackSearchParams, forcePrompt bool) (*stack, error) {
func findAndSelectStack[T hasIDAndName](ctx context.Context, p *stackSearchParams, forcePrompt bool) (*T, error) {
conditions := []structs.QueryPredicate{
{
Field: graphql.String("repository"),
Expand Down Expand Up @@ -169,16 +165,16 @@ func findAndSelectStack(ctx context.Context, p *stackSearchParams, forcePrompt b
Predicates: &conditions,
}

result, err := searchStacks(ctx, input)
result, err := searchStacks[T](ctx, input)
if err != nil {
return nil, err
}

items := []string{}
found := map[string]stack{}
found := map[string]T{}
for _, s := range result.Stacks {
items = append(items, s.Name)
found[s.Name] = s
items = append(items, s.GetName())
found[s.GetName()] = s
}

if len(found) == 0 {
Expand Down

0 comments on commit 524502b

Please sign in to comment.