From 11721a4ef317698ac2700b4619c2f89d73db4f5f Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Mon, 12 May 2025 12:08:35 +0200 Subject: [PATCH 1/6] [AGENT-129] Send new tag argument to backend on deployment --- cmd/agent.go | 5 +++++ cmd/cloud.go | 40 +++++++++++++++++++++++++++++++++------- 2 files changed, 38 insertions(+), 7 deletions(-) diff --git a/cmd/agent.go b/cmd/agent.go index 38e53395..2bf20458 100644 --- a/cmd/agent.go +++ b/cmd/agent.go @@ -170,6 +170,11 @@ func getAgentAuthType(logger logger.Logger, authType string) string { default: } } + + if !tui.HasTTY { + // error out with a message + logger.Fatal("No TTY detected, please specify an Agent authentication type from the command line") + } auth := tui.Select(logger, "Select your Agent's webhook authentication method", "Do you want to secure the webhook or make it publicly available?", []tui.Option{ {Text: tui.PadRight("API Key", 10, " ") + tui.Muted("Bearer Token (will be generated for you)"), ID: "bearer"}, {Text: tui.PadRight("None", 10, " ") + tui.Muted("No Authentication Required"), ID: "none"}, diff --git a/cmd/cloud.go b/cmd/cloud.go index 02df3077..677298b7 100644 --- a/cmd/cloud.go +++ b/cmd/cloud.go @@ -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"` + Tag string `json:"tag,omitempty"` + TagMessage string `json:"tagMessage,omitempty"` + TagDescription string `json:"tagDescription,omitempty"` } func ShowNewProjectImport(ctx context.Context, logger logger.Logger, cmd *cobra.Command, apiUrl, apikey, projectId string, project *project.Project, dir string, isImport bool) { @@ -95,9 +98,13 @@ func ShowNewProjectImport(ctx context.Context, logger logger.Logger, cmd *cobra. project.Name = name project.Description = description var createWebhookAuth bool - auth := getAgentAuthType(logger, "") - if auth == "bearer" { - createWebhookAuth = true + if project.Development != nil && !tui.HasTTY { + createWebhookAuth = false + } else { + auth := getAgentAuthType(logger, "") + if auth == "bearer" { + createWebhookAuth = true + } } tui.ClearScreen() tui.ShowSpinner("Importing project ...", func() { @@ -129,11 +136,14 @@ between local and remote agents. Flags: --dir The directory containing the project to deploy + --tag An optional tag for this deployment + --tag-message An optional message for the tag + --tag-description An optional description for the tag Examples: agentuity cloud deploy agentuity deploy - agentuity cloud deploy --dir /path/to/project`, + agentuity cloud deploy --dir /path/to/project --tag v1.2.3 --tag-message "Release 1.2.3" --tag-description "Stable release"`, Run: func(cmd *cobra.Command, args []string) { parentCtx := context.Background() ctx, cancel := signal.NotifyContext(parentCtx, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) @@ -153,6 +163,9 @@ Examples: ciMessage, _ := cmd.Flags().GetString("ci-message") ciGitProvider, _ := cmd.Flags().GetString("ci-git-provider") ciLogsUrl, _ := cmd.Flags().GetString("ci-logs-url") + tag, _ := cmd.Flags().GetString("tag") + tagMessage, _ := cmd.Flags().GetString("tag-message") + tagDescription, _ := cmd.Flags().GetString("tag-description") deploymentConfig := project.NewDeploymentConfig() client := util.NewAPIClient(ctx, logger, apiUrl, token) @@ -400,6 +413,16 @@ Examples: }, } + if tag != "" { + startRequest.Tag = tag + } + if tagMessage != "" { + startRequest.TagMessage = tagMessage + } + if tagDescription != "" { + startRequest.TagDescription = tagDescription + } + // 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, @@ -664,6 +687,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().String("tag", "", "An optional tag for this deployment") + cloudDeployCmd.Flags().String("tag-message", "", "An optional message for the tag") + cloudDeployCmd.Flags().String("tag-description", "", "An optional description for the tag") cloudDeployCmd.Flags().MarkHidden("deploymentId") cloudDeployCmd.Flags().MarkHidden("ci") From c98d80d7d5554d7c72eb40bfce2869c746bdabad Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Mon, 12 May 2025 19:04:55 +0200 Subject: [PATCH 2/6] Enter custom tag or use commig hash --- cmd/cloud.go | 50 +++++++++++++++++++++++++++++++++++++++++++++++--- cmd/project.go | 8 ++++++-- go.mod | 2 ++ go.sum | 4 ++++ 4 files changed, 59 insertions(+), 5 deletions(-) diff --git a/cmd/cloud.go b/cmd/cloud.go index 677298b7..47eae053 100644 --- a/cmd/cloud.go +++ b/cmd/cloud.go @@ -25,6 +25,7 @@ import ( "github.com/agentuity/go-common/logger" cstr "github.com/agentuity/go-common/string" "github.com/agentuity/go-common/tui" + "github.com/gosimple/slug" "github.com/spf13/cobra" "github.com/spf13/viper" "k8s.io/apimachinery/pkg/api/resource" @@ -163,9 +164,6 @@ Examples: ciMessage, _ := cmd.Flags().GetString("ci-message") ciGitProvider, _ := cmd.Flags().GetString("ci-git-provider") ciLogsUrl, _ := cmd.Flags().GetString("ci-logs-url") - tag, _ := cmd.Flags().GetString("tag") - tagMessage, _ := cmd.Flags().GetString("tag-message") - tagDescription, _ := cmd.Flags().GetString("tag-description") deploymentConfig := project.NewDeploymentConfig() client := util.NewAPIClient(ctx, logger, apiUrl, token) @@ -373,6 +371,52 @@ Examples: deploymentId = "/" + deploymentId } + // get a tag, ask the user for a tag if they didn't provide one or use the commit hash if we're in CI + tag, _ := cmd.Flags().GetString("tag") + if tag == "" { + if tui.HasTTY { + randomTag := util.RandStringBytes(8) + tag = tui.Select(logger, "Select a tag", "", []tui.Option{ + tui.Option{ + Text: "latest", + ID: "latest", + }, { + Text: randomTag, + ID: randomTag, + }, { + Text: "Enter manually", + ID: "__custom", + }}) + + if tag == "__custom" { + tag = tui.Input(logger, "Enter a custom tag", "") + if tag == "" { + errsystem.New(errsystem.ErrDeployProject, fmt.Errorf("tag cannot be empty"), + errsystem.WithContextMessage("Tag cannot be empty")).ShowErrorAndExit() + } + tag = slug.Make(tag) + } + } else { + if ciCommit != "" { + tag = ciCommit + } else { + tag = "latest" + } + } + } + + // get a tag message, ask the user for a tag message if they didn't provide one or use the commit message if we're in CI + tagMessage, _ := cmd.Flags().GetString("tag-message") + if tagMessage == "" { + if tui.HasTTY { + tagMessage = tui.Input(logger, "Enter a tag message", "") + } else { + tagMessage = ciMessage + } + } + + tagDescription, _ := cmd.Flags().GetString("tag-description") + var gitInfo deployer.GitInfo var originType string var ciInfo deployer.CIInfo diff --git a/cmd/project.go b/cmd/project.go index b1ccd135..eebfb834 100644 --- a/cmd/project.go +++ b/cmd/project.go @@ -643,7 +643,7 @@ Examples: fmt.Println(tui.Bold(orgNames[orgId]) + " " + tui.Muted("("+orgId+")")) fmt.Println() - headers := []string{tui.Title("Project Id"), tui.Title("Name"), tui.Title("Description")} + headers := []string{tui.Title("Project Id"), tui.Title("Name"), tui.Title("Description"), tui.Title("Tag"), tui.Title("Tag Message")} rows := [][]string{} for _, project := range orgProjects[orgId] { desc := project.Description @@ -654,12 +654,14 @@ Examples: tui.Muted(project.ID), tui.Bold(project.Name), tui.Text(tui.MaxWidth(desc, 30)), + tui.Muted(project.Tag), + tui.Muted(project.TagMessage), }) } tui.Table(headers, rows) } } else { - headers := []string{tui.Title("Project Id"), tui.Title("Name"), tui.Title("Description")} + headers := []string{tui.Title("Project Id"), tui.Title("Name"), tui.Title("Description"), tui.Title("Tag"), tui.Title("Tag Message")} rows := [][]string{} for _, project := range projects { desc := project.Description @@ -670,6 +672,8 @@ Examples: tui.Muted(project.ID), tui.Bold(project.Name), tui.Text(tui.MaxWidth(desc, 30)), + tui.Muted(project.Tag), + tui.Muted(project.TagMessage), }) } tui.Table(headers, rows) diff --git a/go.mod b/go.mod index 1176d9d6..8857efcd 100644 --- a/go.mod +++ b/go.mod @@ -17,6 +17,7 @@ require ( github.com/fsnotify/fsnotify v1.7.0 github.com/google/uuid v1.6.0 github.com/gorilla/websocket v1.5.3 + github.com/gosimple/slug v1.15.0 github.com/marcozac/go-jsonc v0.1.1 github.com/mattn/go-isatty v0.0.20 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c @@ -43,6 +44,7 @@ require ( github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.6.2 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect + github.com/gosimple/unidecode v1.0.1 // indirect github.com/invopop/jsonschema v0.13.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect diff --git a/go.sum b/go.sum index 3b050756..49e34861 100644 --- a/go.sum +++ b/go.sum @@ -129,6 +129,10 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gosimple/slug v1.15.0 h1:wRZHsRrRcs6b0XnxMUBM6WK1U1Vg5B0R7VkIf1Xzobo= +github.com/gosimple/slug v1.15.0/go.mod h1:UiRaFH+GEilHstLUmcBgWcI42viBN7mAb818JrYOeFQ= +github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6T/o= +github.com/gosimple/unidecode v1.0.1/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= From 3bf0d8bc04f89784a4ccbfc61dbf8943b0b01737 Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Mon, 12 May 2025 21:46:49 +0200 Subject: [PATCH 3/6] default tag to latest --- cmd/cloud.go | 54 +++++-------------------------------- go.mod | 2 -- go.sum | 4 --- internal/project/project.go | 2 ++ 4 files changed, 8 insertions(+), 54 deletions(-) diff --git a/cmd/cloud.go b/cmd/cloud.go index 47eae053..e7517f3f 100644 --- a/cmd/cloud.go +++ b/cmd/cloud.go @@ -25,7 +25,6 @@ import ( "github.com/agentuity/go-common/logger" cstr "github.com/agentuity/go-common/string" "github.com/agentuity/go-common/tui" - "github.com/gosimple/slug" "github.com/spf13/cobra" "github.com/spf13/viper" "k8s.io/apimachinery/pkg/api/resource" @@ -157,6 +156,11 @@ Examples: appUrl := context.APPURL transportUrl := context.TransportURL token := context.Token + + tag, _ := cmd.Flags().GetString("tag") + tagMessage, _ := cmd.Flags().GetString("tag-message") + tagDescription, _ := cmd.Flags().GetString("tag-description") + ci, _ := cmd.Flags().GetBool("ci") ciRemoteUrl, _ := cmd.Flags().GetString("ci-remote-url") ciBranch, _ := cmd.Flags().GetString("ci-branch") @@ -371,52 +375,6 @@ Examples: deploymentId = "/" + deploymentId } - // get a tag, ask the user for a tag if they didn't provide one or use the commit hash if we're in CI - tag, _ := cmd.Flags().GetString("tag") - if tag == "" { - if tui.HasTTY { - randomTag := util.RandStringBytes(8) - tag = tui.Select(logger, "Select a tag", "", []tui.Option{ - tui.Option{ - Text: "latest", - ID: "latest", - }, { - Text: randomTag, - ID: randomTag, - }, { - Text: "Enter manually", - ID: "__custom", - }}) - - if tag == "__custom" { - tag = tui.Input(logger, "Enter a custom tag", "") - if tag == "" { - errsystem.New(errsystem.ErrDeployProject, fmt.Errorf("tag cannot be empty"), - errsystem.WithContextMessage("Tag cannot be empty")).ShowErrorAndExit() - } - tag = slug.Make(tag) - } - } else { - if ciCommit != "" { - tag = ciCommit - } else { - tag = "latest" - } - } - } - - // get a tag message, ask the user for a tag message if they didn't provide one or use the commit message if we're in CI - tagMessage, _ := cmd.Flags().GetString("tag-message") - if tagMessage == "" { - if tui.HasTTY { - tagMessage = tui.Input(logger, "Enter a tag message", "") - } else { - tagMessage = ciMessage - } - } - - tagDescription, _ := cmd.Flags().GetString("tag-description") - var gitInfo deployer.GitInfo var originType string var ciInfo deployer.CIInfo @@ -731,7 +689,7 @@ 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().String("tag", "", "An optional tag for this deployment") + cloudDeployCmd.Flags().String("tag", "latest", "An tag for this deployment, defaults to 'latest'") cloudDeployCmd.Flags().String("tag-message", "", "An optional message for the tag") cloudDeployCmd.Flags().String("tag-description", "", "An optional description for the tag") diff --git a/go.mod b/go.mod index 8857efcd..1176d9d6 100644 --- a/go.mod +++ b/go.mod @@ -17,7 +17,6 @@ require ( github.com/fsnotify/fsnotify v1.7.0 github.com/google/uuid v1.6.0 github.com/gorilla/websocket v1.5.3 - github.com/gosimple/slug v1.15.0 github.com/marcozac/go-jsonc v0.1.1 github.com/mattn/go-isatty v0.0.20 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c @@ -44,7 +43,6 @@ require ( github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.6.2 // indirect github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/gosimple/unidecode v1.0.1 // indirect github.com/invopop/jsonschema v0.13.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect diff --git a/go.sum b/go.sum index 49e34861..3b050756 100644 --- a/go.sum +++ b/go.sum @@ -129,10 +129,6 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/gosimple/slug v1.15.0 h1:wRZHsRrRcs6b0XnxMUBM6WK1U1Vg5B0R7VkIf1Xzobo= -github.com/gosimple/slug v1.15.0/go.mod h1:UiRaFH+GEilHstLUmcBgWcI42viBN7mAb818JrYOeFQ= -github.com/gosimple/unidecode v1.0.1 h1:hZzFTMMqSswvf0LBJZCZgThIZrpDHFXux9KeGmn6T/o= -github.com/gosimple/unidecode v1.0.1/go.mod h1:CP0Cr1Y1kogOtx0bJblKzsVWrqYaqfNOnHzpgWw4Awc= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 h1:5ZPtiqj0JL5oKWmcsq4VMaAW5ukBEgSGXEN89zeH1Jo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3/go.mod h1:ndYquD05frm2vACXE1nsccT4oJzjhw2arTS2cpUD1PI= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= diff --git a/internal/project/project.go b/internal/project/project.go index 7fa67eff..0173a78b 100644 --- a/internal/project/project.go +++ b/internal/project/project.go @@ -283,6 +283,8 @@ type ProjectListData struct { Description string `json:"description"` OrgId string `json:"orgId"` OrgName string `json:"orgName"` + Tag string `json:"tag"` + TagMessage string `json:"tagMessage"` } func ListProjects(ctx context.Context, logger logger.Logger, baseUrl string, token string) ([]ProjectListData, error) { From 5614b3b7f8305ec59c74e7575c030b0d12916b58 Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Mon, 12 May 2025 21:49:46 +0200 Subject: [PATCH 4/6] Put some code back --- cmd/cloud.go | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/cmd/cloud.go b/cmd/cloud.go index e7517f3f..97cbe8df 100644 --- a/cmd/cloud.go +++ b/cmd/cloud.go @@ -98,13 +98,9 @@ func ShowNewProjectImport(ctx context.Context, logger logger.Logger, cmd *cobra. project.Name = name project.Description = description var createWebhookAuth bool - if project.Development != nil && !tui.HasTTY { - createWebhookAuth = false - } else { - auth := getAgentAuthType(logger, "") - if auth == "bearer" { - createWebhookAuth = true - } + auth := getAgentAuthType(logger, "") + if auth == "bearer" { + createWebhookAuth = true } tui.ClearScreen() tui.ShowSpinner("Importing project ...", func() { From 5a44e26cd5ad2267d09eebf4370e904d1be0f677 Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Mon, 12 May 2025 21:51:13 +0200 Subject: [PATCH 5/6] Better sample message --- cmd/cloud.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/cloud.go b/cmd/cloud.go index 97cbe8df..623a357f 100644 --- a/cmd/cloud.go +++ b/cmd/cloud.go @@ -139,7 +139,7 @@ Flags: Examples: agentuity cloud deploy agentuity deploy - agentuity cloud deploy --dir /path/to/project --tag v1.2.3 --tag-message "Release 1.2.3" --tag-description "Stable release"`, + agentuity cloud deploy --dir /path/to/project --tag latest --tag-message "Latest Release" --tag-description "Some longer description"`, Run: func(cmd *cobra.Command, args []string) { parentCtx := context.Background() ctx, cancel := signal.NotifyContext(parentCtx, os.Interrupt, syscall.SIGINT, syscall.SIGTERM) From 2fa2612377225ca72f00615f51d6d5686042ac48 Mon Sep 17 00:00:00 2001 From: Pedro Enrique Date: Tue, 13 May 2025 21:46:33 +0200 Subject: [PATCH 6/6] remove unused code --- cmd/agent.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/cmd/agent.go b/cmd/agent.go index 2bf20458..9729cc2a 100644 --- a/cmd/agent.go +++ b/cmd/agent.go @@ -171,10 +171,6 @@ func getAgentAuthType(logger logger.Logger, authType string) string { } } - if !tui.HasTTY { - // error out with a message - logger.Fatal("No TTY detected, please specify an Agent authentication type from the command line") - } auth := tui.Select(logger, "Select your Agent's webhook authentication method", "Do you want to secure the webhook or make it publicly available?", []tui.Option{ {Text: tui.PadRight("API Key", 10, " ") + tui.Muted("Bearer Token (will be generated for you)"), ID: "bearer"}, {Text: tui.PadRight("None", 10, " ") + tui.Muted("No Authentication Required"), ID: "none"},