Skip to content

Commit 5159521

Browse files
committed
Add dry run flag to extension upgrade
1 parent af849ca commit 5159521

File tree

6 files changed

+207
-40
lines changed

6 files changed

+207
-40
lines changed

pkg/cmd/extension/command.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command {
117117
func() *cobra.Command {
118118
var flagAll bool
119119
var flagForce bool
120+
var flagDryRun bool
120121
cmd := &cobra.Command{
121122
Use: "upgrade {<name> | --all}",
122123
Short: "Upgrade installed extensions",
@@ -127,6 +128,9 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command {
127128
if len(args) > 0 && flagAll {
128129
return cmdutil.FlagErrorf("cannot use `--all` with extension name")
129130
}
131+
if flagForce && flagDryRun {
132+
return cmdutil.FlagErrorf("cannot use `--force` and `--dry-run`")
133+
}
130134
if len(args) > 1 {
131135
return cmdutil.FlagErrorf("too many arguments")
132136
}
@@ -138,7 +142,7 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command {
138142
name = normalizeExtensionSelector(args[0])
139143
}
140144
cs := io.ColorScheme()
141-
err := m.Upgrade(name, flagForce)
145+
err := m.Upgrade(name, flagForce, flagDryRun)
142146
if err != nil && !errors.Is(err, upToDateError) {
143147
if name != "" {
144148
fmt.Fprintf(io.ErrOut, "%s Failed upgrading extension %s: %s\n", cs.FailureIcon(), name, err)
@@ -148,19 +152,24 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command {
148152
return cmdutil.SilentError
149153
}
150154
if io.IsStdoutTTY() {
155+
successStr := "Successfully"
156+
if flagDryRun {
157+
successStr = "Would have"
158+
}
151159
if errors.Is(err, upToDateError) {
152160
fmt.Fprintf(io.Out, "%s Extension already up to date\n", cs.SuccessIcon())
153161
} else if name != "" {
154-
fmt.Fprintf(io.Out, "%s Successfully upgraded extension %s\n", cs.SuccessIcon(), name)
162+
fmt.Fprintf(io.Out, "%s %s upgraded extension %s\n", cs.SuccessIcon(), successStr, name)
155163
} else {
156-
fmt.Fprintf(io.Out, "%s Successfully upgraded extensions\n", cs.SuccessIcon())
164+
fmt.Fprintf(io.Out, "%s %s upgraded extensions\n", cs.SuccessIcon(), successStr)
157165
}
158166
}
159167
return nil
160168
},
161169
}
162170
cmd.Flags().BoolVar(&flagAll, "all", false, "Upgrade all extensions")
163171
cmd.Flags().BoolVar(&flagForce, "force", false, "Force upgrade extension")
172+
cmd.Flags().BoolVar(&flagDryRun, "dry-run", false, "Only display upgrades")
164173
return cmd
165174
}(),
166175
&cobra.Command{

pkg/cmd/extension/command_test.go

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -92,11 +92,23 @@ func TestNewCmdExtension(t *testing.T) {
9292
wantErr: true,
9393
errMsg: "specify an extension to upgrade or `--all`",
9494
},
95+
{
96+
name: "upgrade --all with extension name error",
97+
args: []string{"upgrade", "test", "--all"},
98+
wantErr: true,
99+
errMsg: "cannot use `--all` with extension name",
100+
},
101+
{
102+
name: "upgrade --force and --dry-run error",
103+
args: []string{"upgrade", "test", "--force", "--dry-run"},
104+
wantErr: true,
105+
errMsg: "cannot use `--force` and `--dry-run`",
106+
},
95107
{
96108
name: "upgrade an extension",
97109
args: []string{"upgrade", "hello"},
98110
managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) {
99-
em.UpgradeFunc = func(name string, force bool) error {
111+
em.UpgradeFunc = func(name string, force, dryRun bool) error {
100112
return nil
101113
}
102114
return func(t *testing.T) {
@@ -108,11 +120,29 @@ func TestNewCmdExtension(t *testing.T) {
108120
isTTY: true,
109121
wantStdout: "✓ Successfully upgraded extension hello\n",
110122
},
123+
{
124+
name: "upgrade an extension dry run",
125+
args: []string{"upgrade", "hello", "--dry-run"},
126+
managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) {
127+
em.UpgradeFunc = func(name string, force, dryRun bool) error {
128+
return nil
129+
}
130+
return func(t *testing.T) {
131+
calls := em.UpgradeCalls()
132+
assert.Equal(t, 1, len(calls))
133+
assert.Equal(t, "hello", calls[0].Name)
134+
assert.False(t, calls[0].Force)
135+
assert.True(t, calls[0].DryRun)
136+
}
137+
},
138+
isTTY: true,
139+
wantStdout: "✓ Would have upgraded extension hello\n",
140+
},
111141
{
112142
name: "upgrade an extension notty",
113143
args: []string{"upgrade", "hello"},
114144
managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) {
115-
em.UpgradeFunc = func(name string, force bool) error {
145+
em.UpgradeFunc = func(name string, force, dryRun bool) error {
116146
return nil
117147
}
118148
return func(t *testing.T) {
@@ -127,7 +157,7 @@ func TestNewCmdExtension(t *testing.T) {
127157
name: "upgrade an up-to-date extension",
128158
args: []string{"upgrade", "hello"},
129159
managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) {
130-
em.UpgradeFunc = func(name string, force bool) error {
160+
em.UpgradeFunc = func(name string, force, dryRun bool) error {
131161
return upToDateError
132162
}
133163
return func(t *testing.T) {
@@ -144,7 +174,7 @@ func TestNewCmdExtension(t *testing.T) {
144174
name: "upgrade extension error",
145175
args: []string{"upgrade", "hello"},
146176
managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) {
147-
em.UpgradeFunc = func(name string, force bool) error {
177+
em.UpgradeFunc = func(name string, force, dryRun bool) error {
148178
return errors.New("oh no")
149179
}
150180
return func(t *testing.T) {
@@ -163,7 +193,7 @@ func TestNewCmdExtension(t *testing.T) {
163193
name: "upgrade an extension gh-prefix",
164194
args: []string{"upgrade", "gh-hello"},
165195
managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) {
166-
em.UpgradeFunc = func(name string, force bool) error {
196+
em.UpgradeFunc = func(name string, force, dryRun bool) error {
167197
return nil
168198
}
169199
return func(t *testing.T) {
@@ -179,7 +209,7 @@ func TestNewCmdExtension(t *testing.T) {
179209
name: "upgrade an extension full name",
180210
args: []string{"upgrade", "monalisa/gh-hello"},
181211
managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) {
182-
em.UpgradeFunc = func(name string, force bool) error {
212+
em.UpgradeFunc = func(name string, force, dryRun bool) error {
183213
return nil
184214
}
185215
return func(t *testing.T) {
@@ -195,7 +225,7 @@ func TestNewCmdExtension(t *testing.T) {
195225
name: "upgrade all",
196226
args: []string{"upgrade", "--all"},
197227
managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) {
198-
em.UpgradeFunc = func(name string, force bool) error {
228+
em.UpgradeFunc = func(name string, force, dryRun bool) error {
199229
return nil
200230
}
201231
return func(t *testing.T) {
@@ -207,11 +237,29 @@ func TestNewCmdExtension(t *testing.T) {
207237
isTTY: true,
208238
wantStdout: "✓ Successfully upgraded extensions\n",
209239
},
240+
{
241+
name: "upgrade all dry run",
242+
args: []string{"upgrade", "--all", "--dry-run"},
243+
managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) {
244+
em.UpgradeFunc = func(name string, force, dryRun bool) error {
245+
return nil
246+
}
247+
return func(t *testing.T) {
248+
calls := em.UpgradeCalls()
249+
assert.Equal(t, 1, len(calls))
250+
assert.Equal(t, "", calls[0].Name)
251+
assert.False(t, calls[0].Force)
252+
assert.True(t, calls[0].DryRun)
253+
}
254+
},
255+
isTTY: true,
256+
wantStdout: "✓ Would have upgraded extensions\n",
257+
},
210258
{
211259
name: "upgrade all notty",
212260
args: []string{"upgrade", "--all"},
213261
managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) {
214-
em.UpgradeFunc = func(name string, force bool) error {
262+
em.UpgradeFunc = func(name string, force, dryRun bool) error {
215263
return nil
216264
}
217265
return func(t *testing.T) {

pkg/cmd/extension/manager.go

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ var localExtensionUpgradeError = errors.New("local extensions can not be upgrade
427427
var upToDateError = errors.New("already up to date")
428428
var noExtensionsInstalledError = errors.New("no extensions installed")
429429

430-
func (m *Manager) Upgrade(name string, force bool) error {
430+
func (m *Manager) Upgrade(name string, force, dryRun bool) error {
431431
// Fetch metadata during list only when upgrading all extensions.
432432
// This is a performance improvement so that we don't make a
433433
// bunch of unecessary network requests when trying to upgrade a single extension.
@@ -437,7 +437,7 @@ func (m *Manager) Upgrade(name string, force bool) error {
437437
return noExtensionsInstalledError
438438
}
439439
if name == "" {
440-
return m.upgradeExtensions(exts, force)
440+
return m.upgradeExtensions(exts, force, dryRun)
441441
}
442442
for _, f := range exts {
443443
if f.Name() != name {
@@ -450,16 +450,16 @@ func (m *Manager) Upgrade(name string, force bool) error {
450450
if err != nil {
451451
return err
452452
}
453-
return m.upgradeExtension(f, force)
453+
return m.upgradeExtension(f, force, dryRun)
454454
}
455455
return fmt.Errorf("no extension matched %q", name)
456456
}
457457

458-
func (m *Manager) upgradeExtensions(exts []Extension, force bool) error {
458+
func (m *Manager) upgradeExtensions(exts []Extension, force, dryRun bool) error {
459459
var failed bool
460460
for _, f := range exts {
461461
fmt.Fprintf(m.io.Out, "[%s]: ", f.Name())
462-
err := m.upgradeExtension(f, force)
462+
err := m.upgradeExtension(f, force, dryRun)
463463
if err != nil {
464464
if !errors.Is(err, localExtensionUpgradeError) &&
465465
!errors.Is(err, upToDateError) {
@@ -468,21 +468,28 @@ func (m *Manager) upgradeExtensions(exts []Extension, force bool) error {
468468
fmt.Fprintf(m.io.Out, "%s\n", err)
469469
continue
470470
}
471-
fmt.Fprintf(m.io.Out, "upgrade complete\n")
471+
if dryRun {
472+
fmt.Fprintf(m.io.Out, "would have upgraded from %s to %s\n", f.currentVersion, f.latestVersion)
473+
} else {
474+
fmt.Fprintf(m.io.Out, "upgrade complete\n")
475+
}
472476
}
473477
if failed {
474478
return errors.New("some extensions failed to upgrade")
475479
}
476480
return nil
477481
}
478482

479-
func (m *Manager) upgradeExtension(ext Extension, force bool) error {
483+
func (m *Manager) upgradeExtension(ext Extension, force, dryRun bool) error {
480484
if ext.isLocal {
481485
return localExtensionUpgradeError
482486
}
483487
if !ext.UpdateAvailable() {
484488
return upToDateError
485489
}
490+
if dryRun {
491+
return nil
492+
}
486493
var err error
487494
if ext.IsBinary() {
488495
err = m.upgradeBinExtension(ext)

0 commit comments

Comments
 (0)