From a39d20f170c038125cd3910e5869ebeacc7de487 Mon Sep 17 00:00:00 2001 From: Michael Malave Date: Wed, 1 Apr 2026 09:51:16 -0700 Subject: [PATCH 01/11] updating to leverage foreman for output formatting --- docs/local.md | 6 ++- src/commands/local/index.ts | 59 +++++++++++++++++---- src/commands/local/run.ts | 13 +++-- src/commands/local/version.ts | 12 ++++- src/lib/local/fork-foreman.ts | 28 ++++++++-- test/unit/commands/local/index.unit.test.ts | 56 +++++++++++++++++++ 6 files changed, 153 insertions(+), 21 deletions(-) diff --git a/docs/local.md b/docs/local.md index fd8646736e..dad4ebd8d4 100644 --- a/docs/local.md +++ b/docs/local.md @@ -14,7 +14,7 @@ run heroku app locally ``` USAGE - $ heroku local [PROCESSNAME] [-e ] [-p ] [-f ] + $ heroku local [PROCESSNAME] [-e ] [-p ] [-f ] [--start-cmd ] ARGUMENTS [PROCESSNAME] name of the process @@ -23,6 +23,7 @@ FLAGS -e, --env= location of env file (defaults to .env) -f, --procfile= use a different Procfile -p, --port= port to listen on + --start-cmd= command to run as web when no Procfile is found DESCRIPTION run heroku app locally @@ -70,7 +71,7 @@ run heroku app locally ``` USAGE - $ heroku local:start [PROCESSNAME] [-e ] [-p ] [-f ] + $ heroku local:start [PROCESSNAME] [-e ] [-p ] [-f ] [--start-cmd ] ARGUMENTS [PROCESSNAME] name of the process @@ -79,6 +80,7 @@ FLAGS -e, --env= location of env file (defaults to .env) -f, --procfile= use a different Procfile -p, --port= port to listen on + --start-cmd= command to run as web when no Procfile is found DESCRIPTION run heroku app locally diff --git a/src/commands/local/index.ts b/src/commands/local/index.ts index b412aa0316..67d291bba7 100644 --- a/src/commands/local/index.ts +++ b/src/commands/local/index.ts @@ -1,8 +1,9 @@ import * as color from '@heroku/heroku-cli-util/color' import {Args, Command, Flags} from '@oclif/core' +import fs from 'fs' import {validateEnvFile} from '../../lib/local/env-file-validator.js' -import {fork as foreman} from '../../lib/local/fork-foreman.js' +import {fork as foreman, isForemanExitError} from '../../lib/local/fork-foreman.js' import {loadProc} from '../../lib/local/load-foreman-procfile.js' export default class Index extends Command { @@ -45,6 +46,13 @@ Start the application specified by a Procfile (defaults to ./Procfile)` description: 'restart process if it dies', hidden: true, }), + 'start-cmd': Flags.string({ + description: 'command to run as web when no Procfile is found', + }), + } + + public hasProcfile(procfilePath: string): boolean { + return fs.existsSync(procfilePath) && fs.statSync(procfilePath).isFile() } // Proxy method to make procfile loading testable @@ -53,8 +61,13 @@ Start the application specified by a Procfile (defaults to ./Procfile)` } async run() { - const execArgv = ['start'] const {args, flags} = await this.parse(Index) + const processName = args.processname + const procfile = flags.procfile || 'Procfile' + const hasProcfile = this.hasProcfile(procfile) + const startCmd = flags['start-cmd'] + const useStartCmd = !hasProcfile && !processName && Boolean(startCmd) + const execArgv = useStartCmd ? ['run'] : ['start'] if (flags.restart) { this.error('--restart is no longer available\nUse forego instead: https://github.com/ddollar/forego') @@ -66,20 +79,48 @@ Start the application specified by a Procfile (defaults to ./Procfile)` const envFile = validateEnvFile(flags.env, this.warn.bind(this)) - if (flags.procfile) execArgv.push('--procfile', flags.procfile) execArgv.push('--env', envFile) - if (flags.port) execArgv.push('--port', flags.port) - if (args.processname) { - execArgv.push(args.processname) - } else { - const procfile = flags.procfile || 'Procfile' + if (flags.port) { + if (useStartCmd) { + this.warn(`The specified port, ${color.label(flags.port)}, is being ignored when using --start-cmd.`) + } else { + execArgv.push('--port', flags.port) + } + } + + if (flags.procfile && hasProcfile) execArgv.push('--procfile', flags.procfile) + + if (processName) { + execArgv.push(processName) + } else if (hasProcfile) { + if (startCmd) { + this.warn(`The specified start command, ${color.label(startCmd)}, is being ignored.`) + } + const procHash = this.loadProcfile(procfile) const processes = Object.keys(procHash).filter(x => x !== 'release') execArgv.push(processes.join(',')) + } else { + if (!startCmd) { + this.error( + `No ${procfile} found.\nAdd a Procfile to add process types.\nhttps://devcenter.heroku.com/articles/procfile\nOr specify a start command with --start-cmd.`, + ) + } + + const resolvedStartCmd = startCmd ?? '' + execArgv.push('--', 'sh', '-c', resolvedStartCmd) } - await this.runForeman(execArgv) + try { + await this.runForeman(execArgv) + } catch (error: unknown) { + if (isForemanExitError(error)) { + this.exit(error.exitCode) + } + + throw error + } } // Proxy method to make foreman calls testable diff --git a/src/commands/local/run.ts b/src/commands/local/run.ts index d7696b363a..cbcba9e9ba 100644 --- a/src/commands/local/run.ts +++ b/src/commands/local/run.ts @@ -1,9 +1,8 @@ import * as color from '@heroku/heroku-cli-util/color' - import {Command, Flags} from '@oclif/core' import {validateEnvFile} from '../../lib/local/env-file-validator.js' -import {fork as foreman} from '../../lib/local/fork-foreman.js' +import {fork as foreman, isForemanExitError} from '../../lib/local/fork-foreman.js' import {revertSortedArgs} from '../../lib/run/helpers.js' export default class Run extends Command { @@ -44,6 +43,14 @@ export default class Run extends Command { execArgv.push('--') // disable node-foreman flag parsing execArgv.push(...commandArgs as string[]) // eslint-disable-line unicorn/no-array-push-push - await foreman(execArgv) + try { + await foreman(execArgv) + } catch (error: unknown) { + if (isForemanExitError(error)) { + this.exit(error.exitCode) + } + + throw error + } } } diff --git a/src/commands/local/version.ts b/src/commands/local/version.ts index b6aeb18630..392f078da8 100644 --- a/src/commands/local/version.ts +++ b/src/commands/local/version.ts @@ -1,6 +1,6 @@ import {Command} from '@oclif/core' -import {fork as foreman} from '../../lib/local/fork-foreman.js' +import {fork as foreman, isForemanExitError} from '../../lib/local/fork-foreman.js' export default class Version extends Command { static description = 'display node-foreman version' @@ -9,6 +9,14 @@ export default class Version extends Command { await this.parse(Version) const execArgv = ['--version'] - await foreman(execArgv) + try { + await foreman(execArgv) + } catch (error: unknown) { + if (isForemanExitError(error)) { + this.exit(error.exitCode) + } + + throw error + } } } diff --git a/src/lib/local/fork-foreman.ts b/src/lib/local/fork-foreman.ts index f74cac649a..1773bbc8af 100644 --- a/src/lib/local/fork-foreman.ts +++ b/src/lib/local/fork-foreman.ts @@ -1,21 +1,39 @@ -import {ux} from '@oclif/core/ux' import {fork as forkChildProcess} from 'child_process' import * as fs from 'fs' import * as path from 'path' import {fileURLToPath} from 'url' +export class ForemanExitError extends Error { + public exitCode: number + + public constructor(exitCode: number) { + super(`Foreman exited with code ${exitCode}`) + this.exitCode = exitCode + this.name = 'ForemanExitError' + } +} + export function fork(argv: string[]): Promise { const script = getForemanScriptPath() const nf = forkChildProcess(script, argv, {stdio: 'inherit'}) - return new Promise(resolve => { - nf.on('exit', (code: number) => { - if (code !== 0) ux.exit(code) - resolve() + return new Promise((resolve, reject) => { + nf.on('error', reject) + nf.on('exit', (code: null | number) => { + if (code === 0) { + resolve() + return + } + + reject(new ForemanExitError(code ?? 1)) }) }) } +export function isForemanExitError(error: unknown): error is ForemanExitError { + return error instanceof ForemanExitError +} + // depending if this is being ran before or after compilation // we need to check for `.ts` and `.js` extensions and use // the appropriate one. diff --git a/test/unit/commands/local/index.unit.test.ts b/test/unit/commands/local/index.unit.test.ts index 1f263b2773..b31c9bd657 100644 --- a/test/unit/commands/local/index.unit.test.ts +++ b/test/unit/commands/local/index.unit.test.ts @@ -39,6 +39,16 @@ describe('local', function () { expect(error.message).to.not.contain('Invalid flag') } }) + + it('accepts --start-cmd flag', async function () { + sandbox.stub(Local.prototype, 'runForeman').resolves() + sandbox.stub(Local.prototype, 'hasProcfile').returns(false) + const {error} = await runCommand(Local, ['--start-cmd', 'npm start']) + // If command parsing reaches execution, the flag was accepted + if (error) { + expect(error.message).to.not.contain('Invalid flag') + } + }) }) describe('error handling', function () { @@ -60,10 +70,14 @@ describe('local', function () { describe('argument construction', function () { let runForemanStub: sinon.SinonStub + let hasProcfileStub: sinon.SinonStub + let loadProcfileStub: sinon.SinonStub let originalCwd: string beforeEach(function () { runForemanStub = sandbox.stub(Local.prototype, 'runForeman').resolves() + hasProcfileStub = sandbox.stub(Local.prototype, 'hasProcfile').returns(true) + loadProcfileStub = sandbox.stub(Local.prototype, 'loadProcfile').returns({web: 'npm start'}) originalCwd = process.cwd() }) @@ -110,6 +124,8 @@ describe('local', function () { it('uses default procfile when none specified', async function () { // Change to fixtures directory so the test can find the default Procfile process.chdir('test/fixtures/local') + hasProcfileStub.restore() + loadProcfileStub.restore() // This test verifies that when no procfile is specified, it defaults to 'Procfile' // and calls loadProc with the default path @@ -130,6 +146,7 @@ describe('local', function () { beforeEach(function () { sandbox = sinon.createSandbox() runForemanStub = sandbox.stub(Local.prototype, 'runForeman').resolves() + sandbox.stub(Local.prototype, 'hasProcfile').returns(true) }) afterEach(function () { @@ -200,6 +217,45 @@ describe('local', function () { }) }) + describe('start command precedence', function () { + let runForemanStub: sinon.SinonStub + let hasProcfileStub: sinon.SinonStub + let loadProcfileStub: sinon.SinonStub + + beforeEach(function () { + runForemanStub = sandbox.stub(Local.prototype, 'runForeman').resolves() + hasProcfileStub = sandbox.stub(Local.prototype, 'hasProcfile').returns(true) + loadProcfileStub = sandbox.stub(Local.prototype, 'loadProcfile').returns({web: 'node server.js'}) + }) + + it('uses procfile and warns when both procfile and --start-cmd are provided', async function () { + const {stderr} = await runCommand(Local, ['--start-cmd', 'npm start']) + + expect(loadProcfileStub.calledOnce).to.be.true + expect(runForemanStub.calledOnce).to.be.true + expect(stderr).to.contain('is being ignored') + }) + + it('uses --start-cmd when no procfile is found', async function () { + hasProcfileStub.returns(false) + await runCommand(Local, ['--start-cmd', 'python app.py']) + + expect(loadProcfileStub.called).to.be.false + expect(runForemanStub.calledOnce).to.be.true + expect(runForemanStub.firstCall.args[0]).to.deep.equal(['run', '--env', '.env', '--', 'sh', '-c', 'python app.py']) + }) + + it('errors when no procfile and no --start-cmd are provided', async function () { + hasProcfileStub.returns(false) + const {error} = await runCommand(Local) + + expect(error?.message).to.equal( + 'No Procfile found.\nAdd a Procfile to add process types.\nhttps://devcenter.heroku.com/articles/procfile\nOr specify a start command with --start-cmd.', + ) + expect(runForemanStub.called).to.be.false + }) + }) + describe('environment file integration', function () { let sandbox: ReturnType let runForemanStub: sinon.SinonStub From 51bb946623c5e1fd75399585b3856e3f08ffe06f Mon Sep 17 00:00:00 2001 From: Michael Malave Date: Wed, 1 Apr 2026 10:26:47 -0700 Subject: [PATCH 02/11] small text update for description --- docs/local.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/local.md b/docs/local.md index dad4ebd8d4..b9c7994421 100644 --- a/docs/local.md +++ b/docs/local.md @@ -23,7 +23,7 @@ FLAGS -e, --env= location of env file (defaults to .env) -f, --procfile= use a different Procfile -p, --port= port to listen on - --start-cmd= command to run as web when no Procfile is found + --start-cmd= command to run as web when no Procfile is present DESCRIPTION run heroku app locally @@ -80,7 +80,7 @@ FLAGS -e, --env= location of env file (defaults to .env) -f, --procfile= use a different Procfile -p, --port= port to listen on - --start-cmd= command to run as web when no Procfile is found + --start-cmd= command to run as web when no Procfile is present DESCRIPTION run heroku app locally From f6afd063560ca1edde44d2a3134082630e233e46 Mon Sep 17 00:00:00 2001 From: Michael Malave Date: Thu, 2 Apr 2026 11:55:05 -0700 Subject: [PATCH 03/11] Apply suggestion from @heicheng18 Co-authored-by: Helen Cheng <48834224+heicheng18@users.noreply.github.com> Signed-off-by: Michael Malave --- docs/local.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/local.md b/docs/local.md index b9c7994421..118685b395 100644 --- a/docs/local.md +++ b/docs/local.md @@ -23,7 +23,7 @@ FLAGS -e, --env= location of env file (defaults to .env) -f, --procfile= use a different Procfile -p, --port= port to listen on - --start-cmd= command to run as web when no Procfile is present + --start-cmd= command to run as a web process when there’s no Procfile DESCRIPTION run heroku app locally From c6013ae349f255cbaa934f5d9d22c9d7b91db1fc Mon Sep 17 00:00:00 2001 From: Michael Malave Date: Thu, 2 Apr 2026 11:55:16 -0700 Subject: [PATCH 04/11] Apply suggestion from @heicheng18 Co-authored-by: Helen Cheng <48834224+heicheng18@users.noreply.github.com> Signed-off-by: Michael Malave --- docs/local.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/local.md b/docs/local.md index 118685b395..576106b67e 100644 --- a/docs/local.md +++ b/docs/local.md @@ -80,7 +80,7 @@ FLAGS -e, --env= location of env file (defaults to .env) -f, --procfile= use a different Procfile -p, --port= port to listen on - --start-cmd= command to run as web when no Procfile is present + --start-cmd= command to run as a web process when there’s no Procfile DESCRIPTION run heroku app locally From f7d897987fe7d23f81ae0fdb584579a6ec68652f Mon Sep 17 00:00:00 2001 From: Michael Malave Date: Thu, 2 Apr 2026 11:55:26 -0700 Subject: [PATCH 05/11] Apply suggestion from @heicheng18 Co-authored-by: Helen Cheng <48834224+heicheng18@users.noreply.github.com> Signed-off-by: Michael Malave --- src/commands/local/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/local/index.ts b/src/commands/local/index.ts index 67d291bba7..071ab53b33 100644 --- a/src/commands/local/index.ts +++ b/src/commands/local/index.ts @@ -47,7 +47,7 @@ Start the application specified by a Procfile (defaults to ./Procfile)` hidden: true, }), 'start-cmd': Flags.string({ - description: 'command to run as web when no Procfile is found', + description: 'command to run as a web process when there’s no Procfile', }), } From 4297cfa7022c22c9fa304e2886fc7baa72551bfc Mon Sep 17 00:00:00 2001 From: Michael Malave Date: Thu, 2 Apr 2026 11:56:11 -0700 Subject: [PATCH 06/11] Apply suggestion from @heicheng18 Co-authored-by: Helen Cheng <48834224+heicheng18@users.noreply.github.com> Signed-off-by: Michael Malave --- src/commands/local/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/local/index.ts b/src/commands/local/index.ts index 071ab53b33..b66fd1a7f6 100644 --- a/src/commands/local/index.ts +++ b/src/commands/local/index.ts @@ -83,7 +83,7 @@ Start the application specified by a Procfile (defaults to ./Procfile)` if (flags.port) { if (useStartCmd) { - this.warn(`The specified port, ${color.label(flags.port)}, is being ignored when using --start-cmd.`) + this.warn(`Using the --start-cmd flag ignores the specified port, {color.label(flags.port)}.`) } else { execArgv.push('--port', flags.port) } From ad75f4ad2795d4513c67de8c3efa65bad899e807 Mon Sep 17 00:00:00 2001 From: Michael Malave Date: Thu, 2 Apr 2026 11:56:29 -0700 Subject: [PATCH 07/11] Apply suggestion from @heicheng18 Co-authored-by: Helen Cheng <48834224+heicheng18@users.noreply.github.com> Signed-off-by: Michael Malave --- src/commands/local/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/local/index.ts b/src/commands/local/index.ts index b66fd1a7f6..709d6f86cd 100644 --- a/src/commands/local/index.ts +++ b/src/commands/local/index.ts @@ -95,7 +95,7 @@ Start the application specified by a Procfile (defaults to ./Procfile)` execArgv.push(processName) } else if (hasProcfile) { if (startCmd) { - this.warn(`The specified start command, ${color.label(startCmd)}, is being ignored.`) + this.warn(`Using the --procfile flag ignores the specified start command, ${color.label(startCmd)}.`) } const procHash = this.loadProcfile(procfile) From 046b9afe05bb9f496ac1a68f4d5bfd6b312de8ba Mon Sep 17 00:00:00 2001 From: Michael Malave Date: Thu, 2 Apr 2026 11:56:47 -0700 Subject: [PATCH 08/11] Apply suggestion from @heicheng18 Co-authored-by: Helen Cheng <48834224+heicheng18@users.noreply.github.com> Signed-off-by: Michael Malave --- src/commands/local/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/local/index.ts b/src/commands/local/index.ts index 709d6f86cd..da6d25fe2f 100644 --- a/src/commands/local/index.ts +++ b/src/commands/local/index.ts @@ -104,7 +104,7 @@ Start the application specified by a Procfile (defaults to ./Procfile)` } else { if (!startCmd) { this.error( - `No ${procfile} found.\nAdd a Procfile to add process types.\nhttps://devcenter.heroku.com/articles/procfile\nOr specify a start command with --start-cmd.`, + `Your app doesn’t have a ${procfile}.\nAdd a Procfile to add process types. \nSee https://devcenter.heroku.com/articles/procfile.\nOr specify a start command with --start-cmd.`, ) } From 38d61c55e4d72f1fa59fadb86ed59da35eb990f5 Mon Sep 17 00:00:00 2001 From: Michael Malave Date: Thu, 2 Apr 2026 11:57:00 -0700 Subject: [PATCH 09/11] Apply suggestion from @heicheng18 Co-authored-by: Helen Cheng <48834224+heicheng18@users.noreply.github.com> Signed-off-by: Michael Malave --- test/unit/commands/local/index.unit.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/unit/commands/local/index.unit.test.ts b/test/unit/commands/local/index.unit.test.ts index b31c9bd657..c8932421f6 100644 --- a/test/unit/commands/local/index.unit.test.ts +++ b/test/unit/commands/local/index.unit.test.ts @@ -250,7 +250,7 @@ describe('local', function () { const {error} = await runCommand(Local) expect(error?.message).to.equal( - 'No Procfile found.\nAdd a Procfile to add process types.\nhttps://devcenter.heroku.com/articles/procfile\nOr specify a start command with --start-cmd.', + 'Your app doesn’t have a ${procfile}.\nAdd a Procfile to add process types. \nSee https://devcenter.heroku.com/articles/procfile.\nOr specify a start command with --start-cmd.', ) expect(runForemanStub.called).to.be.false }) From 388f504727fd8077f7b2735e196279ac3d8e8aaa Mon Sep 17 00:00:00 2001 From: Michael Malave Date: Thu, 2 Apr 2026 12:28:36 -0700 Subject: [PATCH 10/11] fixes applied to tests following cx updates --- test/unit/commands/local/index.unit.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/unit/commands/local/index.unit.test.ts b/test/unit/commands/local/index.unit.test.ts index c8932421f6..fd293b8214 100644 --- a/test/unit/commands/local/index.unit.test.ts +++ b/test/unit/commands/local/index.unit.test.ts @@ -233,7 +233,7 @@ describe('local', function () { expect(loadProcfileStub.calledOnce).to.be.true expect(runForemanStub.calledOnce).to.be.true - expect(stderr).to.contain('is being ignored') + expect(stderr).to.contain('Using the --procfile flag ignores the specified start command') }) it('uses --start-cmd when no procfile is found', async function () { @@ -250,7 +250,7 @@ describe('local', function () { const {error} = await runCommand(Local) expect(error?.message).to.equal( - 'Your app doesn’t have a ${procfile}.\nAdd a Procfile to add process types. \nSee https://devcenter.heroku.com/articles/procfile.\nOr specify a start command with --start-cmd.', + 'Your app doesn’t have a Procfile.\nAdd a Procfile to add process types. \nSee https://devcenter.heroku.com/articles/procfile.\nOr specify a start command with --start-cmd.', ) expect(runForemanStub.called).to.be.false }) From 4073cf73c31b281be6cca28332f89ce46209b5e7 Mon Sep 17 00:00:00 2001 From: Michael Malave Date: Thu, 2 Apr 2026 12:34:03 -0700 Subject: [PATCH 11/11] merge in main and lint fix --- src/commands/local/index.ts | 8 ++++---- test/unit/commands/local/index.unit.test.ts | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/commands/local/index.ts b/src/commands/local/index.ts index da6d25fe2f..2231cbf653 100644 --- a/src/commands/local/index.ts +++ b/src/commands/local/index.ts @@ -47,7 +47,7 @@ Start the application specified by a Procfile (defaults to ./Procfile)` hidden: true, }), 'start-cmd': Flags.string({ - description: 'command to run as a web process when there’s no Procfile', + description: 'command to run as web when no Procfile is present', }), } @@ -83,7 +83,7 @@ Start the application specified by a Procfile (defaults to ./Procfile)` if (flags.port) { if (useStartCmd) { - this.warn(`Using the --start-cmd flag ignores the specified port, {color.label(flags.port)}.`) + this.warn('The specified port, ' + color.label(flags.port) + ', is being ignored when using --start-cmd.') } else { execArgv.push('--port', flags.port) } @@ -95,7 +95,7 @@ Start the application specified by a Procfile (defaults to ./Procfile)` execArgv.push(processName) } else if (hasProcfile) { if (startCmd) { - this.warn(`Using the --procfile flag ignores the specified start command, ${color.label(startCmd)}.`) + this.warn(`The specified start command, ${color.label(startCmd)}, is being ignored.`) } const procHash = this.loadProcfile(procfile) @@ -104,7 +104,7 @@ Start the application specified by a Procfile (defaults to ./Procfile)` } else { if (!startCmd) { this.error( - `Your app doesn’t have a ${procfile}.\nAdd a Procfile to add process types. \nSee https://devcenter.heroku.com/articles/procfile.\nOr specify a start command with --start-cmd.`, + `No ${procfile} found.\nAdd a Procfile to add process types.\nhttps://devcenter.heroku.com/articles/procfile\nOr specify a start command with --start-cmd.`, ) } diff --git a/test/unit/commands/local/index.unit.test.ts b/test/unit/commands/local/index.unit.test.ts index fd293b8214..b31c9bd657 100644 --- a/test/unit/commands/local/index.unit.test.ts +++ b/test/unit/commands/local/index.unit.test.ts @@ -233,7 +233,7 @@ describe('local', function () { expect(loadProcfileStub.calledOnce).to.be.true expect(runForemanStub.calledOnce).to.be.true - expect(stderr).to.contain('Using the --procfile flag ignores the specified start command') + expect(stderr).to.contain('is being ignored') }) it('uses --start-cmd when no procfile is found', async function () { @@ -250,7 +250,7 @@ describe('local', function () { const {error} = await runCommand(Local) expect(error?.message).to.equal( - 'Your app doesn’t have a Procfile.\nAdd a Procfile to add process types. \nSee https://devcenter.heroku.com/articles/procfile.\nOr specify a start command with --start-cmd.', + 'No Procfile found.\nAdd a Procfile to add process types.\nhttps://devcenter.heroku.com/articles/procfile\nOr specify a start command with --start-cmd.', ) expect(runForemanStub.called).to.be.false })