Skip to content

Commit 7c09da2

Browse files
committed
feat: add archiving template versions to hide from ui
1 parent 49b509b commit 7c09da2

26 files changed

+1221
-37
lines changed

cli/templatedelete.go

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -48,33 +48,13 @@ func (r *RootCmd) templateDelete() *clibase.Cmd {
4848
templates = append(templates, template)
4949
}
5050
} else {
51-
allTemplates, err := client.TemplatesByOrganization(ctx, organization.ID)
51+
template, err := selectTemplate(inv, client, organization)
5252
if err != nil {
53-
return xerrors.Errorf("get templates by organization: %w", err)
53+
return err
5454
}
5555

56-
if len(allTemplates) == 0 {
57-
return xerrors.Errorf("no templates exist in the current organization %q", organization.Name)
58-
}
59-
60-
opts := make([]string, 0, len(allTemplates))
61-
for _, template := range allTemplates {
62-
opts = append(opts, template.Name)
63-
}
64-
65-
selection, err := cliui.Select(inv, cliui.SelectOptions{
66-
Options: opts,
67-
})
68-
if err != nil {
69-
return xerrors.Errorf("select template: %w", err)
70-
}
71-
72-
for _, template := range allTemplates {
73-
if template.Name == selection {
74-
templates = append(templates, template)
75-
templateNames = append(templateNames, template.Name)
76-
}
77-
}
56+
templates = append(templates, template)
57+
templateNames = append(templateNames, template.Name)
7858
}
7959

8060
// Confirm deletion of the template.

cli/templates.go

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ package cli
33
import (
44
"time"
55

6-
"github.com/google/uuid"
7-
86
"github.com/coder/pretty"
7+
"github.com/google/uuid"
8+
"golang.org/x/xerrors"
99

1010
"github.com/coder/coder/v2/cli/clibase"
1111
"github.com/coder/coder/v2/cli/cliui"
@@ -43,12 +43,45 @@ func (r *RootCmd) templates() *clibase.Cmd {
4343
r.templateVersions(),
4444
r.templateDelete(),
4545
r.templatePull(),
46+
r.archiveTemplateVersions(),
4647
},
4748
}
4849

4950
return cmd
5051
}
5152

