summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2023-11-24 09:48:25 +0100
committerMartin Polden <mpolden@mpolden.no>2023-11-24 09:48:25 +0100
commit3672125e74c660eaf12eb030de04b5dffd7374ff (patch)
treed982b0043ba82939024060891e00e72ed8d61626 /client
parent999368ffee9d84c324f419653961bc9abf2a4c18 (diff)
Print build number on submit
Diffstat (limited to 'client')
-rw-r--r--client/go/internal/cli/cmd/deploy_test.go2
-rw-r--r--client/go/internal/cli/cmd/prod.go6
-rw-r--r--client/go/internal/cli/cmd/prod_test.go12
-rw-r--r--client/go/internal/vespa/deploy.go41
-rw-r--r--client/go/internal/vespa/deploy_test.go13
5 files changed, 47 insertions, 27 deletions
diff --git a/client/go/internal/cli/cmd/deploy_test.go b/client/go/internal/cli/cmd/deploy_test.go
index c0652c30863..f34faa21de1 100644
--- a/client/go/internal/cli/cmd/deploy_test.go
+++ b/client/go/internal/cli/cmd/deploy_test.go
@@ -276,6 +276,6 @@ func assertDeployServerError(t *testing.T, status int, errorMessage string) {
cli.httpClient = client
assert.NotNil(t, cli.Run("deploy", "--wait=0", "testdata/applications/withTarget/target/application.zip"))
assert.Equal(t,
- "Error: error from deploy api at 127.0.0.1:19071 (Status "+strconv.Itoa(status)+"):\n"+errorMessage+"\n",
+ "Error: error from deploy API at 127.0.0.1:19071 (Status "+strconv.Itoa(status)+"):\n"+errorMessage+"\n",
stderr.String())
}
diff --git a/client/go/internal/cli/cmd/prod.go b/client/go/internal/cli/cmd/prod.go
index d90d89437f9..ddf2995126a 100644
--- a/client/go/internal/cli/cmd/prod.go
+++ b/client/go/internal/cli/cmd/prod.go
@@ -10,6 +10,7 @@ import (
"log"
"os"
"path/filepath"
+ "strconv"
"strings"
"github.com/fatih/color"
@@ -164,10 +165,11 @@ $ vespa prod deploy`,
AuthorEmail: options.authorEmail,
SourceURL: options.sourceURL,
}
- if err := vespa.Submit(deployment, submission); err != nil {
+ build, err := vespa.Submit(deployment, submission)
+ if err != nil {
return fmt.Errorf("could not deploy application: %w", err)
} else {
- cli.printSuccess("Deployed ", color.CyanString(pkg.Path))
+ cli.printSuccess(fmt.Sprintf("Deployed %s with build number %s", color.CyanString(pkg.Path), color.CyanString(strconv.FormatInt(build, 10))))
log.Printf("See %s for deployment progress\n", color.CyanString(fmt.Sprintf("%s/tenant/%s/application/%s/prod/deployment",
deployment.Target.Deployment().System.ConsoleURL, deployment.Target.Deployment().Application.Tenant, deployment.Target.Deployment().Application.Application)))
}
diff --git a/client/go/internal/cli/cmd/prod_test.go b/client/go/internal/cli/cmd/prod_test.go
index 5594c846cc8..7f2836125d8 100644
--- a/client/go/internal/cli/cmd/prod_test.go
+++ b/client/go/internal/cli/cmd/prod_test.go
@@ -167,7 +167,6 @@ func TestProdDeployWithoutTests(t *testing.T) {
func prodDeploy(pkgDir string, t *testing.T) {
t.Helper()
httpClient := &mock.HTTPClient{}
- httpClient.NextResponseString(200, `ok`)
cli, stdout, _ := newTestCLI(t, "CI=true")
cli.httpClient = httpClient
@@ -189,12 +188,14 @@ func prodDeploy(pkgDir string, t *testing.T) {
stdout.Reset()
cli.Environment["VESPA_CLI_API_KEY_FILE"] = filepath.Join(cli.config.homeDir, "t1.api-key.pem")
+ httpClient.NextResponseString(200, `{"build": 42}`)
assert.Nil(t, cli.Run("prod", "deploy", "--add-cert"))
- assert.Contains(t, stdout.String(), "Success: Deployed")
+ assert.Contains(t, stdout.String(), "Success: Deployed . with build number 42")
assert.Contains(t, stdout.String(), "See https://console.vespa-cloud.com/tenant/t1/application/a1/prod/deployment for deployment progress")
stdout.Reset()
+ httpClient.NextResponseString(200, `{"build": 43}`)
assert.Nil(t, cli.Run("prod", "submit", "--add-cert")) // old variant also works
- assert.Contains(t, stdout.String(), "Success: Deployed")
+ assert.Contains(t, stdout.String(), "Success: Deployed . with build number 43")
assert.Contains(t, stdout.String(), "See https://console.vespa-cloud.com/tenant/t1/application/a1/prod/deployment for deployment progress")
}
@@ -203,7 +204,7 @@ func TestProdDeployWithJava(t *testing.T) {
createApplication(t, pkgDir, true, false)
httpClient := &mock.HTTPClient{}
- httpClient.NextResponseString(200, `ok`)
+ httpClient.NextResponseString(200, `{"build": 42}`)
cli, stdout, stderr := newTestCLI(t, "CI=true")
cli.httpClient = httpClient
assert.Nil(t, cli.Run("config", "set", "application", "t1.a1.i1"))
@@ -215,7 +216,7 @@ func TestProdDeployWithJava(t *testing.T) {
cli.Environment["VESPA_CLI_API_KEY_FILE"] = filepath.Join(cli.config.homeDir, "t1.api-key.pem")
assert.Nil(t, cli.Run("prod", "deploy", "--add-cert", pkgDir))
assert.Equal(t, "", stderr.String())
- assert.Contains(t, stdout.String(), "Success: Deployed")
+ assert.Contains(t, stdout.String(), "Success: Deployed "+pkgDir+"/target/application with build number 42")
assert.Contains(t, stdout.String(), "See https://console.vespa-cloud.com/tenant/t1/application/a1/prod/deployment for deployment progress")
}
@@ -224,7 +225,6 @@ func TestProdDeployInvalidZip(t *testing.T) {
createApplication(t, pkgDir, true, false)
httpClient := &mock.HTTPClient{}
- httpClient.NextResponseString(200, `ok`)
cli, _, stderr := newTestCLI(t, "CI=true")
cli.httpClient = httpClient
assert.Nil(t, cli.Run("config", "set", "application", "t1.a1.i1"))
diff --git a/client/go/internal/vespa/deploy.go b/client/go/internal/vespa/deploy.go
index 7d90930d5f9..35fd523f15a 100644
--- a/client/go/internal/vespa/deploy.go
+++ b/client/go/internal/vespa/deploy.go
@@ -370,45 +370,45 @@ func copyToPart(dst *multipart.Writer, src io.Reader, fieldname, filename string
return nil
}
-func Submit(opts DeploymentOptions, submission Submission) error {
+func Submit(opts DeploymentOptions, submission Submission) (int64, error) {
if !opts.Target.IsCloud() {
- return fmt.Errorf("%s: deploy is unsupported by %s target", opts, opts.Target.Type())
+ return 0, fmt.Errorf("%s: deploy is unsupported by %s target", opts, opts.Target.Type())
}
if err := checkDeploymentOpts(opts); err != nil {
- return err
+ return 0, err
}
submitURL := opts.Target.Deployment().System.SubmitURL(opts.Target.Deployment())
u, err := url.Parse(submitURL)
if err != nil {
- return err
+ return 0, err
}
var body bytes.Buffer
writer := multipart.NewWriter(&body)
submitOptions, err := json.Marshal(submission)
if err != nil {
- return err
+ return 0, err
}
if err := copyToPart(writer, bytes.NewReader(submitOptions), "submitOptions", ""); err != nil {
- return err
+ return 0, err
}
applicationZip, err := opts.ApplicationPackage.zipReader(false)
if err != nil {
- return err
+ return 0, err
}
if err := copyToPart(writer, applicationZip, "applicationZip", "application.zip"); err != nil {
- return err
+ return 0, err
}
if opts.ApplicationPackage.HasTests() {
testApplicationZip, err := opts.ApplicationPackage.zipReader(true)
if err != nil {
- return err
+ return 0, err
}
if err := copyToPart(writer, testApplicationZip, "applicationTestZip", "application-test.zip"); err != nil {
- return err
+ return 0, err
}
}
if err := writer.Close(); err != nil {
- return err
+ return 0, err
}
request := &http.Request{
URL: u,
@@ -419,10 +419,23 @@ func Submit(opts DeploymentOptions, submission Submission) error {
request.Header.Set("Content-Type", writer.FormDataContentType())
response, err := deployServiceDo(request, time.Minute*10, opts)
if err != nil {
- return err
+ return 0, err
}
defer response.Body.Close()
- return checkResponse(request, response)
+ if err := checkResponse(request, response); err != nil {
+ return 0, err
+ }
+ responseBody, err := io.ReadAll(response.Body)
+ if err != nil {
+ return 0, err
+ }
+ var submitResponse struct {
+ Build int64 `json:"build"`
+ }
+ if err := json.Unmarshal(responseBody, &submitResponse); err != nil {
+ return 0, err
+ }
+ return submitResponse.Build, nil
}
func deployServiceDo(request *http.Request, timeout time.Duration, opts DeploymentOptions) (*http.Response, error) {
@@ -527,7 +540,7 @@ func checkResponse(req *http.Request, response *http.Response) error {
if response.StatusCode/100 == 4 {
return fmt.Errorf("invalid application package (%s)\n%s", response.Status, extractError(response.Body))
} else if response.StatusCode != 200 {
- return fmt.Errorf("error from deploy api at %s (%s):\n%s", req.URL.Host, response.Status, util.ReaderToJSON(response.Body))
+ return fmt.Errorf("error from deploy API at %s (%s):\n%s", req.URL.Host, response.Status, util.ReaderToJSON(response.Body))
}
return nil
}
diff --git a/client/go/internal/vespa/deploy_test.go b/client/go/internal/vespa/deploy_test.go
index 09129d3027a..516a21e7786 100644
--- a/client/go/internal/vespa/deploy_test.go
+++ b/client/go/internal/vespa/deploy_test.go
@@ -82,8 +82,10 @@ func TestSubmit(t *testing.T) {
Target: target,
ApplicationPackage: ApplicationPackage{Path: appDir},
}
- httpClient.NextResponseString(200, "ok")
- require.Nil(t, Submit(opts, Submission{}))
+ httpClient.NextResponseString(200, `{"build": 42}`)
+ build, err := Submit(opts, Submission{})
+ require.Nil(t, err)
+ require.Equal(t, int64(42), build)
require.Nil(t, httpClient.LastRequest.ParseMultipartForm(1<<20))
assert.Equal(t, "{}", httpClient.LastRequest.FormValue("submitOptions"))
f, err := httpClient.LastRequest.MultipartForm.File["applicationZip"][0].Open()
@@ -93,13 +95,16 @@ func TestSubmit(t *testing.T) {
f.Read(contents)
assert.Equal(t, "PK\x03\x04\x14", string(contents))
- require.Nil(t, Submit(opts, Submission{
+ httpClient.NextResponseString(200, `{"build": 43}`)
+ build, err = Submit(opts, Submission{
Risk: 1,
Commit: "sha",
Description: "broken garbage",
AuthorEmail: "foo@example.com",
SourceURL: "https://github.com/foo/repo",
- }))
+ })
+ require.Nil(t, err)
+ require.Equal(t, int64(43), build)
require.Nil(t, httpClient.LastRequest.ParseMultipartForm(1<<20))
assert.Equal(t, "https://api-ctl.vespa-cloud.com:4443/application/v4/tenant/t1/application/a1/submit", httpClient.LastRequest.URL.String())
assert.Equal(t,