Skip to content

Commit 8271d51

Browse files
heroku-johnnyclaudemichaelmalave
authored
feat(pg,redis): add --as flag to pg:promote and redis:promote (W-23597911, #1819) (#3841)
feat(pg,redis): add --as flag to pg:promote and redis:promote for custom attachment names Resolves W-23597911 / GitHub #1819. Previously, both commands hardcoded the attachment name (DATABASE and REDIS respectively). With this change, users can pass --as NAME to create the promoted attachment under a custom name, falling back to the original default when the flag is omitted. Co-authored-by: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Michael Malave <michael.malave@salesforce.com>
1 parent 57d4124 commit 8271d51

4 files changed

Lines changed: 86 additions & 7 deletions

File tree

src/commands/pg/promote.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@ export default class Promote extends Command {
1818
static description = 'sets DATABASE as your DATABASE_URL'
1919
static flags = {
2020
app: flags.app({required: true}),
21+
as: flags.string({description: 'name for the database attachment'}),
2122
force: flags.boolean({char: 'f'}),
2223
remote: flags.remote(),
2324
}
2425
static topic = 'pg'
2526

2627
public async run(): Promise<void> {
2728
const {args, flags} = await this.parse(Promote)
28-
const {app, force} = flags
29+
const {app, as, force} = flags
2930
const {database} = args
3031
const dbResolver = new utils.pg.DatabaseResolver(this.heroku)
3132
const attachment = await dbResolver.getAttachment(app, database)
@@ -87,7 +88,7 @@ export default class Promote extends Command {
8788
addon: {name: attachment.addon.name},
8889
app: {name: app},
8990
confirm: app,
90-
name: 'DATABASE',
91+
name: as || 'DATABASE',
9192
namespace: attachment.namespace || null,
9293
},
9394
})

src/commands/redis/promote.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,32 @@ export default class Promote extends Command {
1111
static description = 'sets DATABASE as your REDIS_URL'
1212
static flags = {
1313
app: flags.app({required: true}),
14+
as: flags.string({description: 'name for the Key-Value Store attachment'}),
1415
remote: flags.remote(),
1516
}
1617
static topic = 'redis'
1718

1819
public async run(): Promise<void> {
1920
const {args, flags} = await this.parse(Promote)
20-
const api = apiFactory(flags.app, args.database, false, this.heroku)
21-
const {body: addonsList} = await this.heroku.get<Required<Heroku.AddOn>[]>(`/apps/${flags.app}/addons`)
21+
const {app, as} = flags
22+
const api = apiFactory(app, args.database, false, this.heroku)
23+
const {body: addonsList} = await this.heroku.get<Required<Heroku.AddOn>[]>(`/apps/${app}/addons`)
2224
const addon = await api.getRedisAddon(addonsList)
2325
const redisFilter = api.makeAddonsFilter('REDIS_URL')
2426
const redis = redisFilter(addonsList) as Required<Heroku.AddOn>[]
2527
if (redis.length === 1 && redis[0].config_vars.filter((c: string) => c.endsWith('_URL')).length === 1) {
2628
const attachment = redis[0]
2729
await this.heroku.post('/addon-attachments', {
2830
body: {
29-
addon: {name: attachment.name}, app: {name: flags.app}, confirm: flags.app,
31+
addon: {name: attachment.name}, app: {name: app}, confirm: app,
3032
},
3133
})
3234
}
3335

34-
ux.stdout(`Promoting ${addon.name} to REDIS_URL on ${flags.app}`)
36+
ux.stdout(`Promoting ${addon.name} to REDIS_URL on ${app}`)
3537
await this.heroku.post('/addon-attachments', {
3638
body: {
37-
addon: {name: addon.name}, app: {name: flags.app}, confirm: flags.app, name: 'REDIS',
39+
addon: {name: addon.name}, app: {name: app}, confirm: app, name: as || 'REDIS',
3840
},
3941
})
4042
}

test/unit/commands/pg/promote.unit.test.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,45 @@ describe('pg:promote when argument is database', function () {
227227
`))
228228
})
229229

230+
it('promotes the db with a custom attachment name when --as is provided', async function () {
231+
nock('https://api.heroku.com')
232+
.get('/apps/myapp/formation')
233+
.reply(200, [])
234+
.get('/apps/myapp/addon-attachments')
235+
.reply(200, [
236+
{
237+
addon: {name: 'postgres-2'},
238+
name: 'DATABASE',
239+
namespace: null,
240+
},
241+
{
242+
addon: {name: 'postgres-2'},
243+
name: 'RED',
244+
namespace: null,
245+
},
246+
])
247+
.post('/addon-attachments', {
248+
addon: {name: addon.name},
249+
app: {name: 'myapp'},
250+
confirm: 'myapp',
251+
name: 'CUSTOM_DB',
252+
namespace: null,
253+
})
254+
.reply(201)
255+
256+
const {stderr} = await runCommand(Cmd, [
257+
'--app',
258+
'myapp',
259+
'--as',
260+
'CUSTOM_DB',
261+
'DATABASE',
262+
])
263+
expectOutput(stderr, heredoc(`
264+
Ensuring an alternate alias for existing ⛁ DATABASE_URL... RED_URL
265+
Promoting ⛁ ${addon.name} to ⛁ DATABASE_URL on ⬢ myapp... done
266+
`))
267+
})
268+
230269
it('does not promote the db if is already is DATABASE', async function () {
231270
nock('https://api.heroku.com')
232271
.get('/apps/myapp/formation')

test/unit/commands/redis/promote.unit.test.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,43 @@ describe('heroku redis:promote', function () {
4949
expect(stderr).to.equal('')
5050
})
5151

52+
it('# promotes with a custom attachment name when --as is provided', async function () {
53+
const app = nock('https://api.heroku.com:443')
54+
.get('/apps/example/addons')
55+
.reply(200, [
56+
{
57+
addon_service: {name: 'heroku-redis'},
58+
config_vars: ['REDIS_URL', 'HEROKU_REDIS_SILVER_URL'],
59+
name: 'redis-silver-haiku',
60+
}, {
61+
addon_service: {name: 'heroku-redis'},
62+
config_vars: ['HEROKU_REDIS_GOLD_URL'],
63+
name: 'redis-gold-haiku',
64+
},
65+
])
66+
67+
const attach = nock('https://api.heroku.com:443')
68+
.post('/addon-attachments', {
69+
addon: {name: 'redis-gold-haiku'},
70+
app: {name: 'example'},
71+
confirm: 'example',
72+
name: 'CUSTOM_REDIS',
73+
})
74+
.reply(200, {})
75+
76+
const {stderr, stdout} = await runCommand(Cmd, [
77+
'--app',
78+
'example',
79+
'--as',
80+
'CUSTOM_REDIS',
81+
'redis-gold-haiku',
82+
])
83+
app.done()
84+
attach.done()
85+
expect(stdout).to.equal('Promoting redis-gold-haiku to REDIS_URL on example\n')
86+
expect(stderr).to.equal('')
87+
})
88+
5289
it('# promotes and replaces attachment of existing REDIS_URL if necessary', async function () {
5390
const app = nock('https://api.heroku.com:443')
5491
.get('/apps/example/addons')

0 commit comments

Comments
 (0)