Skip to content

Commit 5ffac14

Browse files
feat(monorepo): prefix output with package name (#1378)
* feat(monorepo): prefix output with package name * chore: move piping subprocess output to util fn * chore: fix lint errors * chore: revert releaseRc changes * chore: apply changes to monorepo-only releaseRc * chore: fix default noPrefix values * chore: replace noPrefix with prefix * chore: ensure prefix written on every newline * test: add tests * chore: refactor * chore: fix tests * chore: add dt types * chore: windows is so broken * chore: add dependency to monorepo test fixture --------- Co-authored-by: achingbrain <[email protected]>
1 parent 308b23e commit 5ffac14

File tree

15 files changed

+271
-21
lines changed

15 files changed

+271
-21
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@
303303
"source-map-support": "^0.5.20",
304304
"strip-bom": "^5.0.0",
305305
"strip-json-comments": "^5.0.0",
306+
"strong-log-transformer": "^2.1.0",
306307
"tempy": "^3.0.0",
307308
"typedoc": "^0.25.0",
308309
"typedoc-plugin-mdn-links": "^3.0.3",
@@ -330,6 +331,7 @@
330331
"@types/prompt": "^1.1.2",
331332
"@types/proper-lockfile": "^4.1.1",
332333
"@types/semver": "^7.3.4",
334+
"@types/strong-log-transformer": "^1.0.2",
333335
"@types/update-notifier": "^6.0.1",
334336
"@types/yargs": "^17.0.0",
335337
"electron": "^27.0.2"

src/cmds/exec.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ export default {
2929
type: 'boolean',
3030
describe: '',
3131
default: userConfig.exec.bail
32+
},
33+
prefix: {
34+
type: 'boolean',
35+
describe: 'Prefix output with the package name',
36+
default: userConfig.exec.prefix
3237
}
3338
})
3439
},

src/cmds/release-rc.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ export default {
3535
type: 'string',
3636
describe: 'Which tag to publish the version as',
3737
default: userConfig.releaseRc.tag
38+
},
39+
prefix: {
40+
type: 'boolean',
41+
describe: 'Prefix output with the package name',
42+
default: userConfig.releaseRc.prefix
3843
}
3944
})
4045
},

