Skip to content

Commit 3727e02

Browse files
authored
feat(cli): add --create flag to templates push (coder#8454)
1 parent 5432c3f commit 3727e02

File tree

4 files changed

+95
-8
lines changed

4 files changed

+95
-8
lines changed

cli/templatepush.go

+36-8
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,7 @@ func (r *RootCmd) templatePush() *clibase.Cmd {
163163
provisionerTags []string
164164
uploadFlags templateUploadFlags
165165
activate bool
166+
create bool
166167
)
167168
client := new(codersdk.Client)
168169
cmd := &clibase.Cmd{
@@ -185,9 +186,13 @@ func (r *RootCmd) templatePush() *clibase.Cmd {
185186
return err
186187
}
187188

189+
var createTemplate bool
188190
template, err := client.TemplateByName(inv.Context(), organization.ID, name)
189191
if err != nil {
190-
return err
192+
if !create {
193+
return err
194+
}
195+
createTemplate = true
191196
}
192197

193198
err = uploadFlags.checkForLockfile(inv)
@@ -207,19 +212,24 @@ func (r *RootCmd) templatePush() *clibase.Cmd {
207212
return err
208213
}
209214

210-
job, err := createValidTemplateVersion(inv, createValidTemplateVersionArgs{
211-
Name: versionName,
215+
args := createValidTemplateVersionArgs{
212216
Message: message,
213217
Client: client,
214218
Organization: organization,
215219
Provisioner: database.ProvisionerType(provisioner),
216220
FileID: resp.ID,
221+
ProvisionerTags: tags,
217222
VariablesFile: variablesFile,
218223
Variables: variables,
219-
Template: &template,
220-
ReuseParameters: !alwaysPrompt,
221-
ProvisionerTags: tags,
222-
})
224+
}
225+
226+
if !createTemplate {
227+
args.Name = versionName
228+
args.Template = &template
229+
args.ReuseParameters = !alwaysPrompt
230+
}
231+
232+
job, err := createValidTemplateVersion(inv, args)
223233
if err != nil {
224234
return err
225235
}
@@ -228,7 +238,19 @@ func (r *RootCmd) templatePush() *clibase.Cmd {
228238
return xerrors.Errorf("job failed: %s", job.Job.Status)
229239
}
230240

231-
if activate {
241+
if createTemplate {
242+
_, err = client.CreateTemplate(inv.Context(), organization.ID, codersdk.CreateTemplateRequest{
243+
Name: name,
244+
VersionID: job.ID,
245+
})
246+
if err != nil {
247+
return err
248+
}
249+
250+
_, _ = fmt.Fprintln(inv.Stdout, "\n"+cliui.DefaultStyles.Wrap.Render(
251+
"The "+cliui.DefaultStyles.Keyword.Render(name)+" template has been created at "+cliui.DefaultStyles.DateTimeStamp.Render(time.Now().Format(time.Stamp))+"! "+
252+
"Developers can provision a workspace with this template using:")+"\n")
253+
} else if activate {
232254
err = client.UpdateActiveTemplateVersion(inv.Context(), template.ID, codersdk.UpdateActiveTemplateVersion{
233255
ID: job.ID,
234256
})
@@ -290,6 +312,12 @@ func (r *RootCmd) templatePush() *clibase.Cmd {
290312
Default: "true",
291313
Value: clibase.BoolOf(&activate),
292314
},
315+
{
316+
Flag: "create",
317+
Description: "Create the template if it does not exist.",
318+
Default: "false",
319+
Value: clibase.BoolOf(&create),
320+
},
293321
cliui.SkipPromptOption(),
294322
}
295323
cmd.Options = append(cmd.Options, uploadFlags.options()...)

cli/templatepush_test.go

+47
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"strings"
1010
"testing"
1111

12+
"github.com/google/uuid"
1213
"github.com/stretchr/testify/assert"
1314
"github.com/stretchr/testify/require"
1415

@@ -613,6 +614,52 @@ func TestTemplatePush(t *testing.T) {
613614
require.Equal(t, "second_variable", templateVariables[1].Name)
614615
require.Equal(t, "foobar", templateVariables[1].Value)
615616
})
617+
618+
t.Run("CreateTemplate", func(t *testing.T) {
619+
t.Parallel()
620+
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
621+
user := coderdtest.CreateFirstUser(t, client)
622+
source := clitest.CreateTemplateVersionSource(t, &echo.Responses{
623+
Parse: echo.ParseComplete,
624+
ProvisionApply: provisionCompleteWithAgent,
625+
})
626+
627+
const templateName = "my-template"
628+
args := []string{
629+
"templates",
630+
"push",
631+
templateName,
632+
"--directory", source,
633+
"--test.provisioner", string(database.ProvisionerTypeEcho),
634+
"--create",
635+
}
636+
inv, root := clitest.New(t, args...)
637+
clitest.SetupConfig(t, client, root)
638+
pty := ptytest.New(t).Attach(inv)
639+
640+
waiter := clitest.StartWithWaiter(t, inv)
641+
642+
matches := []struct {
643+
match string
644+
write string
645+
}{
646+
{match: "Upload", write: "yes"},
647+
{match: "template has been created"},
648+
}
649+
for _, m := range matches {
650+
pty.ExpectMatch(m.match)
651+
if m.write != "" {
652+
pty.WriteLine(m.write)
653+
}
654+
}
655+
656+
waiter.RequireSuccess()
657+
658+
template, err := client.TemplateByName(context.Background(), user.OrganizationID, templateName)
659+
require.NoError(t, err)
660+
require.Equal(t, templateName, template.Name)
661+
require.NotEqual(t, uuid.Nil, template.ActiveVersionID)
662+
})
616663
})
617664
}
618665

cli/testdata/coder_templates_push_--help.golden

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ Push a new template version from the current directory or as specified by flag
1010
Always prompt all parameters. Does not pull parameter values from
1111
active template version.
1212

13+
--create bool (default: false)
14+
Create the template if it does not exist.
15+
1316
-d, --directory string (default: .)
1417
Specify the directory to create from, use '-' to read tar from stdin.
1518

docs/cli/templates_push.md

+9
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,15 @@ Whether the new template will be marked active.
2929

3030
Always prompt all parameters. Does not pull parameter values from active template version.
3131

32+
### --create
33+
34+
| | |
35+
| ------- | ------------------ |
36+
| Type | <code>bool</code> |
37+
| Default | <code>false</code> |
38+
39+
Create the template if it does not exist.
40+
3241
### -d, --directory
3342

3443
| | |

0 commit comments

Comments
 (0)