From 3e5edb19f01e8bf3581437e6face4a9d26aea478 Mon Sep 17 00:00:00 2001 From: John Coburn Date: Thu, 18 Jun 2026 16:13:19 -0500 Subject: [PATCH 1/9] decouple from yarn classic --- lib/cli/global-dirs.js | 2 +- lib/cli/stripes-core.js | 6 ++-- lib/package-manager.js | 76 +++++++++++++++++++++++++++++++++++++++++ lib/yarn.js | 53 +++------------------------- 4 files changed, 84 insertions(+), 53 deletions(-) create mode 100644 lib/package-manager.js diff --git a/lib/cli/global-dirs.js b/lib/cli/global-dirs.js index 0208eaae..3e2ed548 100644 --- a/lib/cli/global-dirs.js +++ b/lib/cli/global-dirs.js @@ -10,7 +10,7 @@ function isYarnVersion(version) { logger.log('Yarn version', yarnVersion); return semver.satisfies(yarnVersion, version); } catch (err) { - logger.error('Unable to determine Yarn version.', err); + logger.log('Unable to determine Yarn version.', err); return false; } } diff --git a/lib/cli/stripes-core.js b/lib/cli/stripes-core.js index 266e9c0b..0c436396 100644 --- a/lib/cli/stripes-core.js +++ b/lib/cli/stripes-core.js @@ -58,9 +58,9 @@ module.exports = class StripesCore { } getCoreModulePath(moduleId) { - const coreModulePath = (this.corePath === this.coreAlias) - ? path.join(this.corePath, moduleId) - : resolveFrom(this.corePath, `@folio/stripes-webpack/${moduleId}`); + const coreModulePath = (this.corePath.includes('node_modules')) + ? resolveFrom(this.corePath, `@folio/stripes-webpack/${moduleId}`) + : path.join(this.corePath, moduleId); return coreModulePath; } diff --git a/lib/package-manager.js b/lib/package-manager.js new file mode 100644 index 00000000..9475f4f4 --- /dev/null +++ b/lib/package-manager.js @@ -0,0 +1,76 @@ +const childProcess = require('child_process'); +const path = require('path'); +const fs = require('fs'); + +function hasCommand(cmd) { + try { + const v = childProcess.execSync(`${cmd} --version`, { encoding: 'utf8' }).trim(); + // simple check that command exists and returns something + return !!v; + } catch (e) { + return false; + } +} + +function detect(projectDir) { + // Env override + const env = process.env.STRIPES_PKG_MANAGER; + if (env) return env; + + // Prefer pnpm if a lockfile exists nearby + try { + const pnpmLock = path.join(projectDir || process.cwd(), 'pnpm-lock.yaml'); + if (fs.existsSync(pnpmLock) && hasCommand('pnpm')) return 'pnpm'; + } catch (e) { + // ignore + } + + if (hasCommand('pnpm')) return 'pnpm'; + if (hasCommand('yarn')) return 'yarn'; + if (hasCommand('npm')) return 'npm'; + + // default to npm if nothing else + return 'npm'; +} + +function execCmd(cmd, args, options) { + return new Promise((resolve, reject) => { + const full = `${cmd} ${args.join(' ')}`.trim(); + const p = childProcess.exec(full, options, (error) => { + if (error) return reject(error); + resolve({ isInstalled: true, appDir: options && options.cwd }); + }); + if (p && p.stdout) p.stdout.on('data', d => console.log(` ${d.toString().trim()}`)); + if (p && p.stderr) p.stderr.on('data', d => console.error(` ${d.toString().trim()}`)); + }); +} + +function install(projectDir) { + const pm = detect(projectDir); + console.log(`Using package manager: ${pm}`); + if (pm === 'pnpm') return execCmd('pnpm', ['install', '--frozen-lockfile'], { cwd: projectDir }); + if (pm === 'yarn') return execCmd('yarn', [], { cwd: projectDir }); + return execCmd('npm', ['install'], { cwd: projectDir }); +} + +function add(projectDir, packageName, isDev) { + const pm = detect(projectDir); + console.log(`Using package manager: ${pm}`); + const pkgs = [].concat(packageName).join(' '); + if (pm === 'pnpm') { + const flag = isDev ? ['-D'] : []; + return execCmd('pnpm', ['add'].concat(flag).concat([pkgs]), { cwd: projectDir }); + } + if (pm === 'yarn') { + const flag = isDev ? '--dev' : ''; + return execCmd('yarn', ['add', flag, pkgs].filter(Boolean), { cwd: projectDir }); + } + const flag = isDev ? ['--save-dev'] : ['--save']; + return execCmd('npm', ['install'].concat(flag).concat([pkgs]), { cwd: projectDir }); +} + +module.exports = { + detect, + install, + add, +}; diff --git a/lib/yarn.js b/lib/yarn.js index cf09a320..2bcf451b 100644 --- a/lib/yarn.js +++ b/lib/yarn.js @@ -1,53 +1,8 @@ -const childProcess = require('child_process'); - -function runYarn(options) { - return new Promise((resolve, reject) => { - const installProcess = childProcess.exec('yarn', options, (error) => { - if (error) { - reject(error); - return; - } - resolve({ isInstalled: true, appDir: options.cwd }); - }); - installProcess.stdout.on('data', data => console.log(` ${data.trim()}`)); - }); -} - -function yarnAdd(packageName, isDevDep, options) { - const pkgs = [].concat(packageName).join(' '); - const flag = isDevDep ? '--dev' : ''; - - return new Promise((resolve, reject) => { - const installProcess = childProcess.exec(`yarn add ${flag} ${pkgs}`, options, (error) => { - if (error) { - reject(error); - return; - } - resolve({ isInstalled: true, appDir: options.cwd }); - }); - installProcess.stdout.on('data', data => console.log(` ${data.trim()}`)); - }); -} - -// Above method does not capture full yarn output, but is a lot quieter -// TODO: Offer option to toggle between the two - -// function runYarn(options) { -// options.stdio = 'inherit'; -// return new Promise((resolve, reject) => { -// childProcess.spawn('yarn', [], options) -// .on('exit', (error) => { -// if (error) { -// reject(error); -// } -// resolve({ isInstalled: true, appDir: options.cwd }); -// }); -// }); -// } +const packageManager = require('./package-manager'); function install(projectDir) { console.log(` Directory "${projectDir}"`); - return runYarn({ cwd: projectDir }) + return packageManager.install(projectDir) .catch((err) => { console.error('Something went wrong while attempting to use Yarn.'); console.info(err); @@ -56,9 +11,9 @@ function install(projectDir) { function add(projectDir, packageName, isDev) { console.log(` Directory "${projectDir}"`); - return yarnAdd(packageName, isDev, { cwd: projectDir }) + return packageManager.add(projectDir, packageName, isDev) .catch((err) => { - console.error('Something went wrong while attempting to use Yarn.'); + console.error('Something went wrong while attempting to add package via package manager.'); console.info(err); }); } From a8094af4fbcf9b750d1ee491db0070cafe6b97fb Mon Sep 17 00:00:00 2001 From: John Coburn Date: Mon, 22 Jun 2026 09:59:50 -0500 Subject: [PATCH 2/9] sonardad cleanup --- lib/package-manager.js | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/lib/package-manager.js b/lib/package-manager.js index 9475f4f4..5d7cf251 100644 --- a/lib/package-manager.js +++ b/lib/package-manager.js @@ -1,6 +1,6 @@ -const childProcess = require('child_process'); -const path = require('path'); -const fs = require('fs'); +const childProcess = require('node:child_process'); +const path = require('node:path'); +const fs = require('node:fs'); function hasCommand(cmd) { try { @@ -8,7 +8,7 @@ function hasCommand(cmd) { // simple check that command exists and returns something return !!v; } catch (e) { - return false; + throw new Error(`There was an error in stripes-cli initialization: Command not found - ${cmd}`); } } @@ -22,7 +22,7 @@ function detect(projectDir) { const pnpmLock = path.join(projectDir || process.cwd(), 'pnpm-lock.yaml'); if (fs.existsSync(pnpmLock) && hasCommand('pnpm')) return 'pnpm'; } catch (e) { - // ignore + throw new Error('There was an error in stripes-cli initialization: Unable to detect package manager.'); } if (hasCommand('pnpm')) return 'pnpm'; @@ -38,17 +38,18 @@ function execCmd(cmd, args, options) { const full = `${cmd} ${args.join(' ')}`.trim(); const p = childProcess.exec(full, options, (error) => { if (error) return reject(error); - resolve({ isInstalled: true, appDir: options && options.cwd }); + resolve({ isInstalled: true, appDir: options?.cwd }); + return undefined; }); - if (p && p.stdout) p.stdout.on('data', d => console.log(` ${d.toString().trim()}`)); - if (p && p.stderr) p.stderr.on('data', d => console.error(` ${d.toString().trim()}`)); + if (p?.stdout) p.stdout.on('data', d => console.log(` ${d.toString().trim()}`)); + if (p?.stderr) p.stderr.on('data', d => console.error(` ${d.toString().trim()}`)); }); } function install(projectDir) { const pm = detect(projectDir); console.log(`Using package manager: ${pm}`); - if (pm === 'pnpm') return execCmd('pnpm', ['install', '--frozen-lockfile'], { cwd: projectDir }); + if (pm === 'pnpm') return execCmd('pnpm', ['install'], { cwd: projectDir }); if (pm === 'yarn') return execCmd('yarn', [], { cwd: projectDir }); return execCmd('npm', ['install'], { cwd: projectDir }); } @@ -56,7 +57,7 @@ function install(projectDir) { function add(projectDir, packageName, isDev) { const pm = detect(projectDir); console.log(`Using package manager: ${pm}`); - const pkgs = [].concat(packageName).join(' '); + const pkgs = packageName.flat().join(' '); if (pm === 'pnpm') { const flag = isDev ? ['-D'] : []; return execCmd('pnpm', ['add'].concat(flag).concat([pkgs]), { cwd: projectDir }); From ae9c6e388cf653c04eaf0871ad5a92cb1b160731 Mon Sep 17 00:00:00 2001 From: John Coburn Date: Mon, 22 Jun 2026 14:00:50 -0500 Subject: [PATCH 3/9] throw errors --- lib/package-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/package-manager.js b/lib/package-manager.js index 5d7cf251..2a6c440a 100644 --- a/lib/package-manager.js +++ b/lib/package-manager.js @@ -22,7 +22,7 @@ function detect(projectDir) { const pnpmLock = path.join(projectDir || process.cwd(), 'pnpm-lock.yaml'); if (fs.existsSync(pnpmLock) && hasCommand('pnpm')) return 'pnpm'; } catch (e) { - throw new Error('There was an error in stripes-cli initialization: Unable to detect package manager.'); + throw new Error('There was an error in stripes-cli initialization: Unable to detect package manager.', { cause: e }); } if (hasCommand('pnpm')) return 'pnpm'; From a6928ef518cb0f9d8bac06ec9cb089e9f5b7b91c Mon Sep 17 00:00:00 2001 From: John Coburn Date: Mon, 22 Jun 2026 14:05:09 -0500 Subject: [PATCH 4/9] actually throw error for the command check also --- lib/package-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/package-manager.js b/lib/package-manager.js index 2a6c440a..b24bf164 100644 --- a/lib/package-manager.js +++ b/lib/package-manager.js @@ -8,7 +8,7 @@ function hasCommand(cmd) { // simple check that command exists and returns something return !!v; } catch (e) { - throw new Error(`There was an error in stripes-cli initialization: Command not found - ${cmd}`); + throw new Error(`There was an error in stripes-cli initialization: Command not found - ${cmd}`, { cause: e }); } } From d1d7fbcecd734daf7b58508c361c55db7e36b740 Mon Sep 17 00:00:00 2001 From: John Coburn Date: Tue, 23 Jun 2026 08:48:38 -0500 Subject: [PATCH 5/9] add conditional to prevent unexpected logger errors in global-directory handling --- lib/cli/global-dirs.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/cli/global-dirs.js b/lib/cli/global-dirs.js index 3e2ed548..a00ca2e1 100644 --- a/lib/cli/global-dirs.js +++ b/lib/cli/global-dirs.js @@ -10,7 +10,8 @@ function isYarnVersion(version) { logger.log('Yarn version', yarnVersion); return semver.satisfies(yarnVersion, version); } catch (err) { - logger.log('Unable to determine Yarn version.', err); + const logError = logger?.error ? logger.error : console.error; + logError('Unable to determine Yarn version.', err?.message ? err.message : err); return false; } } From 656c4da00882e3506ec5840ec10d1fa9a268a8db Mon Sep 17 00:00:00 2001 From: John Coburn Date: Wed, 1 Jul 2026 15:36:40 -0500 Subject: [PATCH 6/9] conform package-manager.js in error scenarios, add tests --- lib/package-manager.js | 2 +- test/lib/package-manager.spec.js | 203 +++++++++++++++++++++++++++++++ test/lib/yarn.spec.js | 60 +++++++++ 3 files changed, 264 insertions(+), 1 deletion(-) create mode 100644 test/lib/package-manager.spec.js create mode 100644 test/lib/yarn.spec.js diff --git a/lib/package-manager.js b/lib/package-manager.js index b24bf164..686120f1 100644 --- a/lib/package-manager.js +++ b/lib/package-manager.js @@ -8,7 +8,7 @@ function hasCommand(cmd) { // simple check that command exists and returns something return !!v; } catch (e) { - throw new Error(`There was an error in stripes-cli initialization: Command not found - ${cmd}`, { cause: e }); + return false; } } diff --git a/test/lib/package-manager.spec.js b/test/lib/package-manager.spec.js new file mode 100644 index 00000000..a4ab727b --- /dev/null +++ b/test/lib/package-manager.spec.js @@ -0,0 +1,203 @@ +const expect = require('chai').expect; +const childProcess = require('node:child_process'); +const fs = require('node:fs'); +const { EventEmitter } = require('node:events'); + +const packageManager = require('../../lib/package-manager'); + +// Stubs childProcess.exec to simulate a successful or failed command, +// emitting stdout/stderr asynchronously so listeners attached by execCmd +// are in place before data arrives. +function stubExec(sandbox, { error, stdout, stderr } = {}) { + return sandbox.stub(childProcess, 'exec').callsFake((command, options, callback) => { + const proc = new EventEmitter(); + proc.stdout = new EventEmitter(); + proc.stderr = new EventEmitter(); + setImmediate(() => { + if (stdout) proc.stdout.emit('data', stdout); + if (stderr) proc.stderr.emit('data', stderr); + callback(error || null); + }); + return proc; + }); +} + +describe('The package-manager service', function () { + let originalEnv; + + beforeEach(function () { + originalEnv = process.env.STRIPES_PKG_MANAGER; + delete process.env.STRIPES_PKG_MANAGER; + this.sandbox.stub(console, 'log'); + this.sandbox.stub(console, 'error'); + }); + + afterEach(function () { + if (originalEnv === undefined) { + delete process.env.STRIPES_PKG_MANAGER; + } else { + process.env.STRIPES_PKG_MANAGER = originalEnv; + } + }); + + describe('detect', function () { + it('honors the STRIPES_PKG_MANAGER environment variable', function () { + process.env.STRIPES_PKG_MANAGER = 'npm'; + this.sandbox.stub(fs, 'existsSync'); + this.sandbox.stub(childProcess, 'execSync'); + + expect(packageManager.detect('/project')).to.equal('npm'); + expect(fs.existsSync).not.to.have.been.called; + expect(childProcess.execSync).not.to.have.been.called; + }); + + it('prefers pnpm when a pnpm-lock.yaml is present and pnpm is available', function () { + this.sandbox.stub(fs, 'existsSync').returns(true); + this.sandbox.stub(childProcess, 'execSync').returns('8.0.0'); + + expect(packageManager.detect('/project')).to.equal('pnpm'); + expect(childProcess.execSync).to.have.been.calledWithMatch('pnpm --version'); + }); + + it('falls back to yarn when pnpm is not installed', function () { + this.sandbox.stub(fs, 'existsSync').returns(false); + this.sandbox.stub(childProcess, 'execSync').callsFake((cmd) => { + if (cmd.startsWith('pnpm')) throw new Error('command not found: pnpm'); + if (cmd.startsWith('yarn')) return '1.22.0'; + return ''; + }); + + expect(packageManager.detect('/project')).to.equal('yarn'); + }); + + it('falls back to npm when neither pnpm nor yarn is installed', function () { + this.sandbox.stub(fs, 'existsSync').returns(false); + this.sandbox.stub(childProcess, 'execSync').callsFake((cmd) => { + if (cmd.startsWith('npm')) return '8.0.0'; + throw new Error('command not found'); + }); + + expect(packageManager.detect('/project')).to.equal('npm'); + }); + + it('defaults to npm when no other package manager is detected', function () { + this.sandbox.stub(fs, 'existsSync').returns(false); + this.sandbox.stub(childProcess, 'execSync').returns(''); + + expect(packageManager.detect('/project')).to.equal('npm'); + }); + + it('wraps errors encountered while probing for a pnpm lockfile', function () { + this.sandbox.stub(fs, 'existsSync').throws(new Error('disk error')); + + expect(() => packageManager.detect('/project')).to.throw('Unable to detect package manager'); + }); + }); + + describe('install', function () { + it('installs with pnpm when pnpm is detected', function () { + process.env.STRIPES_PKG_MANAGER = 'pnpm'; + const exec = stubExec(this.sandbox); + + return packageManager.install('/project').then((result) => { + expect(exec).to.have.been.calledWithMatch('pnpm install', { cwd: '/project' }); + expect(result).to.eql({ isInstalled: true, appDir: '/project' }); + }); + }); + + it('installs with yarn when yarn is detected', function () { + process.env.STRIPES_PKG_MANAGER = 'yarn'; + const exec = stubExec(this.sandbox); + + return packageManager.install('/project').then(() => { + expect(exec).to.have.been.calledWithMatch('yarn', { cwd: '/project' }); + }); + }); + + it('installs with npm by default', function () { + process.env.STRIPES_PKG_MANAGER = 'npm'; + const exec = stubExec(this.sandbox); + + return packageManager.install('/project').then(() => { + expect(exec).to.have.been.calledWithMatch('npm install', { cwd: '/project' }); + }); + }); + + it('logs stdout and stderr from the child process', function () { + process.env.STRIPES_PKG_MANAGER = 'npm'; + stubExec(this.sandbox, { stdout: 'installing...', stderr: 'a warning' }); + + return packageManager.install('/project').then(() => { + expect(console.log).to.have.been.calledWithMatch('installing...'); + expect(console.error).to.have.been.calledWithMatch('a warning'); + }); + }); + + it('rejects when the child process fails', function () { + process.env.STRIPES_PKG_MANAGER = 'npm'; + const failure = new Error('command failed'); + stubExec(this.sandbox, { error: failure }); + + return packageManager.install('/project').then( + () => { throw new Error('expected install to reject'); }, + (err) => { expect(err).to.equal(failure); } + ); + }); + }); + + describe('add', function () { + it('adds a dependency with pnpm, using the -D flag for dev dependencies', function () { + process.env.STRIPES_PKG_MANAGER = 'pnpm'; + const exec = stubExec(this.sandbox); + + return packageManager.add('/project', ['lodash'], true).then(() => { + expect(exec).to.have.been.calledWithMatch('pnpm add -D lodash', { cwd: '/project' }); + }); + }); + + it('adds a dependency with yarn, using the --dev flag for dev dependencies', function () { + process.env.STRIPES_PKG_MANAGER = 'yarn'; + const exec = stubExec(this.sandbox); + + return packageManager.add('/project', ['lodash'], true).then(() => { + expect(exec).to.have.been.calledWithMatch('yarn add --dev lodash', { cwd: '/project' }); + }); + }); + + it('adds a dependency with yarn, omitting the flag for non-dev dependencies', function () { + process.env.STRIPES_PKG_MANAGER = 'yarn'; + const exec = stubExec(this.sandbox); + + return packageManager.add('/project', ['lodash'], false).then(() => { + expect(exec).to.have.been.calledWithMatch('yarn add lodash', { cwd: '/project' }); + }); + }); + + it('adds a dependency with npm, using --save-dev for dev dependencies', function () { + process.env.STRIPES_PKG_MANAGER = 'npm'; + const exec = stubExec(this.sandbox); + + return packageManager.add('/project', ['lodash'], true).then(() => { + expect(exec).to.have.been.calledWithMatch('npm install --save-dev lodash', { cwd: '/project' }); + }); + }); + + it('adds a dependency with npm, using --save by default', function () { + process.env.STRIPES_PKG_MANAGER = 'npm'; + const exec = stubExec(this.sandbox); + + return packageManager.add('/project', ['lodash'], false).then(() => { + expect(exec).to.have.been.calledWithMatch('npm install --save lodash', { cwd: '/project' }); + }); + }); + + it('flattens nested package name arrays', function () { + process.env.STRIPES_PKG_MANAGER = 'npm'; + const exec = stubExec(this.sandbox); + + return packageManager.add('/project', [['lodash', 'chalk']], false).then(() => { + expect(exec).to.have.been.calledWithMatch('npm install --save lodash chalk', { cwd: '/project' }); + }); + }); + }); +}); diff --git a/test/lib/yarn.spec.js b/test/lib/yarn.spec.js new file mode 100644 index 00000000..0465e6f3 --- /dev/null +++ b/test/lib/yarn.spec.js @@ -0,0 +1,60 @@ +const expect = require('chai').expect; + +const packageManager = require('../../lib/package-manager'); +const yarn = require('../../lib/yarn'); + +describe('The yarn service', function () { + beforeEach(function () { + this.sandbox.stub(console, 'log'); + this.sandbox.stub(console, 'error'); + this.sandbox.stub(console, 'info'); + }); + + describe('install', function () { + it('delegates to the package manager service', function () { + const result = { isInstalled: true, appDir: '/path/to/project' }; + this.sandbox.stub(packageManager, 'install').resolves(result); + + return yarn.install('/path/to/project').then((res) => { + expect(packageManager.install).to.have.been.calledWith('/path/to/project'); + expect(res).to.equal(result); + expect(console.log).to.have.been.calledWithMatch('/path/to/project'); + }); + }); + + it('reports and swallows an error from the package manager service', function () { + const error = new Error('boom'); + this.sandbox.stub(packageManager, 'install').rejects(error); + + return yarn.install('/path/to/project').then((res) => { + expect(res).to.be.undefined; + expect(console.error).to.have.been.calledWithMatch('Something went wrong while attempting to use Yarn.'); + expect(console.info).to.have.been.calledWith(error); + }); + }); + }); + + describe('add', function () { + it('delegates to the package manager service', function () { + const result = { isInstalled: true, appDir: '/path/to/project' }; + this.sandbox.stub(packageManager, 'add').resolves(result); + + return yarn.add('/path/to/project', ['lodash'], true).then((res) => { + expect(packageManager.add).to.have.been.calledWith('/path/to/project', ['lodash'], true); + expect(res).to.equal(result); + expect(console.log).to.have.been.calledWithMatch('/path/to/project'); + }); + }); + + it('reports and swallows an error from the package manager service', function () { + const error = new Error('boom'); + this.sandbox.stub(packageManager, 'add').rejects(error); + + return yarn.add('/path/to/project', ['lodash'], false).then((res) => { + expect(res).to.be.undefined; + expect(console.error).to.have.been.calledWithMatch('Something went wrong while attempting to add package via package manager.'); + expect(console.info).to.have.been.calledWith(error); + }); + }); + }); +}); From 1237f78af433939c7a1d1dea762c782fa3798f8e Mon Sep 17 00:00:00 2001 From: John Coburn Date: Thu, 2 Jul 2026 08:27:10 -0500 Subject: [PATCH 7/9] conform for sonar-dad --- lib/package-manager.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/package-manager.js b/lib/package-manager.js index 686120f1..f6992f0c 100644 --- a/lib/package-manager.js +++ b/lib/package-manager.js @@ -1,6 +1,7 @@ const childProcess = require('node:child_process'); const path = require('node:path'); const fs = require('node:fs'); +const logger = require('./cli/logger')('package-manager'); function hasCommand(cmd) { try { @@ -8,6 +9,7 @@ function hasCommand(cmd) { // simple check that command exists and returns something return !!v; } catch (e) { + logger.log(`Unable to determine ${cmd} version.`, e?.message ? e.message : e); return false; } } From adfcd03b63197f294a3440aba272f20921423049 Mon Sep 17 00:00:00 2001 From: John Coburn Date: Thu, 2 Jul 2026 08:47:56 -0500 Subject: [PATCH 8/9] try the coverage command --- .github/workflows/ui.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ui.yml b/.github/workflows/ui.yml index d505ef46..e41b76f3 100644 --- a/.github/workflows/ui.yml +++ b/.github/workflows/ui.yml @@ -11,7 +11,7 @@ jobs: secrets: inherit with: jest-enabled: true - jest-test-command: yarn run test + jest-test-command: yarn run test:coverage sonar-sources: ./lib compile-translations: false generate-module-descriptor: false From 2859ba7cb65c07c11f4d392b7a99fc815a99b023 Mon Sep 17 00:00:00 2001 From: John Coburn Date: Thu, 2 Jul 2026 10:43:18 -0500 Subject: [PATCH 9/9] point coverage upload at the location --- .github/workflows/ui.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ui.yml b/.github/workflows/ui.yml index e41b76f3..80ecac98 100644 --- a/.github/workflows/ui.yml +++ b/.github/workflows/ui.yml @@ -12,6 +12,7 @@ jobs: with: jest-enabled: true jest-test-command: yarn run test:coverage + jest-coverage-report-dir: artifacts/coverage sonar-sources: ./lib compile-translations: false generate-module-descriptor: false