feat(deployment): Run commands on deployments via quick actions and exec#3
Conversation
Operators previously had no way to run a command such as a database migration or cache rebuild on a deployment from the CLI. Two commands are added: one lists the quick actions defined on a deployment, and one runs a chosen action inside its service container and prints the command output. Actions remain subject to the deployment's protected-mode rules. This lets continuous deployment pipelines run tasks like migrations as an explicit step after shipping a release.
Quick actions cover named, reusable commands, but there was no way to run a one-off command on a deployment without first defining it. Adds an exec command that runs an arbitrary command in a deployment's service container (selecting the service when there is more than one) and prints its output, plus an equivalent that targets a container by ID. Both run non-interactively and honor the deployment's protected-mode rules, so a pipeline can run something like a database migration as a single step.
A failed command previously surfaced only its exit status (for example "exit status 127"), hiding the container's own output and making failures hard to diagnose. The captured output is now printed alongside the error whenever an exec or quick action exits non-zero, so the underlying message (a missing binary, a migration error, a stack trace) is visible. The command still exits non-zero so pipelines continue to fail.
Running exec on a deployment with more than one service silently picked the first one, so a command meant for the app could land in an unrelated container (for example a database) and fail confusingly. Exec now resolves the service automatically only when a deployment has a single running service; with more than one it lists them and stops until a service is named. The service can be given positionally or with --service, and the command to run must follow `--` so it is never mistaken for a service or flag.
Code Review SummaryThis PR introduces the ability to run quick actions and ad-hoc commands within deployment containers via the CLI. It adds 🚀 Key Improvements
💡 Minor Suggestions
|
| return 2 | ||
| } | ||
|
|
||
| data, err := client.GetDeployment(context.Background(), name) |
There was a problem hiding this comment.
It is safer to use the context passed to the function rather than context.Background(), ensuring that cancellation signals (like SIGINT) are respected during the API call.
| data, err := client.GetDeployment(context.Background(), name) | |
| data, err := client.GetDeployment(ctx, name) |
| return execContainer(client, containerID, command, opts, stdout, stderr) | ||
| } | ||
|
|
||
| func execContainer(client *flatrun.Client, containerID string, command []string, opts globalOptions, stdout, stderr io.Writer) int { |
There was a problem hiding this comment.
Passing a context to the API request allows for proper timeout and cancellation management, which is critical for long-running 'exec' commands.
| func execContainer(client *flatrun.Client, containerID string, command []string, opts globalOptions, stdout, stderr io.Writer) int { | |
| func execContainer(ctx context.Context, client *flatrun.Client, containerID string, command []string, opts globalOptions, stdout, stderr io.Writer) int { | |
| data, err := client.ContainerExec(ctx, containerID, flatrun.ExecRequest{ |
The README command overview did not mention the new ways to run commands on a deployment, so add quick action and exec usage alongside the existing deployment commands.
| var parsed struct { | ||
| Output string `json:"output"` | ||
| } | ||
| if json.Unmarshal([]byte(apiErr.Body), &parsed) != nil { |
There was a problem hiding this comment.
If json.Unmarshal fails, the error is swallowed and an empty string is returned. While this prevents a crash, it might be helpful to log a debug message or handle the error if the API structure is expected to be stable.
| if json.Unmarshal([]byte(apiErr.Body), &parsed) != nil { | |
| if err := json.Unmarshal([]byte(apiErr.Body), &parsed); err != nil { | |
| return "" | |
| } |
Summary
Adds CLI support for running operator commands against a deployment, which previously had to be done outside the CLI. The agent already exposed the quick-action and container-exec endpoints; this surfaces them.
Commands
flatrun deployment actions NAME— list a deployment's quick actionsflatrun deployment action NAME ACTION_ID— run a quick action (named, reusable command) in its service containerflatrun deployment exec NAME [SERVICE] -- COMMAND [ARGS...]— run an ad-hoc command in a service containerflatrun container exec CONTAINER_ID -- COMMAND [ARGS...]— run an ad-hoc command in a container by IDBehavior
--; the service is chosen positionally or with--service.Notes
bin/rails db:migrate,npx prisma migrate deploy,php artisan migrate, …).docs/reference/commands.md) andCHANGELOG.mdupdated;VERSIONbumped to0.2.0.Testing
gofmt,go vet,go build, andgo test ./...all pass; new unit tests cover the client request shapes, service resolution (positional/flag/ambiguous),--handling, and output-on-failure.