Skip to content

Commit 6691ef8

Browse files
authored
feat: updating pg:upgrade with deprecation warning (#3270)
2 parents 78a5f72 + 6fc47d9 commit 6691ef8

File tree

3 files changed

+159
-32
lines changed

3 files changed

+159
-32
lines changed

packages/cli/src/commands/pg/upgrade/index.ts

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,23 @@ import {Args, ux} from '@oclif/core'
44
import heredoc from 'tsheredoc'
55
import {getAddon} from '../../../lib/pg/fetcher'
66
import pgHost from '../../../lib/pg/host'
7-
import {legacyEssentialPlan, databaseNameFromUrl} from '../../../lib/pg/util'
8-
import {PgDatabase} from '../../../lib/pg/types'
7+
import {legacyEssentialPlan, databaseNameFromUrl, essentialNumPlan, formatResponseWithCommands} from '../../../lib/pg/util'
8+
import {PgDatabase, PgUpgradeError, PgUpgradeResponse} from '../../../lib/pg/types'
99
import * as Heroku from '@heroku-cli/schema'
1010
import confirmCommand from '../../../lib/confirmCommand'
1111
import {nls} from '../../../nls'
1212

1313
export default class Upgrade extends Command {
1414
static topic = 'pg';
1515
static description = heredoc(`
16-
For an Essential-* plan, this command upgrades the database's PostgreSQL version. For a Standard-tier and higher plan, this command unfollows the leader database before upgrading the PostgreSQL version.
17-
To upgrade to another PostgreSQL version, use pg:copy instead
18-
`)
16+
We’re deprecating this command. To upgrade your database's Postgres version, use the new ${color.cmd('pg:upgrade:*')} subcommands. See https://devcenter.heroku.com/changelog-items/3179.
17+
18+
For an Essential-* plan, this command upgrades the database's Postgres version. For a Standard-tier and higher plan, this command unfollows the leader database before upgrading the Postgres version.
19+
`)
1920

2021
static flags = {
2122
confirm: flags.string({char: 'c'}),
22-
version: flags.string({char: 'v', description: 'PostgreSQL version to upgrade to'}),
23+
version: flags.string({char: 'v', description: 'Postgres version to upgrade to'}),
2324
app: flags.app({required: true}),
2425
remote: flags.remote(),
2526
}
@@ -35,29 +36,47 @@ export default class Upgrade extends Command {
3536

3637
const db = await getAddon(this.heroku, app, database)
3738
if (legacyEssentialPlan(db))
38-
ux.error('pg:upgrade is only available for Essential-* databases and follower databases on Standard-tier and higher plans.')
39+
ux.error(`You can only use ${color.cmd('heroku pg:upgrade')} on Essential-tier databases and follower databases on Standard-tier and higher plans.`)
40+
41+
const versionPhrase = version ? heredoc(`Postgres version ${version}`) : heredoc('the latest supported Postgres version')
3942
const {body: replica} = await this.heroku.get<PgDatabase>(`/client/v11/databases/${db.id}`, {hostname: pgHost()})
43+
4044
if (replica.following) {
4145
const {body: configVars} = await this.heroku.get<Heroku.ConfigVars>(`/apps/${app}/config-vars`)
4246
const origin = databaseNameFromUrl(replica.following, configVars)
47+
4348
await confirmCommand(app, confirm, heredoc(`
49+
We’re deprecating this command. To upgrade your database's Postgres version, use the new ${color.cmd('pg:upgrade:*')} subcommands. See https://devcenter.heroku.com/changelog-items/3179.
50+
4451
Destructive action
45-
${color.addon(db.name)} will be upgraded to a newer PostgreSQL version, stop following ${origin}, and become writable.
52+
You're upgrading ${color.addon(db.name)} to ${versionPhrase}. The database will stop following ${origin} and become writable.
4653
4754
This cannot be undone.
4855
`))
49-
} else {
56+
} else if (essentialNumPlan(db)) {
5057
await confirmCommand(app, confirm, heredoc(`
58+
We’re deprecating this command. To upgrade your database's Postgres version, use the new ${color.cmd('pg:upgrade:*')} subcommands. See https://devcenter.heroku.com/changelog-items/3179.
59+
5160
Destructive action
52-
${color.addon(db.name)} will be upgraded to a newer PostgreSQL version.
61+
You're upgrading ${color.addon(db.name)} to ${versionPhrase}.
5362
5463
This cannot be undone.
5564
`))
65+
} else {
66+
ux.warn(heredoc(`
67+
We’re deprecating this command. To upgrade your database's Postgres version, use the new ${color.cmd('pg:upgrade:*')} subcommands. See https://devcenter.heroku.com/changelog-items/3179.`,
68+
))
69+
ux.error(`You can only use ${color.cmd('heroku pg:upgrade')} on Essential-tier databases and follower databases on Standard-tier and higher plans.`)
5670
}
5771

