Skip to content

Commit 78f5b64

Browse files
authored
Merge pull request #153 from replicatedhq/release-and-installer
add --auto option for kurl installers, update release notes generation for release creation to match starter makefile
2 parents 6b6d3a6 + 47b4c93 commit 78f5b64

File tree

4 files changed

+142
-53
lines changed

4 files changed

+142
-53
lines changed

cli/cmd/installer_create.go

Lines changed: 68 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,18 @@ package cmd
33
import (
44
"fmt"
55
"github.com/pkg/errors"
6+
"github.com/replicatedhq/replicated/cli/print"
67
"github.com/spf13/cobra"
78
"io/ioutil"
9+
"time"
810
)
911

1012
func (r *runners) InitInstallerCreate(parent *cobra.Command) {
1113
cmd := &cobra.Command{
1214
Use: "create",
1315
Short: "Create a new installer spec",
1416
Long: `Create a new installer spec by providing YAML configuration for a https://kurl.sh cluster.`,
17+
SilenceUsage: true,
1518
}
1619

1720
parent.AddCommand(cmd)
@@ -20,15 +23,71 @@ func (r *runners) InitInstallerCreate(parent *cobra.Command) {
2023
cmd.Flags().StringVar(&r.args.createInstallerYamlFile, "yaml-file", "", "The file name with YAML config for this installer. Cannot be used with the `yaml` flag.")
2124
cmd.Flags().StringVar(&r.args.createInstallerPromote, "promote", "", "Channel name or id to promote this installer to")
2225
cmd.Flags().BoolVar(&r.args.createInstallerPromoteEnsureChannel, "ensure-channel", false, "When used with --promote <channel>, will create the channel if it doesn't exist")
26+
cmd.Flags().BoolVar(&r.args.createInstallerAutoDefaults, "auto", false, "generate default values for use in CI")
27+
cmd.Flags().BoolVarP(&r.args.createInstallerAutoDefaultsAccept, "confirm-auto", "y", false, "auto-accept the configuration generated by the --auto flag")
2328

2429
cmd.RunE = r.installerCreate
2530
}
2631

32+
func (r *runners) setKOTSDefaultInstallerParams() error {
33+
34+
if r.args.createInstallerYamlFile == "" {
35+
r.args.createInstallerYamlFile = "./kurl-installer.yaml"
36+
}
37+
38+
_, branch, _, err := r.gitSHABranch()
39+
if err != nil {
40+
return errors.Wrapf(err, "get git properties")
41+
}
42+
43+
if r.args.createInstallerPromote == "" {
44+
r.args.createInstallerPromote = branch
45+
if branch == "master" || branch == "main" {
46+
r.args.createInstallerPromote = "Unstable"
47+
}
48+
}
49+
50+
r.args.createInstallerPromoteEnsureChannel = true
51+
52+
return nil
53+
}
54+
2755
func (r *runners) installerCreate(_ *cobra.Command, _ []string) error {
2856
if r.appType != "kots" {
2957
return errors.Errorf("Installer specs are only supported for KOTS applications, app %q has type %q", r.appID, r.appType)
3058
}
3159

60+
log := print.NewLogger(r.w)
61+
if r.args.createInstallerAutoDefaults {
62+
log.ActionWithSpinner("Reading Environment")
63+
err := r.setKOTSDefaultInstallerParams()
64+
if err != nil {
65+
log.FinishSpinnerWithError()
66+
return errors.Wrap(err, "resolve kots defaults")
67+
}
68+
time.Sleep(500 * time.Millisecond)
69+
log.FinishSpinner()
70+
71+
fmt.Fprintf(r.w, `
72+
Prepared to create release with defaults:
73+
74+
yaml-file %q
75+
promote %q
76+
ensure-channel %t
77+
78+
`, r.args.createInstallerYamlFile, r.args.createInstallerPromote, r.args.createInstallerPromoteEnsureChannel)
79+
if !r.args.createInstallerAutoDefaultsAccept {
80+
confirmed, err := promptForConfirm()
81+
if err != nil {
82+
return err
83+
}
84+
if confirmed != "y" {
85+
return errors.New("configuration declined")
86+
}
87+
fmt.Printf("You can use the --confirm-auto or -y flag in the future to skip this prompt.\n")
88+
}
89+
}
90+
3291
if r.args.createInstallerYaml == "" &&
3392
r.args.createInstallerYamlFile == "" {
3493
return errors.New("one of --yaml, --yaml-file is required")
@@ -72,34 +131,35 @@ func (r *runners) installerCreate(_ *cobra.Command, _ []string) error {
72131
return errors.Wrapf(err, "get or create channel %q for promotion", promoteChanID)
73132
}
74133
}
75-
134+
log.ActionWithSpinner("Creating Installer")
76135
installerSpec, err := r.api.CreateInstaller(r.appID, r.appType, r.args.createInstallerYaml)
77136
if err != nil {
78-
return errors.Wrap(err, "create installer")
137+
log.FinishSpinnerWithError()
138+
return err
79139
}
140+
log.FinishSpinner()
80141

81-
if _, err := fmt.Fprintf(r.w, "SEQUENCE: %d\n", installerSpec.Sequence); err != nil {
82-
return errors.Wrap(err, "print sequence to r.w")
83-
}
84-
r.w.Flush()
142+
log.ChildActionWithoutSpinner("SEQUENCE: %d", installerSpec.Sequence)
85143

86144
// don't send a version label as its not really meaningful
87145
noVersionLabel := ""
88146

89147
if promoteChanID != "" {
148+
log.ActionWithSpinner("Promoting")
90149
if err := r.api.PromoteInstaller(
91150
r.appID,
92151
r.appType,
93152
installerSpec.Sequence,
94153
promoteChanID,
95154
noVersionLabel,
96155
); err != nil {
156+
log.FinishSpinnerWithError()
97157
return errors.Wrap(err, "promote installer")
98158
}
159+
log.FinishSpinner()
99160

100161
// ignore error since operation was successful
101-
fmt.Fprintf(r.w, "Channel %s successfully set to release %d\n", promoteChanID, installerSpec.Sequence)
102-
r.w.Flush()
162+
log.ChildActionWithoutSpinner("Channel %s successfully set to installer %d\n", promoteChanID, installerSpec.Sequence)
103163
}
104164

105165
return nil

cli/cmd/release_create.go

Lines changed: 70 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -88,19 +88,42 @@ func (r *runners) gitSHABranch() (sha string, branch string, dirty bool, err err
8888
return h.String()[0:6], head.Name().Short(), !status.IsClean(), nil
8989
}
9090

91-
func (r *runners) setKOTSDefaults() error {
91+
func (r *runners) setKOTSDefaultReleaseParams() error {
92+
93+
if r.args.createReleaseYamlDir == "" {
94+
r.args.createReleaseYamlDir = "./manifests"
95+
}
96+
9297
rev, branch, isDirty, err := r.gitSHABranch()
9398
if err != nil {
9499
return errors.Wrapf(err, "get git properties")
95100
}
96-
97-
if r.args.createReleaseYamlDir == "" {
98-
r.args.createReleaseYamlDir = "./manifests"
101+
dirtyStatus := ""
102+
if isDirty {
103+
dirtyStatus = "-dirty"
99104
}
100105

101106
if r.args.createReleasePromoteNotes == "" {
107+
// set some default release notes
102108
r.args.createReleasePromoteNotes = fmt.Sprintf(
103-
`CLI release by %s on %s`, os.Getenv("USER"), time.Now().Format(time.RFC822))
109+
`CLI release of %s triggered by %s [SHA: %s%s] [%s]`,
110+
branch,
111+
os.Getenv("USER"),
112+
rev,
113+
dirtyStatus,
114+
time.Now().Format(time.RFC822),
115+
)
116+
// unless it's GH actions, then we can link to the commit! yay!
117+
if os.Getenv("GITHUB_ACTIONS") != "" {
118+
r.args.createReleasePromoteNotes = fmt.Sprintf(
119+
`GitHub Action release of %s triggered by %s: [%s](https://github.com/%s/commit/%s)`,
120+
os.Getenv("GITHUB_REF"),
121+
os.Getenv("GITHUB_ACTOR"),
122+
os.Getenv("GITHUB_SHA")[0:7],
123+
os.Getenv("GITHUB_REPOSITORY"),
124+
os.Getenv("GITHUB_SHA"),
125+
)
126+
}
104127
}
105128

106129
if r.args.createReleasePromote == "" {
@@ -111,10 +134,6 @@ func (r *runners) setKOTSDefaults() error {
111134
}
112135

113136
if r.args.createReleasePromoteVersion == "" {
114-
dirtyStatus := ""
115-
if isDirty {
116-
dirtyStatus = "-dirty"
117-
}
118137
r.args.createReleasePromoteVersion = fmt.Sprintf("%s-%s%s", r.args.createReleasePromote, rev, dirtyStatus)
119138
}
120139

@@ -129,7 +148,7 @@ func (r *runners) releaseCreate(_ *cobra.Command, _ []string) error {
129148

130149
if r.appType == "kots" && r.args.createReleaseAutoDefaults {
131150
log.ActionWithSpinner("Reading Environment")
132-
err := r.setKOTSDefaults()
151+
err := r.setKOTSDefaultReleaseParams()
133152
if err != nil {
134153
log.FinishSpinnerWithError()
135154
return errors.Wrap(err, "resolve kots defaults")
@@ -159,38 +178,9 @@ Prepared to create release with defaults:
159178
}
160179
}
161180

162-
if r.args.createReleaseYaml == "" && r.args.createReleaseYamlFile == "" && r.appType != "kots" {
163-
return errors.New("one of --yaml, --yaml-file must be provided")
164-
}
165-
166-
if r.args.createReleaseYaml != "" && r.args.createReleaseYamlFile != "" {
167-
return errors.New("only one of --yaml or --yaml-file may be specified")
168-
}
169-
170-
if r.args.createReleaseYamlDir == "" && r.appType == "kots" {
171-
return errors.New("--yaml-dir flag must be provided for KOTS applications")
172-
}
173-
174-
// can't ensure a channel if you didn't pass one
175-
if r.args.createReleasePromoteEnsureChannel && r.args.createReleasePromote == "" {
176-
return errors.New("cannot use the flag --ensure-channel without also using --promote <channel> ")
177-
}
178-
179-
// we check this again below, but lets be explicit and fail fast
180-
if r.args.createReleasePromoteEnsureChannel && !(r.appType == "ship" || r.appType == "kots") {
181-
return errors.Errorf("the flag --ensure-channel is only supported for KOTS and Ship applications, app %q is of type %q", r.appID, r.appType)
182-
}
183-
184-
if r.args.createReleasePromoteRequired && r.appType == "kots" {
185-
return errors.Errorf("the --required flag is not supported for KOTS applications")
186-
}
187-
188-
if r.args.createReleaseYamlFile != "" && r.appType == "kots" {
189-
return errors.Errorf("the --yaml-file flag is not supported for KOTS applications, use --yaml-dir instead")
190-
}
191-
192-
if r.args.createReleaseYaml != "" && r.appType == "kots" {
193-
return errors.Errorf("the --yaml flag is not supported for KOTS applications, use --yaml-dir instead")
181+
err := r.validateReleaseCreateParams()
182+
if err != nil {
183+
return errors.Wrap(err, "validate params")
194184
}
195185

196186
if r.args.createReleaseYaml == "-" {
@@ -268,6 +258,43 @@ Prepared to create release with defaults:
268258
return nil
269259
}
270260

261+
func (r *runners) validateReleaseCreateParams() error {
262+
if r.args.createReleaseYaml == "" && r.args.createReleaseYamlFile == "" && r.appType != "kots" {
263+
return errors.New("one of --yaml, --yaml-file must be provided")
264+
}
265+
266+
if r.args.createReleaseYaml != "" && r.args.createReleaseYamlFile != "" {
267+
return errors.New("only one of --yaml or --yaml-file may be specified")
268+
}
269+
270+
if r.args.createReleaseYamlDir == "" && r.appType == "kots" {
271+
return errors.New("--yaml-dir flag must be provided for KOTS applications")
272+
}
273+
274+
// can't ensure a channel if you didn't pass one
275+
if r.args.createReleasePromoteEnsureChannel && r.args.createReleasePromote == "" {
276+
return errors.New("cannot use the flag --ensure-channel without also using --promote <channel> ")
277+
}
278+
279+
// we check this again below, but lets be explicit and fail fast
280+
if r.args.createReleasePromoteEnsureChannel && !(r.appType == "ship" || r.appType == "kots") {
281+
return errors.Errorf("the flag --ensure-channel is only supported for KOTS and Ship applications, app %q is of type %q", r.appID, r.appType)
282+
}
283+
284+
if r.args.createReleasePromoteRequired && r.appType == "kots" {
285+
return errors.Errorf("the --required flag is not supported for KOTS applications")
286+
}
287+
288+
if r.args.createReleaseYamlFile != "" && r.appType == "kots" {
289+
return errors.Errorf("the --yaml-file flag is not supported for KOTS applications, use --yaml-dir instead")
290+
}
291+
292+
if r.args.createReleaseYaml != "" && r.appType == "kots" {
293+
return errors.Errorf("the --yaml flag is not supported for KOTS applications, use --yaml-dir instead")
294+
}
295+
return nil
296+
}
297+
271298
func (r *runners) getOrCreateChannelForPromotion(channelName string, createIfAbsent bool) (string, error) {
272299

273300
description := "" // todo: do we want a flag for the desired channel description
@@ -363,7 +390,7 @@ func promptForConfirm() (string, error) {
363390
}
364391

365392
prompt := promptui.Prompt{
366-
Label: "Create release with these properties? [Y/n]",
393+
Label: "Create with these properties? [Y/n]",
367394
Templates: templates,
368395
Default: "y",
369396
Validate: func(input string) error {

cli/cmd/runner.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,5 +139,7 @@ type runnerArgs struct {
139139
createReleaseAutoDefaults bool
140140
createReleaseAutoDefaultsAccept bool
141141

142-
releaseDownloadDest string
142+
releaseDownloadDest string
143+
createInstallerAutoDefaults bool
144+
createInstallerAutoDefaultsAccept bool
143145
}

cli/test/kots_installer_create_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ spec:
8383
req.NotEmpty(stdout.String(), "Expected stdout output")
8484

8585
req.Contains(stdout.String(), `SEQUENCE: 2`)
86-
req.Contains(stdout.String(), `successfully set to release 2`)
86+
req.Contains(stdout.String(), `successfully set to installer 2`)
8787
})
8888
})
8989
})

0 commit comments

Comments
 (0)