mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: add support for template version messages in api and cli (#8336)
This commit is contained in:
@@ -92,6 +92,8 @@ func (r *RootCmd) templateCreate() *clibase.Cmd {
|
||||
return xerrors.Errorf("check for lockfile: %w", err)
|
||||
}
|
||||
|
||||
message := uploadFlags.templateMessage(inv)
|
||||
|
||||
// Confirm upload of the directory.
|
||||
resp, err := uploadFlags.upload(inv, client)
|
||||
if err != nil {
|
||||
@@ -104,6 +106,7 @@ func (r *RootCmd) templateCreate() *clibase.Cmd {
|
||||
}
|
||||
|
||||
job, err := createValidTemplateVersion(inv, createValidTemplateVersionArgs{
|
||||
Message: message,
|
||||
Client: client,
|
||||
Organization: organization,
|
||||
Provisioner: database.ProvisionerType(provisioner),
|
||||
@@ -205,6 +208,7 @@ func (r *RootCmd) templateCreate() *clibase.Cmd {
|
||||
|
||||
type createValidTemplateVersionArgs struct {
|
||||
Name string
|
||||
Message string
|
||||
Client *codersdk.Client
|
||||
Organization codersdk.Organization
|
||||
Provisioner database.ProvisionerType
|
||||
@@ -238,6 +242,7 @@ func createValidTemplateVersion(inv *clibase.Invocation, args createValidTemplat
|
||||
|
||||
req := codersdk.CreateTemplateVersionRequest{
|
||||
Name: args.Name,
|
||||
Message: args.Message,
|
||||
StorageMethod: codersdk.ProvisionerStorageMethodFile,
|
||||
FileID: args.FileID,
|
||||
Provisioner: codersdk.ProvisionerType(args.Provisioner),
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/briandowns/spinner"
|
||||
@@ -21,6 +22,7 @@ import (
|
||||
type templateUploadFlags struct {
|
||||
directory string
|
||||
ignoreLockfile bool
|
||||
message string
|
||||
}
|
||||
|
||||
func (pf *templateUploadFlags) options() []clibase.Option {
|
||||
@@ -35,6 +37,11 @@ func (pf *templateUploadFlags) options() []clibase.Option {
|
||||
Description: "Ignore warnings about not having a .terraform.lock.hcl file present in the template.",
|
||||
Default: "false",
|
||||
Value: clibase.BoolOf(&pf.ignoreLockfile),
|
||||
}, {
|
||||
Flag: "message",
|
||||
FlagShorthand: "m",
|
||||
Description: "Specify a message describing the changes in this version of the template. Messages longer than 72 characters will be displayed as truncated.",
|
||||
Value: clibase.StringOf(&pf.message),
|
||||
}}
|
||||
}
|
||||
|
||||
@@ -110,6 +117,20 @@ func (pf *templateUploadFlags) checkForLockfile(inv *clibase.Invocation) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pf *templateUploadFlags) templateMessage(inv *clibase.Invocation) string {
|
||||
title := strings.SplitN(pf.message, "\n", 2)[0]
|
||||
if len(title) > 72 {
|
||||
cliui.Warn(inv.Stdout, "Template message is longer than 72 characters, it will be displayed as truncated.")
|
||||
}
|
||||
if title != pf.message {
|
||||
cliui.Warn(inv.Stdout, "Template message contains newlines, only the first line will be displayed.")
|
||||
}
|
||||
if pf.message != "" {
|
||||
return pf.message
|
||||
}
|
||||
return "Uploaded from the CLI"
|
||||
}
|
||||
|
||||
func (pf *templateUploadFlags) templateName(args []string) (string, error) {
|
||||
if pf.stdin() {
|
||||
// Can't infer name from directory if none provided.
|
||||
@@ -174,6 +195,8 @@ func (r *RootCmd) templatePush() *clibase.Cmd {
|
||||
return xerrors.Errorf("check for lockfile: %w", err)
|
||||
}
|
||||
|
||||
message := uploadFlags.templateMessage(inv)
|
||||
|
||||
resp, err := uploadFlags.upload(inv, client)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -186,6 +209,7 @@ func (r *RootCmd) templatePush() *clibase.Cmd {
|
||||
|
||||
job, err := createValidTemplateVersion(inv, createValidTemplateVersionArgs{
|
||||
Name: versionName,
|
||||
Message: message,
|
||||
Client: client,
|
||||
Organization: organization,
|
||||
Provisioner: database.ProvisionerType(provisioner),
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -70,6 +71,90 @@ func TestTemplatePush(t *testing.T) {
|
||||
require.Equal(t, "example", templateVersions[1].Name)
|
||||
})
|
||||
|
||||
t.Run("Message less than or equal to 72 chars", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
_ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
source := clitest.CreateTemplateVersionSource(t, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
ProvisionApply: echo.ProvisionComplete,
|
||||
})
|
||||
|
||||
wantMessage := strings.Repeat("a", 72)
|
||||
|
||||
inv, root := clitest.New(t, "templates", "push", template.Name, "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho), "--name", "example", "--message", wantMessage, "--yes")
|
||||
clitest.SetupConfig(t, client, root)
|
||||
pty := ptytest.New(t).Attach(inv)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitMedium)
|
||||
defer cancel()
|
||||
|
||||
inv = inv.WithContext(ctx)
|
||||
w := clitest.StartWithWaiter(t, inv)
|
||||
|
||||
pty.ExpectNoMatchBefore(ctx, "Template message is longer than 72 characters", "Updated version at")
|
||||
|
||||
w.RequireSuccess()
|
||||
|
||||
// Assert that the template version changed.
|
||||
templateVersions, err := client.TemplateVersionsByTemplate(ctx, codersdk.TemplateVersionsByTemplateRequest{
|
||||
TemplateID: template.ID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, templateVersions, 2)
|
||||
assert.NotEqual(t, template.ActiveVersionID, templateVersions[1].ID)
|
||||
require.Equal(t, wantMessage, templateVersions[1].Message)
|
||||
})
|
||||
|
||||
t.Run("Message too long, warn but continue", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
||||
user := coderdtest.CreateFirstUser(t, client)
|
||||
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
|
||||
_ = coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
|
||||
|
||||
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
|
||||
source := clitest.CreateTemplateVersionSource(t, &echo.Responses{
|
||||
Parse: echo.ParseComplete,
|
||||
ProvisionApply: echo.ProvisionComplete,
|
||||
})
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
|
||||
defer cancel()
|
||||
|
||||
for i, tt := range []struct {
|
||||
wantMessage string
|
||||
wantMatch string
|
||||
}{
|
||||
{wantMessage: strings.Repeat("a", 73), wantMatch: "Template message is longer than 72 characters"},
|
||||
{wantMessage: "This is my title\n\nAnd this is my body.", wantMatch: "Template message contains newlines"},
|
||||
} {
|
||||
inv, root := clitest.New(t, "templates", "push", template.Name, "--directory", source, "--test.provisioner", string(database.ProvisionerTypeEcho), "--message", tt.wantMessage, "--yes")
|
||||
clitest.SetupConfig(t, client, root)
|
||||
pty := ptytest.New(t).Attach(inv)
|
||||
|
||||
inv = inv.WithContext(ctx)
|
||||
w := clitest.StartWithWaiter(t, inv)
|
||||
|
||||
pty.ExpectMatchContext(ctx, tt.wantMatch)
|
||||
|
||||
w.RequireSuccess()
|
||||
|
||||
// Assert that the template version changed.
|
||||
templateVersions, err := client.TemplateVersionsByTemplate(ctx, codersdk.TemplateVersionsByTemplateRequest{
|
||||
TemplateID: template.ID,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, templateVersions, 2+i)
|
||||
assert.NotEqual(t, template.ActiveVersionID, templateVersions[1+i].ID)
|
||||
require.Equal(t, tt.wantMessage, templateVersions[1+i].Message)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("NoLockfile", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
|
||||
|
||||
@@ -21,6 +21,11 @@ Create a template from the current directory or as specified by flag
|
||||
Specify an inactivity TTL for workspaces created from this template.
|
||||
This licensed feature's default is 0h (off).
|
||||
|
||||
-m, --message string
|
||||
Specify a message describing the changes in this version of the
|
||||
template. Messages longer than 72 characters will be displayed as
|
||||
truncated.
|
||||
|
||||
--private bool
|
||||
Disable the default behavior of granting template access to the
|
||||
'everyone' group. The template permissions must be updated to allow
|
||||
|
||||
@@ -17,6 +17,11 @@ Push a new template version from the current directory or as specified by flag
|
||||
Ignore warnings about not having a .terraform.lock.hcl file present in
|
||||
the template.
|
||||
|
||||
-m, --message string
|
||||
Specify a message describing the changes in this version of the
|
||||
template. Messages longer than 72 characters will be displayed as
|
||||
truncated.
|
||||
|
||||
--name string
|
||||
Specify a name for the new template version. It will be automatically
|
||||
generated if not provided.
|
||||
|
||||
Reference in New Issue
Block a user