Skip to content
Open
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
43 changes: 34 additions & 9 deletions internal/cmd/service/deploy/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,31 @@ func NewCmdDeploy(f *cmdutil.Factory) *cobra.Command {
}

func runDeploy(f *cmdutil.Factory, opts *Options) error {
// Infer template from flags when not explicitly set
inferTemplate(opts)

if f.Interactive {
return runDeployInteractive(f, opts)
} else {
return runDeployNonInteractive(f, opts)
}
}

// inferTemplate automatically sets the template based on other provided flags.
// If --marketplace-code is provided, the user clearly wants a PREBUILT deployment.
// If --repo-id is provided, the user clearly wants a GIT deployment.
func inferTemplate(opts *Options) {
if opts.template != "" {
return
}

if opts.marketplaceCode != "" {
opts.template = "PREBUILT"
} else if opts.repoID != 0 {
opts.template = "GIT"
Comment on lines +64 to +67
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

--repo-id inference still conflicts with interactive flag precedence.

When this infers GIT from --repo-id, the interactive GIT flow still prompts repository selection and can overwrite the provided repo. That makes the flag non-authoritative in interactive mode.

As per coding guidelines: "Commands should support both interactive and non-interactive modes; if a flag is provided, skip the interactive prompt."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cmd/service/deploy/deploy.go` around lines 64 - 67, The current
inference sets opts.template = "GIT" when opts.repoID != 0 but the interactive
GIT prompt can still run and overwrite opts.repoID/template; update the deploy
flow to treat presence of --repo-id as authoritative by (a) setting
opts.template and a flag like opts.skipInteractive or opts.interactive=false
when opts.repoID != 0 (or moving the repo-id check before any interactive
logic), and (b) guarding the interactive repository selection routine to return
early if opts.repoID != 0 (or opts.skipInteractive is true) so the prompt cannot
overwrite opts.repoID or opts.template; locate and modify the code around
opts.template, opts.repoID, and the interactive GIT prompt function in deploy.go
to implement this change.

}
}

func runDeployNonInteractive(f *cmdutil.Factory, opts *Options) error {
if opts.projectID == "" {
return fmt.Errorf("--project-id is required")
Expand Down Expand Up @@ -231,23 +249,30 @@ func runDeployInteractive(f *cmdutil.Factory, opts *Options) error {

func paramCheck(opts *Options) error {
if opts.template == "" {
return fmt.Errorf("please specify service template with --template")
return fmt.Errorf("please specify service template with --template (PREBUILT or GIT)\n" +
" Example: zeabur service deploy --template PREBUILT --marketplace-code postgresql --project-id <id>\n" +
" Example: zeabur service deploy --template GIT --repo-id <id> --branch-name main --project-id <id>")
}

if strings.ToUpper(opts.template) != "PREBUILT" && strings.ToUpper(opts.template) != "GIT" {
return fmt.Errorf("unsupported service template %s, only support PREBUILT and GIT", opts.template)
template := strings.ToUpper(opts.template)

if template != "PREBUILT" && template != "GIT" {
return fmt.Errorf("unsupported service template %q, only PREBUILT and GIT are supported", opts.template)
}

if opts.template == "PREBUILT" && opts.marketplaceCode == "" {
return fmt.Errorf("please specify marketplace item code with --marketplace-code")
if template == "PREBUILT" && opts.marketplaceCode == "" {
return fmt.Errorf("--marketplace-code is required for PREBUILT template\n" +
" Example: zeabur service deploy --template PREBUILT --marketplace-code postgresql --project-id <id>")
}
Comment on lines +263 to 266
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Unknown --marketplace-code is still not pre-validated with available-code hints.

This only checks presence, not validity. For invalid codes, users still depend on backend failure paths instead of getting the expected list of valid marketplace codes in CLI output.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/cmd/service/deploy/deploy.go` around lines 263 - 266, The current
check only ensures opts.marketplaceCode is present for template == "PREBUILT"
but does not validate that the value is one of the available marketplace codes;
update the validation in the same branch (where template and
opts.marketplaceCode are checked) to call the marketplace listing API/client to
fetch the set of valid codes (e.g., use the existing marketplace/catalog client
method in this package), compare opts.marketplaceCode against that set, and if
it is not found return a user-friendly error that includes the list of valid
codes and the example usage (instead of deferring to backend errors). Ensure the
lookup is case/whitespace-normalized and perform this validation early in the
deploy flow before attempting to create or send the request.


if opts.template == "GIT" && opts.repoID == 0 {
return fmt.Errorf("please specify git repository ID with --repo-id")
if template == "GIT" && opts.repoID == 0 {
return fmt.Errorf("--repo-id is required for GIT template\n" +
" Example: zeabur service deploy --template GIT --repo-id <id> --branch-name main --project-id <id>")
}

if opts.template == "GIT" && opts.branchName == "" {
return fmt.Errorf("please specify git branch name with --branch-name")
if template == "GIT" && opts.branchName == "" {
return fmt.Errorf("--branch-name is required for GIT template\n" +
" Example: zeabur service deploy --template GIT --repo-id <id> --branch-name main --project-id <id>")
}

return nil
Expand Down