53+
func selectTemplate(inv *clibase.Invocation, client *codersdk.Client, organization codersdk.Organization) (codersdk.Template, error) {
54+
var empty codersdk.Template
55+
ctx := inv.Context()
56+
allTemplates, err := client.TemplatesByOrganization(ctx, organization.ID)
57+
if err != nil {
58+
return empty, xerrors.Errorf("get templates by organization: %w", err)
59+
}
60+
61+
if len(allTemplates) == 0 {
62+
return empty, xerrors.Errorf("no templates exist in the current organization %q", organization.Name)
63+
}
64+
65+
opts := make([]string, 0, len(allTemplates))
66+
for _, template := range allTemplates {
67+
opts = append(opts, template.Name)
68+
}
69+
70+
selection, err := cliui.Select(inv, cliui.SelectOptions{
71+
Options: opts,
72+
})
73+
if err != nil {
74+
return empty, xerrors.Errorf("select template: %w", err)
75+
}
76+
77+
for _, template := range allTemplates {
78+
if template.Name == selection {
79+
return template, nil
80+
}
81+
}
82+
return empty, xerrors.Errorf("no template selected")
83+
}
84+
5285
type templateTableRow struct {
5386
// Used by json format:
5487
Template codersdk.Template

cli/templateversionarchive.go

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
package cli
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"strings"
7+
"time"
8+
9+
"github.com/coder/pretty"
10+
"golang.org/x/xerrors"
11+
12+
"github.com/coder/coder/v2/cli/clibase"
13+
"github.com/coder/coder/v2/cli/cliui"
14+
"github.com/coder/coder/v2/codersdk"
15+
)
16+
17+
func (r *RootCmd) unarchiveTemplateVersion() *clibase.Cmd {
18+
return r.setArchiveTemplateVersion(false)
19+
}
20+
21+
func (r *RootCmd) archiveTemplateVersion() *clibase.Cmd {
22+
return r.setArchiveTemplateVersion(true)
23+
}
24+
25+
//nolint:revive
26+
func (r *RootCmd) setArchiveTemplateVersion(archive bool) *clibase.Cmd {
27+
presentVerb := "archive"
28+
pastVerb := "archived"
29+
if !archive {
30+
presentVerb = "unarchive"
31+
pastVerb = "unarchived"
32+
}
33+
34+
client := new(codersdk.Client)
35+
cmd := &clibase.Cmd{
36+
Use: presentVerb + " <template-name> [template-version-names...] ",
37+
Short: strings.ToUpper(string(presentVerb[0])) + presentVerb[1:] + " a template version(s).",
38+
Middleware: clibase.Chain(
39+
r.InitClient(client),
40+
),
41+
Options: clibase.OptionSet{
42+
cliui.SkipPromptOption(),
43+
},
44+
Handler: func(inv *clibase.Invocation) error {
45+
var (
46+
ctx = inv.Context()
47+
versions []codersdk.TemplateVersion
48+
)
49+
50+
organization, err := CurrentOrganization(inv, client)
51+
if err != nil {
52+
return err
53+
}
54+
55+
if len(inv.Args) == 0 {
56+
return xerrors.Errorf("missing template name")
57+
}
58+
if len(inv.Args) < 2 {
59+
return xerrors.Errorf("missing template version name(s)")
60+
}
61+
62+
templateName := inv.Args[0]
63+
template, err := client.TemplateByName(ctx, organization.ID, templateName)
64+
if err != nil {
65+
return xerrors.Errorf("get template by name: %w", err)
66+
}
67+
for _, versionName := range inv.Args[1:] {
68+
version, err := client.TemplateVersionByOrganizationAndName(ctx, organization.ID, template.Name, versionName)
69+
if err != nil {
70+
return xerrors.Errorf("get template version by name %q: %w", versionName, err)
71+
}
72+
versions = append(versions, version)
73+
}
74+
75+
for _, version := range versions {
76+
if version.Archived == archive {
77+
_, _ = fmt.Fprintln(
78+
inv.Stdout, fmt.Sprintf("Version "+pretty.Sprint(cliui.DefaultStyles.Keyword, version.Name)+" already "+pastVerb),
79+
)
80+
continue
81+
}
82+
83+
err := client.SetArchiveTemplateVersion(ctx, version.ID, archive)
84+
if err != nil {
85+
return xerrors.Errorf("%s template version %q: %w", presentVerb, version.Name, err)
86+
}
87+
88+
_, _ = fmt.Fprintln(
89+
inv.Stdout, fmt.Sprintf("Version "+pretty.Sprint(cliui.DefaultStyles.Keyword, version.Name)+" "+pastVerb+" at "+cliui.Timestamp(time.Now())),
90+
)
91+
}
92+
return nil
93+
},
94+
}
95+
96+
return cmd
97+
}
98+
99+
func (r *RootCmd) archiveTemplateVersions() *clibase.Cmd {
100+
var all clibase.Bool
101+
client := new(codersdk.Client)
102+
cmd := &clibase.Cmd{
103+
Use: "archive [template-name...] ",
104+
Short: "Archive unused failed template versions from a given template(s)",
105+
Middleware: clibase.Chain(
106+
r.InitClient(client),
107+
),
108+
Options: clibase.OptionSet{
109+
cliui.SkipPromptOption(),
110+
clibase.Option{
111+
Name: "all",
112+
Description: "Include all unused template versions. By default, only failed template versions are archived.",
113+
Flag: "all",
114+
Value: &all,
115+
},
116+
},
117+
Handler: func(inv *clibase.Invocation) error {
118+
var (
119+
ctx = inv.Context()
120+
templateNames = []string{}
121+
templates = []codersdk.Template{}
122+
)
123+
124+
organization, err := CurrentOrganization(inv, client)
125+
if err != nil {
126+
return err
127+
}
128+
129+
if len(inv.Args) > 0 {
130+
templateNames = inv.Args
131+
132+
for _, templateName := range templateNames {
133+
template, err := client.TemplateByName(ctx, organization.ID, templateName)
134+
if err != nil {
135+
return xerrors.Errorf("get template by name: %w", err)
136+
}
137+
templates = append(templates, template)
138+
}
139+
} else {
140+
template, err := selectTemplate(inv, client, organization)
141+
if err != nil {
142+
return err
143+
}
144+
145+
templates = append(templates, template)
146+
templateNames = append(templateNames, template.Name)
147+
}
148+
149+
// Confirm archive of the template.
150+
_, err = cliui.Prompt(inv, cliui.PromptOptions{
151+
Text: fmt.Sprintf("Archive template versions of these templates: %s?", pretty.Sprint(cliui.DefaultStyles.Code, strings.Join(templateNames, ", "))),
152+
IsConfirm: true,
153+
Default: cliui.ConfirmNo,
154+
})
155+
if err != nil {
156+
return err
157+
}
158+
159+
for _, template := range templates {
160+
resp, err := client.ArchiveTemplateVersions(ctx, template.ID, all.Value())
161+
if err != nil {
162+
return xerrors.Errorf("archive template %q: %w", template.Name, err)
163+
}
164+
165+
_, _ = fmt.Fprintln(
166+
inv.Stdout, fmt.Sprintf("Archived %d versions from "+pretty.Sprint(cliui.DefaultStyles.Keyword, template.Name)+" at "+cliui.Timestamp(time.Now()), len(resp.ArchivedIDs)),
167+
)
168+
169+
if ok, _ := inv.ParsedFlags().GetBool("verbose"); err == nil && ok {
170+
data, err := json.Marshal(resp)
171+
if err != nil {
172+
return xerrors.Errorf("marshal verbose response: %w", err)
173+
}
174+
_, _ = fmt.Fprintln(
175+
inv.Stdout, string(data),
176+
)
177+
}
178+
}
179+
return nil
180+
},
181+
}
182+
183+
return cmd
184+
}

