Skip to content

Commit d46b239

Browse files
fix: run:inside argument parsing order (#3633)
* fix run:inside argument parsing order and add regression tests for dyno-command mapping * updating test to match expected argument behavior
1 parent d6ff764 commit d46b239

File tree

2 files changed

+64
-12
lines changed

2 files changed

+64
-12
lines changed

src/commands/run/inside.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,21 @@ import debugFactory from 'debug'
66
import tsheredoc from 'tsheredoc'
77

88
import Dyno from '../../lib/run/dyno.js'
9-
import {buildCommandWithLauncher} from '../../lib/run/helpers.js'
9+
import {buildCommandWithLauncher, revertSortedArgs} from '../../lib/run/helpers.js'
1010

1111
const debug = debugFactory('heroku:run:inside')
1212
const heredoc = tsheredoc.default
1313

1414
export default class RunInside extends Command {
1515
static args = {
16-
command: Args.string({
17-
description: 'command to run (Heroku automatically prepends \'launcher\' to the command)',
18-
required: true,
19-
}),
2016
dyno_name: Args.string({
2117
description: 'name of the dyno to run command inside',
2218
required: true,
2319
}),
20+
command: Args.string({
21+
description: 'command to run (Heroku automatically prepends \'launcher\' to the command)',
22+
required: true,
23+
}),
2424
}
2525

2626
static description = 'run a command inside an existing dyno (for Fir-generation apps only)'
@@ -57,13 +57,15 @@ export default class RunInside extends Command {
5757

5858
async run() {
5959
const {args, argv, flags} = await this.parse(RunInside)
60+
const orderedArgs = revertSortedArgs(process.argv, argv as string[])
61+
const commandArgs = orderedArgs.slice(1)
6062

6163
const {dyno_name: dynoName} = args
6264
const {app: appName, 'exit-code': exitCode, listen, 'no-launcher': noLauncher} = flags
6365

6466
const opts = {
6567
app: appName,
66-
command: await buildCommandWithLauncher(this.heroku, appName, argv.slice(1) as string[], noLauncher),
68+
command: await buildCommandWithLauncher(this.heroku, appName, commandArgs, noLauncher),
6769
dyno: dynoName,
6870
'exit-code': exitCode,
6971
heroku: this.heroku,

test/unit/commands/run/inside.unit.test.ts

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,35 @@ import RunInside from '../../../../src/commands/run/inside.js'
55
import runCommand from '../../../helpers/runCommand.js'
66

77
describe('run:inside', function () {
8+
const originalProcessArgv = [...process.argv]
9+
10+
const runWithCliArgv = async (args: string[]) => {
11+
process.argv = [
12+
'/usr/local/bin/node',
13+
'/usr/local/bin/heroku',
14+
'run:inside',
15+
...args,
16+
]
17+
18+
return runCommand(RunInside, args)
19+
}
20+
821
beforeEach(function () {
922
nock.cleanAll()
1023
nock.disableNetConnect()
1124
})
1225

1326
afterEach(function () {
1427
nock.enableNetConnect()
28+
process.argv = [...originalProcessArgv]
1529
})
1630

1731
it('requires a dyno name and command', async function () {
1832
nock('https://api.heroku.com')
1933
.get('/apps/myapp')
2034
.reply(200, {name: 'myapp', stack: {name: 'heroku-20'}})
2135

22-
await runCommand(RunInside, [
36+
await runWithCliArgv([
2337
'--app',
2438
'myapp',
2539
]).catch(error => {
@@ -32,7 +46,10 @@ describe('run:inside', function () {
3246
nock('https://api.heroku.com')
3347
.get('/apps/myapp')
3448
.reply(200, {name: 'myapp', stack: {name: 'heroku-20'}})
35-
.post('/apps/myapp/dynos/web.1')
49+
.post('/apps/myapp/dynos/web.1', body => {
50+
expect(body.command).to.equal('bash')
51+
return true
52+
})
3653
.reply(201, {
3754
attach_url: 'rendezvous://rendezvous.runtime.heroku.com:5000',
3855
command: 'bash',
@@ -45,7 +62,7 @@ describe('run:inside', function () {
4562
updated_at: '2020-01-01T00:00:00Z',
4663
})
4764

48-
await runCommand(RunInside, [
65+
await runWithCliArgv([
4966
'web.1',
5067
'bash',
5168
'--app',
@@ -72,7 +89,7 @@ describe('run:inside', function () {
7289
updated_at: '2020-01-01T00:00:00Z',
7390
})
7491

75-
await runCommand(RunInside, [
92+
await runWithCliArgv([
7693
'web.1',
7794
'false',
7895
'--app',
@@ -88,7 +105,10 @@ describe('run:inside', function () {
88105
nock('https://api.heroku.com')
89106
.get('/apps/myapp')
90107
.reply(200, {name: 'myapp', stack: {name: 'cnb'}})
91-
.post('/apps/myapp/dynos/web.1')
108+
.post('/apps/myapp/dynos/web.1', body => {
109+
expect(body.command).to.equal('bash')
110+
return true
111+
})
92112
.reply(201, {
93113
attach_url: 'rendezvous://rendezvous.runtime.heroku.com:5000',
94114
command: 'bash',
@@ -101,7 +121,7 @@ describe('run:inside', function () {
101121
updated_at: '2020-01-01T00:00:00Z',
102122
})
103123

104-
await runCommand(RunInside, [
124+
await runWithCliArgv([
105125
'web.1',
106126
'bash',
107127
'--app',
@@ -111,4 +131,34 @@ describe('run:inside', function () {
111131
// Expected to fail when trying to connect
112132
})
113133
})
134+
135+
it('prepends launcher by default on cnb apps', async function () {
136+
nock('https://api.heroku.com')
137+
.get('/apps/myapp')
138+
.reply(200, {name: 'myapp', stack: {name: 'cnb'}})
139+
.post('/apps/myapp/dynos/web.1', body => {
140+
expect(body.command).to.equal('launcher bash')
141+
return true
142+
})
143+
.reply(201, {
144+
attach_url: 'rendezvous://rendezvous.runtime.heroku.com:5000',
145+
command: 'launcher bash',
146+
created_at: '2020-01-01T00:00:00Z',
147+
id: '12345678-1234-1234-1234-123456789012',
148+
name: 'web.1',
149+
size: 'basic',
150+
state: 'starting',
151+
type: 'web',
152+
updated_at: '2020-01-01T00:00:00Z',
153+
})
154+
155+
await runWithCliArgv([
156+
'web.1',
157+
'bash',
158+
'--app',
159+
'myapp',
160+
]).catch(() => {
161+
// Expected to fail when trying to connect
162+
})
163+
})
114164
})

0 commit comments

Comments
 (0)