src/cmds/run.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ export default {
2929
type: 'boolean',
3030
describe: '',
3131
default: userConfig.run.bail
32+
},
33+
prefix: {
34+
type: 'boolean',
35+
describe: 'Prefix output with the package name',
36+
default: userConfig.run.prefix
3237
}
3338
})
3439
.positional('script', {

src/config/user.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -108,18 +108,21 @@ const defaults = {
108108
},
109109
releaseRc: {
110110
retries: 5,
111-
tag: 'next'
111+
tag: 'next',
112+
prefix: true
112113
},
113114
// dependency check cmd options
114115
dependencyCheck: {
115116
unused: false,
116117
ignore: []
117118
},
118119
exec: {
119-
bail: true
120+
bail: true,
121+
prefix: true
120122
},
121123
run: {
122-
bail: true
124+
bail: true,
125+
prefix: true
123126
}
124127
}
125128

src/exec.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { execa } from 'execa'
22
import kleur from 'kleur'
3-
import { everyMonorepoProject } from './utils.js'
3+
import { everyMonorepoProject, pipeOutput } from './utils.js'
44

55
/**
66
* @typedef {import("./types").GlobalOptions} GlobalOptions
@@ -12,18 +12,18 @@ export default {
1212
* @param {GlobalOptions & ExecOptions & { command: string }} ctx
1313
*/
1414
async run (ctx) {
15-
const forwardOptions = ctx['--'] ? ctx['--'] : []
15+
const forwardArgs = ctx['--'] ? ctx['--'] : []
1616

1717
await everyMonorepoProject(process.cwd(), async (project) => {
1818
console.info('') // eslint-disable-line no-console
19-
console.info(kleur.grey(`${project.manifest.name} > ${ctx.command} ${forwardOptions.join(' ')}`)) // eslint-disable-line no-console
19+
console.info(kleur.grey(`${project.manifest.name}:`), `> ${ctx.command}${forwardArgs.length > 0 ? ` ${forwardArgs.join(' ')}` : ''}`) // eslint-disable-line no-console
2020

2121
try {
22-
await execa(ctx.command, forwardOptions, {
23-
cwd: project.dir,
24-
stderr: 'inherit',
25-
stdout: 'inherit'
22+
const subprocess = execa(ctx.command, forwardArgs, {
23+
cwd: project.dir
2624
})
25+
pipeOutput(subprocess, project.manifest.name, ctx.prefix)
26+
await subprocess
2727
} catch (/** @type {any} */ err) {
2828
if (ctx.bail !== false) {
2929
throw err

src/release-rc.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { execa } from 'execa'
55
import fs from 'fs-extra'
66
import Listr from 'listr'
77
import retry from 'p-retry'
8-
import { isMonorepoParent, pkg, everyMonorepoProject } from './utils.js'
8+
import { isMonorepoParent, pkg, everyMonorepoProject, pipeOutput } from './utils.js'
99

1010
/**
1111
* @typedef {import("./types").GlobalOptions} GlobalOptions
@@ -78,12 +78,11 @@ async function releaseMonorepoRcs (commit, ctx) {
7878
console.info(`npm publish --tag ${ctx.tag} --dry-run ${!process.env.CI}`)
7979

8080
try {
81-
await execa('npm', ['publish', '--tag', ctx.tag, '--dry-run', `${!process.env.CI}`], {
82-
stdout: 'inherit',
83-
stderr: 'inherit',
84-
cwd: project.dir,
85-
all: true
81+
const subprocess = execa('npm', ['publish', '--tag', ctx.tag, '--dry-run', `${!process.env.CI}`], {
82+
cwd: project.dir
8683
})
84+
pipeOutput(subprocess, project.manifest.name, ctx.prefix)
85+
await subprocess
8786
} catch (/** @type {any} */ err) {
8887
if (err.all?.includes('You cannot publish over the previously published versions')) {
8988
// this appears to be a bug in npm, sometimes you publish successfully but it also

src/run.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { execa } from 'execa'
22
import kleur from 'kleur'
3-
import { everyMonorepoProject } from './utils.js'
3+
import { everyMonorepoProject, pipeOutput } from './utils.js'
44

55
/**
66
* @typedef {import("./types").GlobalOptions} GlobalOptions
@@ -27,14 +27,15 @@ export default {
2727
}
2828

2929
console.info('') // eslint-disable-line no-console
30-
console.info(kleur.grey(`${project.manifest.name} > npm run ${script} ${forwardArgs.join(' ')}`)) // eslint-disable-line no-console
30+
console.info(kleur.grey(`${project.manifest.name}:`), `npm run ${script}${forwardArgs.length > 0 ? ` ${forwardArgs.join(' ')}` : ''}`) // eslint-disable-line no-console
3131

3232
try {
33-
await execa('npm', ['run', script, ...forwardArgs], {
33+
const subprocess = execa('npm', ['run', script, ...forwardArgs], {
3434
cwd: project.dir,
35-
stderr: 'inherit',
36-
stdout: 'inherit'
35+
stdio: ['ignore', 'pipe', 'pipe']
3736
})
37+
pipeOutput(subprocess, project.manifest.name, ctx.prefix)
38+
await subprocess
3839
} catch (/** @type {any} */ err) {
3940
if (ctx.bail !== false) {
4041
throw err

src/types.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,11 @@ interface ReleaseRcOptions {
336336
* Which tag to publish the rc as
337337
*/
338338
tag: string
339+
340+
/**
341+
* Prefix output with the package name
342+
*/
343+
prefix?: boolean
339344
}
340345

341346
interface DependencyCheckOptions {
@@ -355,13 +360,23 @@ interface ExecOptions {
355360
* If false, the command will continue to be run in other packages
356361
*/
357362
bail?: boolean
363+
364+
/**
365+
* Prefix output with the package name
366+
*/
367+
prefix?: boolean
358368
}
359369

360370
interface RunOptions {
361371
/**
362372
* If false, the command will continue to be run in other packages
363373
*/
364374
bail?: boolean
375+
376+
/**
377+
* Prefix output with the package name
378+
*/
379+
prefix?: boolean
365380
}
366381

367382
export type {

src/utils.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import lockfile from 'proper-lockfile'
2222
import { readPackageUpSync } from 'read-pkg-up'
2323
import stripBom from 'strip-bom'
2424
import stripComments from 'strip-json-comments'
25+
import logTransformer from 'strong-log-transformer'
2526

2627
const __dirname = path.dirname(fileURLToPath(import.meta.url))
2728
const EnvPaths = envPaths('aegir', { suffix: '' })
@@ -575,3 +576,30 @@ export const formatCode = (code, errorLines) => {
575576
})
576577
return ' ' + lines.join('\n ')
577578
}
579+
580+
/**
581+
* Pipe subprocess output to stdio
582+
*
583+
* @param {import('execa').ExecaChildProcess} subprocess
584+
* @param {string} prefix
585+
* @param {boolean} [shouldPrefix]
586+
*/
587+
export function pipeOutput (subprocess, prefix, shouldPrefix) {
588+
if (shouldPrefix === false) {
589+
subprocess.stdout?.pipe(process.stdout)
590+
subprocess.stderr?.pipe(process.stderr)
591+
592+
return
593+
}
594+
595+
const stdoutOpts = {
596+
tag: kleur.gray(`${prefix}:`)
597+
}
598+
599+
const stderrOpts = {
600+
tag: kleur.gray(`${prefix}:`)
601+
}
602+
603+
subprocess.stdout?.pipe(logTransformer(stdoutOpts)).pipe(process.stdout)
604+
subprocess.stderr?.pipe(logTransformer(stderrOpts)).pipe(process.stderr)
605+
}

test/exec.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/* eslint-env mocha */
2+
3+
import { createRequire } from 'module'
4+
import os from 'os'
5+
import { execa } from 'execa'
6+
import { expect } from '../utils/chai.js'
7+
import { setUpProject } from './utils/set-up-project.js'
8+
9+
const require = createRequire(import.meta.url)
10+
const bin = require.resolve('../src/index.js')
11+
12+
describe('exec', () => {
13+
if (os.platform() === 'win32') {
14+
describe.skip('Skipping tests on windows because commands are different', () => {})
15+
16+
return
17+
}
18+
19+
let projectDir = ''
20+
21+
before(async () => {
22+
projectDir = await setUpProject('a-monorepo')
23+
})
24+
25+
it('should prefix monorepo output with the project name', async function () {
26+
this.timeout(120 * 1000) // slow ci is slow
27+
28+
const result = await execa(bin, ['exec', 'ls'], {
29+
cwd: projectDir
30+
})
31+
32+
expect(result.stdout).to.equal(`
33+
another-workspace-project: > ls
34+
another-workspace-project: package.json
35+
another-workspace-project: src
36+
another-workspace-project: tsconfig.json
37+
another-workspace-project: typedoc.json
38+
39+
a-workspace-project: > ls
40+
a-workspace-project: package.json
41+
a-workspace-project: src
42+
a-workspace-project: tsconfig.json
43+
a-workspace-project: typedoc.json`)
44+
})
45+
46+
it('should not prefix monorepo output with the project name with --no-prefix', async function () {
47+
this.timeout(120 * 1000) // slow ci is slow
48+
49+
const result = await execa(bin, ['exec', '--no-prefix', 'ls'], {
50+
cwd: projectDir
51+
})
52+
53+
expect(result.stdout).to.equal(`
54+
another-workspace-project: > ls
55+
package.json
56+
src
57+
tsconfig.json
58+
typedoc.json
59+
60+
a-workspace-project: > ls
61+
package.json
62+
src
63+
tsconfig.json
64+
typedoc.json`)
65+
})
66+
67+
it('should not prefix monorepo output with the project name with --prefix=false', async function () {
68+
this.timeout(120 * 1000) // slow ci is slow
69+
70+
const result = await execa(bin, ['exec', '--prefix=false', 'ls'], {
71+
cwd: projectDir
72+
})
73+
74+
expect(result.stdout).to.equal(`
75+
another-workspace-project: > ls
76+
package.json
77+
src
78+
tsconfig.json
79+
typedoc.json
80+
81+
a-workspace-project: > ls
82+
package.json
83+
src
84+
tsconfig.json
85+
typedoc.json`)
86+
})
87+
})

test/fixtures/projects/a-monorepo/packages/a-workspace-project/package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,12 @@
88
"import": "./src/index.js"
99
}
1010
},
11+
"dependencies": {
12+
"another-workspace-project": "1.0.0"
13+
},
14+
"scripts": {
15+
"test": "echo very test"
16+
},
1117
"type": "module",
1218
"author": "",
1319
"license": "ISC"

test/fixtures/projects/a-monorepo/packages/another-workspace-project/package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
"import": "./src/index.js"
99
}
1010
},
11+
"scripts": {
12+
"test": "echo very test"
13+
},
1114
"type": "module",
1215
"author": "",
1316
"license": "ISC"

test/node.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import './fixtures.js'
55
import './dependants.js'
66
import './document-check.js'
77
import './dependency-check.js'
8+
import './exec.js'
9+
import './run.js'
810
import './utils/echo-server.js'
911
import './utils/get-port.js'
1012
import './config/user.js'

0 commit comments

Comments
 (0)