cli/templateversions.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import (
55
"strings"
66
"time"
77

8+
"github.com/coder/pretty"
9+
810
"github.com/google/uuid"
911
"golang.org/x/xerrors"
1012

@@ -29,6 +31,8 @@ func (r *RootCmd) templateVersions() *clibase.Cmd {
2931
},
3032
Children: []*clibase.Cmd{
3133
r.templateVersionsList(),
34+
r.archiveTemplateVersion(),
35+
r.unarchiveTemplateVersion(),
3236
},
3337
}
3438

@@ -42,13 +46,23 @@ func (r *RootCmd) templateVersionsList() *clibase.Cmd {
4246
)
4347
client := new(codersdk.Client)
4448

49+
var includeArchived clibase.Bool
50+
4551
cmd := &clibase.Cmd{
4652
Use: "list <template>",
4753
Middleware: clibase.Chain(
4854
clibase.RequireNArgs(1),
4955
r.InitClient(client),
5056
),
5157
Short: "List all the versions of the specified template",
58+
Options: clibase.OptionSet{
59+
{
60+
Name: "include-archived",
61+
Description: "Include archived versions in the result list.",
62+
Flag: "include-archived",
63+
Value: &includeArchived,
64+
},
65+
},
5266
Handler: func(inv *clibase.Invocation) error {
5367
organization, err := CurrentOrganization(inv, client)
5468
if err != nil {
@@ -59,7 +73,8 @@ func (r *RootCmd) templateVersionsList() *clibase.Cmd {
5973
return xerrors.Errorf("get template by name: %w", err)
6074
}
6175
req := codersdk.TemplateVersionsByTemplateRequest{
62-
TemplateID: template.ID,
76+
TemplateID: template.ID,
77+
IncludeArchived: includeArchived.Value(),
6378
}
6479

6580
versions, err := client.TemplateVersionsByTemplate(inv.Context(), req)
@@ -92,6 +107,7 @@ type templateVersionRow struct {
92107
CreatedBy string `json:"-" table:"created by"`
93108
Status string `json:"-" table:"status"`
94109
Active string `json:"-" table:"active"`
110+
Archived string `json:"-" table:"archived"`
95111
}
96112

97113
// templateVersionsToRows converts a list of template versions to a list of rows
@@ -104,13 +120,19 @@ func templateVersionsToRows(activeVersionID uuid.UUID, templateVersions ...coder
104120
activeStatus = cliui.Keyword("Active")
105121
}
106122

123+
archivedStatus := ""
124+
if templateVersion.Archived {
125+
archivedStatus = pretty.Sprint(cliui.DefaultStyles.Warn, "Archived")
126+
}
127+
107128
rows[i] = templateVersionRow{
108129
TemplateVersion: templateVersion,
109130
Name: templateVersion.Name,
110131
CreatedAt: templateVersion.CreatedAt,
111132
CreatedBy: templateVersion.CreatedBy.Username,
112133
Status: strings.Title(string(templateVersion.Job.Status)),
113134
Active: activeStatus,
135+
Archived: archivedStatus,
114136
}
115137
}
116138

0 commit comments

Comments
 (0)