diff options
author | Martin Polden <mpolden@mpolden.no> | 2023-07-13 11:31:38 +0200 |
---|---|---|
committer | Martin Polden <mpolden@mpolden.no> | 2023-07-13 11:35:10 +0200 |
commit | fade5f5f6b764de037243c1182f82e6a4486a16a (patch) | |
tree | b58f23b934a0d477c7e7c54382b92dbe0e1d4bb0 /client | |
parent | cd357bf9f6718bf279fa4503b973363842f994b1 (diff) |
Add submission options to prod deploy
Diffstat (limited to 'client')
-rw-r--r-- | client/go/internal/cli/cmd/prod.go | 37 | ||||
-rw-r--r-- | client/go/internal/vespa/deploy.go | 16 | ||||
-rw-r--r-- | client/go/internal/vespa/deploy_test.go | 35 |
3 files changed, 79 insertions, 9 deletions
diff --git a/client/go/internal/cli/cmd/prod.go b/client/go/internal/cli/cmd/prod.go index 14fbae68b17..3b37197340f 100644 --- a/client/go/internal/cli/cmd/prod.go +++ b/client/go/internal/cli/cmd/prod.go @@ -102,8 +102,17 @@ https://cloud.vespa.ai/en/reference/deployment`, } } +type prodDeployOptions struct { + copyCert bool + risk int + commit string + description string + authorEmail string + sourceURL string +} + func newProdDeployCmd(cli *CLI) *cobra.Command { - copyCert := false + var options prodDeployOptions cmd := &cobra.Command{ Use: "deploy", Aliases: []string{"submit"}, // TODO: Remove in Vespa 9 @@ -118,7 +127,9 @@ services.xml. For more information about production deployments in Vespa Cloud see: https://cloud.vespa.ai/en/production-deployment -https://cloud.vespa.ai/en/automated-deployments`, +https://cloud.vespa.ai/en/automated-deployments +https://cloud.vespa.ai/en/reference/vespa-cloud-api#submission-properties +`, DisableAutoGenTag: true, SilenceUsage: true, Example: `$ mvn package # when adding custom Java components @@ -142,21 +153,33 @@ $ vespa prod deploy`, if err := verifyTests(cli, pkg); err != nil { return err } - opts := vespa.DeploymentOptions{ApplicationPackage: pkg, Target: target} - if err := maybeCopyCertificate(copyCert, true, cli, target, pkg); err != nil { + if err := maybeCopyCertificate(options.copyCert, true, cli, target, pkg); err != nil { return err } - if err := vespa.Submit(opts); err != nil { + deployment := vespa.DeploymentOptions{ApplicationPackage: pkg, Target: target} + submission := vespa.Submission{ + Risk: options.risk, + Commit: options.commit, + Description: options.description, + AuthorEmail: options.authorEmail, + SourceURL: options.sourceURL, + } + if err := vespa.Submit(deployment, submission); err != nil { return fmt.Errorf("could not deploy application: %w", err) } else { cli.printSuccess("Deployed ", color.CyanString(pkg.Path)) log.Printf("See %s for deployment progress\n", color.CyanString(fmt.Sprintf("%s/tenant/%s/application/%s/prod/deployment", - opts.Target.Deployment().System.ConsoleURL, opts.Target.Deployment().Application.Tenant, opts.Target.Deployment().Application.Application))) + deployment.Target.Deployment().System.ConsoleURL, deployment.Target.Deployment().Application.Tenant, deployment.Target.Deployment().Application.Application))) } return nil }, } - cmd.Flags().BoolVarP(©Cert, "add-cert", "A", false, `Copy certificate of the configured application to the current application package`) + cmd.Flags().BoolVarP(&options.copyCert, "add-cert", "A", false, "Copy certificate of the configured application to the current application package (default false)") + cmd.Flags().IntVarP(&options.risk, "risk", "", 0, "The risk score of source code being deployed. 0 to ignore (default 0)") + cmd.Flags().StringVarP(&options.commit, "commit", "", "", "Identifier of the source code being deployed. For example a commit hash") + cmd.Flags().StringVarP(&options.description, "description", "", "", "Description of the source code being deployed. For example a git commit message") + cmd.Flags().StringVarP(&options.authorEmail, "author-email", "", "", "Email of the author of the commit being deployed") + cmd.Flags().StringVarP(&options.sourceURL, "source-url", "", "", "URL which points to the source code being deployed. For example the build job running the submission") return cmd } diff --git a/client/go/internal/vespa/deploy.go b/client/go/internal/vespa/deploy.go index d04b8ba631c..ae4d4678d66 100644 --- a/client/go/internal/vespa/deploy.go +++ b/client/go/internal/vespa/deploy.go @@ -51,6 +51,14 @@ type DeploymentOptions struct { Version version.Version } +type Submission struct { + Risk int `json:"risk,omitempty"` + Commit string `json:"commit,omitempty"` + Description string `json:"description,omitempty"` + AuthorEmail string `json:"authorEmail,omitempty"` + SourceURL string `json:"sourceUrl,omitempty"` +} + type LogLinePrepareResponse struct { Time int64 Level string @@ -247,7 +255,7 @@ func copyToPart(dst *multipart.Writer, src io.Reader, fieldname, filename string return nil } -func Submit(opts DeploymentOptions) error { +func Submit(opts DeploymentOptions, submission Submission) error { if !opts.Target.IsCloud() { return fmt.Errorf("%s: deploy is unsupported by %s target", opts, opts.Target.Type()) } @@ -261,7 +269,11 @@ func Submit(opts DeploymentOptions) error { } var body bytes.Buffer writer := multipart.NewWriter(&body) - if err := copyToPart(writer, strings.NewReader("{}"), "submitOptions", ""); err != nil { + submitOptions, err := json.Marshal(submission) + if err != nil { + return err + } + if err := copyToPart(writer, bytes.NewReader(submitOptions), "submitOptions", ""); err != nil { return err } applicationZip, err := opts.ApplicationPackage.zipReader(false) diff --git a/client/go/internal/vespa/deploy_test.go b/client/go/internal/vespa/deploy_test.go index ddb500d26e3..39a9f2bcdf2 100644 --- a/client/go/internal/vespa/deploy_test.go +++ b/client/go/internal/vespa/deploy_test.go @@ -69,6 +69,41 @@ func TestDeployCloud(t *testing.T) { assert.Equal(t, string(values["deployOptions"]), `{"vespaVersion":"1.2.3"}`) } +func TestSubmit(t *testing.T) { + httpClient := mock.HTTPClient{} + target := createCloudTarget(t, "http://vespacloud", io.Discard) + cloudTarget, ok := target.(*cloudTarget) + require.True(t, ok) + cloudTarget.httpClient = &httpClient + appDir, _ := mock.ApplicationPackageDir(t, false, true) + opts := DeploymentOptions{ + Target: target, + ApplicationPackage: ApplicationPackage{Path: appDir}, + } + httpClient.NextResponseString(200, "ok") + require.Nil(t, Submit(opts, Submission{})) + require.Nil(t, httpClient.LastRequest.ParseMultipartForm(1<<20)) + assert.Equal(t, "{}", httpClient.LastRequest.FormValue("submitOptions")) + f, err := httpClient.LastRequest.MultipartForm.File["applicationZip"][0].Open() + require.Nil(t, err) + defer f.Close() + contents := make([]byte, 5) + f.Read(contents) + assert.Equal(t, "PK\x03\x04\x14", string(contents)) + + require.Nil(t, Submit(opts, Submission{ + Risk: 1, + Commit: "sha", + Description: "broken garbage", + AuthorEmail: "foo@example.com", + SourceURL: "https://github.com/foo/repo", + })) + require.Nil(t, httpClient.LastRequest.ParseMultipartForm(1<<20)) + assert.Equal(t, + "{\"risk\":1,\"commit\":\"sha\",\"description\":\"broken garbage\",\"authorEmail\":\"foo@example.com\",\"sourceUrl\":\"https://github.com/foo/repo\"}", + httpClient.LastRequest.FormValue("submitOptions")) +} + func TestApplicationFromString(t *testing.T) { app, err := ApplicationFromString("t1.a1.i1") assert.Nil(t, err) |