diff --git a/cmd/sst/deploy.go b/cmd/sst/deploy.go index 6cda321c53..776fe4da1c 100644 --- a/cmd/sst/deploy.go +++ b/cmd/sst/deploy.go @@ -29,6 +29,12 @@ var CmdDeploy = &cli.Command{ "sst deploy --target MyComponent", "```", "", + "Alternatively, exclude a specific component from the deploy.", + "", + "```bash frame=\"none\"", + "sst deploy --exclude MyComponent", + "```", + "", "All the resources are deployed as concurrently as possible, based on their dependencies.", "For resources like your container images, sites, and functions; it first builds them and then deploys the generated assets.", "", @@ -89,6 +95,14 @@ var CmdDeploy = &cli.Command{ Long: "Only run it for the given component.", }, }, + { + Name: "exclude", + Type: "string", + Description: cli.Description{ + Short: "Exclude a component", + Long: "Exclude the specified component from the operation.", + }, + }, { Name: "continue", Type: "bool", @@ -126,6 +140,11 @@ var CmdDeploy = &cli.Command{ target = strings.Split(c.String("target"), ",") } + exclude := []string{} + if c.String("exclude") != "" { + exclude = strings.Split(c.String("exclude"), ",") + } + var wg errgroup.Group defer wg.Wait() out := make(chan interface{}) @@ -152,6 +171,7 @@ var CmdDeploy = &cli.Command{ err = p.Run(c.Context, &project.StackInput{ Command: "deploy", Target: target, + Exclude: exclude, Dev: c.Bool("dev"), ServerPort: s.Port, Verbose: c.Bool("verbose"), diff --git a/cmd/sst/diff.go b/cmd/sst/diff.go index a396f6ab29..e9c7208f50 100644 --- a/cmd/sst/diff.go +++ b/cmd/sst/diff.go @@ -39,6 +39,12 @@ var CmdDiff = &cli.Command{ "sst diff --target MyComponent", "```", "", + "Alternatively, exclude a specific component from the diff.", + "", + "```bash frame=\"none\"", + "sst diff --exclude MyComponent", + "```", + "", "By default, this compares to the last deploy of the given stage as it would be", "deployed using `sst deploy`. But if you are working in dev mode using `sst dev`,", "you can use the `--dev` flag.", @@ -58,6 +64,14 @@ var CmdDiff = &cli.Command{ Long: "Only run it for the given component.", }, }, + { + Name: "exclude", + Type: "string", + Description: cli.Description{ + Short: "Exclude a component", + Long: "Exclude the specified component from the operation.", + }, + }, { Name: "dev", Type: "bool", @@ -89,6 +103,11 @@ var CmdDiff = &cli.Command{ target = strings.Split(c.String("target"), ",") } + exclude := []string{} + if c.String("exclude") != "" { + exclude = strings.Split(c.String("exclude"), ",") + } + var wg errgroup.Group defer wg.Wait() outputs := []*apitype.ResOutputsEvent{} @@ -121,6 +140,7 @@ var CmdDiff = &cli.Command{ ServerPort: s.Port, Dev: c.Bool("dev"), Target: target, + Exclude: exclude, Verbose: c.Bool("verbose"), }) if err != nil { diff --git a/cmd/sst/main.go b/cmd/sst/main.go index d793075607..1a4834225b 100644 --- a/cmd/sst/main.go +++ b/cmd/sst/main.go @@ -968,6 +968,12 @@ var root = &cli.Command{ "sst refresh --target MyComponent", "```", "", + "Alternatively, exclude a specific component from the refresh.", + "", + "```bash frame=\"none\"", + "sst refresh --exclude MyComponent", + "```", + "", "This is useful for cases where you want to ensure that your local state is in sync with your cloud provider. [Learn more about how state works](/docs/providers/#how-state-works).", }, "\n"), }, @@ -980,6 +986,14 @@ var root = &cli.Command{ Long: "Only run it for the given component.", }, }, + { + Name: "exclude", + Type: "string", + Description: cli.Description{ + Short: "Exclude a component", + Long: "Exclude the specified component from the operation.", + }, + }, }, Run: CmdRefresh, }, diff --git a/cmd/sst/refresh.go b/cmd/sst/refresh.go index 151437447b..e154134181 100644 --- a/cmd/sst/refresh.go +++ b/cmd/sst/refresh.go @@ -23,6 +23,11 @@ func CmdRefresh(c *cli.Cli) error { target = strings.Split(c.String("target"), ",") } + exclude := []string{} + if c.String("exclude") != "" { + exclude = strings.Split(c.String("exclude"), ",") + } + var wg errgroup.Group defer wg.Wait() ui := ui.New(c.Context) @@ -47,6 +52,7 @@ func CmdRefresh(c *cli.Cli) error { err = p.Run(c.Context, &project.StackInput{ Command: "refresh", Target: target, + Exclude: exclude, ServerPort: s.Port, Verbose: c.Bool("verbose"), }) diff --git a/pkg/project/run.go b/pkg/project/run.go index 7aa6074be4..ce35126965 100644 --- a/pkg/project/run.go +++ b/pkg/project/run.go @@ -337,6 +337,21 @@ func (p *Project) RunNext(ctx context.Context, input *StackInput) error { } } + if input.Exclude != nil { + for _, item := range input.Exclude { + index := slices.IndexFunc(completed.Resources, func(res apitype.ResourceV3) bool { + return res.URN.Name() == item + }) + if index == -1 { + return util.NewReadableError(nil, fmt.Sprintf("Exclude target not found: %v", item)) + } + args = append(args, "--exclude", string(completed.Resources[index].URN)) + } + if len(input.Exclude) > 0 { + args = append(args, "--exclude-dependents") + } + } + cmd := process.Command(pulumiPath, args...) process.Detach(cmd) cmd.Env = env diff --git a/pkg/project/stack.go b/pkg/project/stack.go index d9e5d47189..00f3c8ae02 100644 --- a/pkg/project/stack.go +++ b/pkg/project/stack.go @@ -16,6 +16,7 @@ type BuildFailedEvent struct { type StackInput struct { Command string Target []string + Exclude []string ServerPort int Dev bool Verbose bool