58-
const data = {version}
59-
ux.action.start(`Starting upgrade of ${color.addon(db.name)}`)
60-
await this.heroku.post(`/client/v11/databases/${db.id}/upgrade`, {hostname: pgHost(), body: data})
61-
ux.action.stop(`Use ${color.cmd('heroku pg:wait')} to track status`)
72+
try {
73+
const data = {version}
74+
ux.action.start(`Starting upgrade on ${color.addon(db.name)}`)
75+
const response = await this.heroku.post<PgUpgradeResponse>(`/client/v11/databases/${db.id}/upgrade`, {hostname: pgHost(), body: data})
76+
ux.action.stop(heredoc(`done\n${formatResponseWithCommands(response.body.message)}`))
77+
} catch (error) {
78+
const response = error as PgUpgradeError
79+
ux.error(heredoc(`${formatResponseWithCommands(response.body.message)}\n\nError ID: ${response.body.id}`))
80+
}
6281
}
6382
}

packages/cli/test/acceptance/commands-output.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ pg:settings:log-min-duration-statement The duration of each completed st
206206
pg:settings:log-statement log_statement controls which SQL statements are logged.
207207
pg:settings:track-functions track_functions controls tracking of function call counts and time used. Default is none.
208208
pg:unfollow stop a replica from following and make it a writeable database
209-
pg:upgrade For an Essential-* plan, this command upgrades the database's PostgreSQL version. For a Standard-tier and higher plan, this command unfollows the leader database before upgrading the PostgreSQL version.
209+
pg:upgrade We’re deprecating this command. To upgrade your database's Postgres version, use the new pg:upgrade:* subcommands. See https://devcenter.heroku.com/changelog-items/3179.
210210
pg:vacuum-stats show dead rows and whether an automatic vacuum is expected to be triggered
211211
pg:wait blocks until database is available
212212
pipelines list pipelines you have access to
Lines changed: 125 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,42 @@
11
import {stderr} from 'stdout-stderr'
2-
import Cmd from '../../../../../src/commands/pg/upgrade'
2+
import Cmd from '../../../../../src/commands/pg/upgrade/index'
33
import runCommand from '../../../../helpers/runCommand'
44
import expectOutput from '../../../../helpers/utils/expectOutput'
55
import {expect} from 'chai'
66
import * as nock from 'nock'
77
import heredoc from 'tsheredoc'
88
import * as fixtures from '../../../../fixtures/addons/fixtures'
9+
import color from '@heroku-cli/color'
10+
import {ux} from '@oclif/core'
11+
import * as sinon from 'sinon'
12+
const stripAnsi = require('strip-ansi')
913

