Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow spacectl usage in hooks #286

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
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
Loading