Skip to content
This repository was archived by the owner on Jan 23, 2026. It is now read-only.
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: 25 additions & 3 deletions cmd/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,12 @@ type startAgent struct {
}

type startRequest struct {
Agents []startAgent `json:"agents"`
Resources *Resources `json:"resources,omitempty"`
Metadata *deployer.Metadata `json:"metadata,omitempty"`
Agents []startAgent `json:"agents"`
Resources *Resources `json:"resources,omitempty"`
Metadata *deployer.Metadata `json:"metadata,omitempty"`
Tags []string `json:"tags,omitempty"`
TagDescription string `json:"description,omitempty"`
TagMessage string `json:"message,omitempty"`
}

func ShowNewProjectImport(ctx context.Context, logger logger.Logger, cmd *cobra.Command, apiUrl, apikey, projectId string, project *project.Project, dir string, isImport bool) {
Expand Down Expand Up @@ -153,6 +156,18 @@ Examples:
ciMessage, _ := cmd.Flags().GetString("ci-message")
ciGitProvider, _ := cmd.Flags().GetString("ci-git-provider")
ciLogsUrl, _ := cmd.Flags().GetString("ci-logs-url")
tags, _ := cmd.Flags().GetStringArray("tag")
description, _ := cmd.Flags().GetString("description")
message, _ := cmd.Flags().GetString("message")

// remove duplicates and empty strings
tags = util.RemoveDuplicates(tags)
tags = util.RemoveEmpty(tags)

// If no tags are provided, default to ["latest"]
if len(tags) == 0 {
tags = []string{"latest"}
}

deploymentConfig := project.NewDeploymentConfig()
client := util.NewAPIClient(ctx, logger, apiUrl, token)
Expand Down Expand Up @@ -400,6 +415,10 @@ Examples:
},
}

startRequest.Tags = tags
startRequest.TagDescription = description
startRequest.TagMessage = message

// Start deployment
if err := client.Do("PUT", fmt.Sprintf("/cli/deploy/start/%s%s", theproject.ProjectId, deploymentId), startRequest, &startResponse); err != nil {
errsystem.New(errsystem.ErrDeployProject, err,
Expand Down Expand Up @@ -664,6 +683,9 @@ func init() {
cloudDeployCmd.Flags().String("ci-message", "", "Used to set the commit message for your deployment metadata")
cloudDeployCmd.Flags().String("ci-git-provider", "", "Used to set the git provider for your deployment metadata")
cloudDeployCmd.Flags().String("ci-logs-url", "", "Used to set the CI logs URL for your deployment metadata")
cloudDeployCmd.Flags().StringArray("tag", nil, "Tag(s) to associate with this deployment (can be specified multiple times)")
cloudDeployCmd.Flags().String("description", "", "Description for the deployment")
cloudDeployCmd.Flags().String("message", "", "A shorter description for the deployment")

cloudDeployCmd.Flags().MarkHidden("deploymentId")
cloudDeployCmd.Flags().MarkHidden("ci")
Expand Down
17 changes: 15 additions & 2 deletions internal/mcp/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ import (
)

type DeployArguments struct {
Directory string `json:"directory" jsonschema:"required,description=The directory where the project is located"`
Directory string `json:"directory" jsonschema:"required,description=The directory where the project is located"`
Tags []string `json:"tags,omitempty" jsonschema:"description=Tags to associate with this deployment"`
Description string `json:"description,omitempty" jsonschema:"description=Description for the deployment tag(s)"`
Message string `json:"message,omitempty" jsonschema:"description=Message for the deployment tag(s)"`
}

func init() {
Expand All @@ -22,7 +25,17 @@ func init() {
if resp := ensureProject(&c); resp != nil {
return resp, nil
}
result, err := execCommand(ctx, c.ProjectDir, "deploy", "--format", "json", "--dir", c.ProjectDir)
argsList := []string{"deploy", "--format", "json", "--dir", c.ProjectDir}
for _, tag := range args.Tags {
argsList = append(argsList, "--tag", tag)
}
if args.Description != "" {
argsList = append(argsList, "--description", args.Description)
}
if args.Message != "" {
argsList = append(argsList, "--message", args.Message)
}
result, err := execCommand(ctx, c.ProjectDir, argsList[0], argsList[1:]...)
if err != nil {
return nil, err
}
Expand Down
24 changes: 24 additions & 0 deletions internal/util/slice.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package util

func RemoveDuplicates[T comparable](slice []T) []T {
uniqueMap := make(map[T]bool)
uniqueSlice := []T{}
for _, item := range slice {
if !uniqueMap[item] {
uniqueMap[item] = true
uniqueSlice = append(uniqueSlice, item)
}
}
return uniqueSlice
}

func RemoveEmpty[T comparable](slice []T) []T {
var zero T
nonEmptySlice := []T{}
for _, item := range slice {
if item != zero {
nonEmptySlice = append(nonEmptySlice, item)
}
}
return nonEmptySlice
}
60 changes: 60 additions & 0 deletions internal/util/slice_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package util

import (
"reflect"
"testing"
)

func TestRemoveDuplicates_String(t *testing.T) {
input := []string{"a", "b", "a", "c", "b", "d"}
want := []string{"a", "b", "c", "d"}
got := RemoveDuplicates(input)
if !reflect.DeepEqual(got, want) {
t.Errorf("RemoveDuplicates(strings) = %v, want %v", got, want)
}
}

func TestRemoveDuplicates_Int(t *testing.T) {
input := []int{1, 2, 2, 3, 1, 4}
want := []int{1, 2, 3, 4}
got := RemoveDuplicates(input)
if !reflect.DeepEqual(got, want) {
t.Errorf("RemoveDuplicates(ints) = %v, want %v", got, want)
}
}

func TestRemoveEmpty_String(t *testing.T) {
input := []string{"a", "", "b", "", "c"}
want := []string{"a", "b", "c"}
got := RemoveEmpty(input)
if !reflect.DeepEqual(got, want) {
t.Errorf("RemoveEmpty(strings) = %v, want %v", got, want)
}
}

func TestRemoveEmpty_Int(t *testing.T) {
input := []int{0, 1, 2, 0, 3}
want := []int{1, 2, 3}
got := RemoveEmpty(input)
if !reflect.DeepEqual(got, want) {
t.Errorf("RemoveEmpty(ints) = %v, want %v", got, want)
}
}

func TestRemoveDuplicates_AlreadyUnique(t *testing.T) {
input := []string{"x", "y", "z"}
want := []string{"x", "y", "z"}
got := RemoveDuplicates(input)
if !reflect.DeepEqual(got, want) {
t.Errorf("RemoveDuplicates(already unique) = %v, want %v", got, want)
}
}

func TestRemoveEmpty_NoEmpty(t *testing.T) {
input := []int{1, 2, 3}
want := []int{1, 2, 3}
got := RemoveEmpty(input)
if !reflect.DeepEqual(got, want) {
t.Errorf("RemoveEmpty(no empty) = %v, want %v", got, want)
}
}
Loading