1014
describe('pg:upgrade', function () {
1115
const hobbyAddon = fixtures.addons['www-db']
16+
const essentialAddon = fixtures.addons['www-db-3']
1217
const addon = fixtures.addons['dwh-db']
18+
let uxWarnStub: sinon.SinonStub
19+
let uxPromptStub: sinon.SinonStub
1320

14-
afterEach(function () {
21+
before(function () {
22+
uxWarnStub = sinon.stub(ux, 'warn')
23+
uxPromptStub = sinon.stub(ux, 'prompt').resolves('myapp')
24+
})
25+
26+
beforeEach(async function () {
27+
uxWarnStub.resetHistory()
28+
uxPromptStub.resetHistory()
29+
})
30+
31+
afterEach(async function () {
1532
nock.cleanAll()
1633
})
1734

35+
after(function () {
36+
uxWarnStub.restore()
37+
uxPromptStub.restore()
38+
})
39+
1840
it('refuses to upgrade legacy essential dbs', async function () {
1941
nock('https://api.heroku.com')
2042
.post('/actions/addon-attachments/resolve')
@@ -25,36 +47,72 @@ describe('pg:upgrade', function () {
2547
'--confirm',
2648
'myapp',
2749
]).catch(error => {
28-
expect(error.message).to.equal('pg:upgrade is only available for Essential-* databases and follower databases on Standard-tier and higher plans.')
50+
expect(error.message).to.equal(`You can only use ${color.cmd('heroku pg:upgrade')} on Essential-tier databases and follower databases on Standard-tier and higher plans.`)
2951
})
3052
})
3153

32-
it('upgrades db', async function () {
54+
it('refuses to upgrade standard tier leader db', async function () {
3355
nock('https://api.heroku.com')
3456
.post('/actions/addon-attachments/resolve')
35-
.reply(200, [{addon}])
57+
.reply(200, [{addon: addon}])
3658
nock('https://api.heroku.com')
3759
.get('/apps/myapp/config-vars')
3860
.reply(200, {DATABASE_URL: 'postgres://db1'})
3961
nock('https://api.data.heroku.com')
4062
.get(`/client/v11/databases/${addon.id}`)
41-
.reply(200, {following: 'postgres://db1'})
42-
.post(`/client/v11/databases/${addon.id}/upgrade`)
4363
.reply(200)
4464

4565
await runCommand(Cmd, [
4666
'--app',
4767
'myapp',
4868
'--confirm',
4969
'myapp',
70+
]).catch(error => {
71+
expect(error.message).to.equal(`You can only use ${color.cmd('heroku pg:upgrade')} on Essential-tier databases and follower databases on Standard-tier and higher plans.`)
72+
})
73+
})
74+
75+
it('upgrades follower db with version flag', async function () {
76+
nock('https://api.heroku.com')
77+
.post('/actions/addon-attachments/resolve')
78+
.reply(200, [{addon}])
79+
nock('https://api.heroku.com')
80+
.get('/apps/myapp/config-vars')
81+
.reply(200, {DATABASE_URL: 'postgres://db1'})
82+
nock('https://api.data.heroku.com')
83+
.get(`/client/v11/databases/${addon.id}`)
84+
.reply(200, {following: 'postgres://db1'})
85+
nock('https://api.data.heroku.com')
86+
.post(`/client/v11/databases/${addon.id}/upgrade`)
87+
.reply(200, {message: 'Upgrading'})
88+
89+
const message = heredoc(`
90+
We’re deprecating this command. To upgrade your database's Postgres version, use the new pg:upgrade:* subcommands. See https://devcenter.heroku.com/changelog-items/3179.
91+
92+
Destructive action
93+
You're upgrading ${addon.name} to Postgres version 15. The database will stop following DATABASE and become writable.
94+
95+
This cannot be undone.
96+
`)
97+
98+
await runCommand(Cmd, [
99+
'--app',
100+
'myapp',
101+
'--version',
102+
'15',
50103
])
104+
105+
expect(stripAnsi(uxPromptStub.args[0].toString())).contains('To proceed, type myapp')
106+
expect(stripAnsi(uxWarnStub.args[0].toString())).to.eq(message)
107+
51108
expectOutput(stderr.output, heredoc(`
52-
Starting upgrade of ${addon.name}...
53-
Starting upgrade of ${addon.name}... Use heroku pg:wait to track status
109+
Starting upgrade on ${addon.name}...
110+
Starting upgrade on ${addon.name}... done
111+
Upgrading
54112
`))
55113
})
56114

57-
it('upgrades db with version flag', async function () {
115+
it('upgrades follower db without version flag', async function () {
58116
nock('https://api.heroku.com')
59117
.post('/actions/addon-attachments/resolve')
60118
.reply(200, [{addon}])
@@ -64,21 +122,71 @@ describe('pg:upgrade', function () {
64122
nock('https://api.data.heroku.com')
65123
.get(`/client/v11/databases/${addon.id}`)
66124
.reply(200, {following: 'postgres://db1'})
67-
nock('https://api.data.heroku.com')
68125
.post(`/client/v11/databases/${addon.id}/upgrade`)
69-
.reply(200)
126+
.reply(200, {message: 'Upgrading'})
127+
128+
const message = heredoc(`
129+
We’re deprecating this command. To upgrade your database's Postgres version, use the new pg:upgrade:* subcommands. See https://devcenter.heroku.com/changelog-items/3179.
130+
131+
Destructive action
132+
You're upgrading ${addon.name} to the latest supported Postgres version. The database will stop following DATABASE and become writable.
133+
134+
This cannot be undone.
135+
`)
70136

71137
await runCommand(Cmd, [
72138
'--app',
73139
'myapp',
74-
'--confirm',
140+
])
141+
142+
expect(stripAnsi(uxPromptStub.args[0].toString())).contains('To proceed, type myapp')
143+
expect(stripAnsi(uxWarnStub.args[0].toString())).to.eq(message)
144+
145+
expectOutput(stderr.output, heredoc(`
146+
Starting upgrade on ${addon.name}...
147+
Starting upgrade on ${addon.name}... done
148+
Upgrading
149+
`))
150+
})
151+
152+
it('upgrades essential db', async function () {
153+
const essentialAddon = {
154+
name: 'postgres-1', plan: {name: 'heroku-postgresql:essential-0'}, id: 'b68d8f51-6577-4a46-a617-c5f36f1bb031',
155+
}
156+
157+
nock('https://api.heroku.com')
158+
.post('/actions/addon-attachments/resolve')
159+
.reply(200, [{addon: essentialAddon}])
160+
nock('https://api.heroku.com')
161+
.get('/apps/myapp/config-vars')
162+
.reply(200, {DATABASE_URL: 'postgres://db1'})
163+
nock('https://api.data.heroku.com')
164+
.get(`/client/v11/databases/${essentialAddon.id}`)
165+
.reply(200)
166+
.post(`/client/v11/databases/${essentialAddon.id}/upgrade`)
167+
.reply(200, {message: 'Upgrading'})
168+
169+
const message = heredoc(`
170+
We’re deprecating this command. To upgrade your database's Postgres version, use the new pg:upgrade:* subcommands. See https://devcenter.heroku.com/changelog-items/3179.
171+
172+
Destructive action
173+
You're upgrading ${essentialAddon.name} to the latest supported Postgres version.
174+
175+
This cannot be undone.
176+
`)
177+
178+
await runCommand(Cmd, [
179+
'--app',
75180
'myapp',
76-
'--version',
77-
'9.6',
78181
])
182+
183+
expect(stripAnsi(uxPromptStub.args[0].toString())).contains('To proceed, type myapp')
184+
expect(stripAnsi(uxWarnStub.args[0].toString())).to.eq(message)
185+
79186
expectOutput(stderr.output, heredoc(`
80-
Starting upgrade of ${addon.name}...
81-
Starting upgrade of ${addon.name}... Use heroku pg:wait to track status
187+
Starting upgrade on ${essentialAddon.name}...
188+
Starting upgrade on ${essentialAddon.name}... done
189+
Upgrading
82190
`))
83191
})
84192
})

0 commit comments

Comments
 (0)