diff --git a/lib/workers/branch/lock-files.js b/lib/workers/branch/lock-files.js index fc01f65e84a6796a1f5be6e862328d74bc41b7c3..c7f78385f6b2ac8d13ad5df83619a9386e8401d5 100644 --- a/lib/workers/branch/lock-files.js +++ b/lib/workers/branch/lock-files.js @@ -69,9 +69,17 @@ function determineLockFileDirs(config) { } } - // If yarn workspaces are in use, then we need to generate yarn.lock from root dir - if (config.updatedPackageFiles.length && config.hasYarnWorkspaces) { - yarnLockFileDirs.push(path.dirname('package.json')); + // If yarn workspaces are in use, then we need to generate yarn.lock from the workspaces dir + if (config.updatedPackageFiles.length && config.workspaceDir) { + const updatedPackageFileNames = config.updatedPackageFiles.map(p => p.name); + for (const packageFile of config.packageFiles) { + if ( + updatedPackageFileNames.includes(packageFile.packageFile) && + packageFile.workspaceDir && + !yarnLockFileDirs.includes(packageFile.workspaceDir) + ) + yarnLockFileDirs.push(packageFile.workspaceDir); + } } return { yarnLockFileDirs, packageLockFileDirs }; diff --git a/lib/workers/repository/apis.js b/lib/workers/repository/apis.js index b4498493b41e04f9d4b54ea53db6be99cf649e51..8a0645c39e7d81d4b3b5a7c511faad8ef45a1a1e 100644 --- a/lib/workers/repository/apis.js +++ b/lib/workers/repository/apis.js @@ -42,20 +42,30 @@ async function checkMonorepos(input) { const { logger } = config; config.monorepoPackages = []; // yarn workspaces - if (config.hasYarnWorkspaces) { - let workspaces = []; - for (const packageFile of config.packageFiles) { - if (packageFile.packageFile === 'package.json') { - ({ workspaces } = packageFile.content); - } + let workspaces = []; + for (const packageFile of config.packageFiles) { + if ( + packageFile.packageFile && + packageFile.packageFile.endsWith('package.json') && + packageFile.content.workspaces + ) { + config.workspaceDir = path.dirname(packageFile.packageFile); + logger.info(`workspaceDir=${config.workspaceDir}`); + ({ workspaces } = packageFile.content); } - logger.debug({ workspaces }, 'workspaces'); - for (const workspace of workspaces) { - for (const packageFile of config.packageFiles) { - if (minimatch(path.dirname(packageFile.packageFile), workspace)) { - const depName = packageFile.content.name; - config.monorepoPackages.push(depName); - } + } + if (workspaces.length) { + logger.debug({ workspaces }, 'Found yarn workspaces'); + } + for (const workspace of workspaces) { + const basePath = path.join(config.workspaceDir, workspace); + logger.info(`basePath=${basePath}`); + for (const packageFile of config.packageFiles) { + if (minimatch(path.dirname(packageFile.packageFile), basePath)) { + logger.info(`Matched ${packageFile.packageFile}`); + const depName = packageFile.content.name; + config.monorepoPackages.push(depName); + packageFile.workspaceDir = config.workspaceDir; } } } @@ -315,14 +325,6 @@ async function resolvePackageFiles(inputConfig) { delete packageFile.yarnrc; } if (packageFile.content) { - // check for workspaces - if ( - packageFile.packageFile === 'package.json' && - packageFile.content.workspaces - ) { - logger.info('Found yarn workspaces configuration'); - config.hasYarnWorkspaces = true; - } // hoist renovate config if exists if (packageFile.content.renovate) { config.hasPackageJsonRenovateConfig = true; diff --git a/test/workers/branch/lock-files.spec.js b/test/workers/branch/lock-files.spec.js index 60d479d1f07f2a8cb98ec83116f2a76357ab08ea..4a7fad10ff987403fe78292474b81e690722bb39 100644 --- a/test/workers/branch/lock-files.spec.js +++ b/test/workers/branch/lock-files.spec.js @@ -150,7 +150,7 @@ describe('workers/branch/lock-files', () => { expect(res).toMatchSnapshot(); }); it('returns root directory if using yarn workspaces', () => { - config.hasYarnWorkspaces = true; + config.workspaceDir = '.'; config.upgrades = [{}]; config.packageFiles = [ { @@ -159,6 +159,7 @@ describe('workers/branch/lock-files', () => { }, { packageFile: 'backend/package.json', + workspaceDir: '.', }, ]; config.updatedPackageFiles = [ diff --git a/test/workers/repository/__snapshots__/apis.spec.js.snap b/test/workers/repository/__snapshots__/apis.spec.js.snap index add163b03e078922f182189f41fa3ba6927d518e..90daea4501746ea09b6ef2e47d1970454b99f343 100644 --- a/test/workers/repository/__snapshots__/apis.spec.js.snap +++ b/test/workers/repository/__snapshots__/apis.spec.js.snap @@ -14,6 +14,13 @@ Array [ ] `; +exports[`workers/repository/apis checkMonorepos adds nested yarn workspaces 1`] = ` +Array [ + "@a/b", + "@a/c", +] +`; + exports[`workers/repository/apis checkMonorepos adds yarn workspaces 1`] = ` Array [ "@a/b", @@ -21,6 +28,8 @@ Array [ ] `; +exports[`workers/repository/apis checkMonorepos skips if no lerna packages 1`] = `Array []`; + exports[`workers/repository/apis detectPackageFiles(config) adds package files to object 1`] = ` Array [ "package.json", diff --git a/test/workers/repository/apis.spec.js b/test/workers/repository/apis.spec.js index 6b0b2e0b4e2ab54ed8982d1d79d05dddad97f5fc..3db1f3c716436cf7de32d293b9946137f786ccff 100644 --- a/test/workers/repository/apis.spec.js +++ b/test/workers/repository/apis.spec.js @@ -57,7 +57,6 @@ describe('workers/repository/apis', () => { }; }); it('adds yarn workspaces', async () => { - config.hasYarnWorkspaces = true; config.packageFiles = [ { packageFile: 'package.json', @@ -75,10 +74,29 @@ describe('workers/repository/apis', () => { const res = await apis.checkMonorepos(config); expect(res.monorepoPackages).toMatchSnapshot(); }); + it('adds nested yarn workspaces', async () => { + config.packageFiles = [ + { + packageFile: 'frontend/package.json', + content: { workspaces: ['packages/*'] }, + }, + { + packageFile: 'frontend/packages/something/package.json', + content: { name: '@a/b' }, + }, + { + packageFile: 'frontend/packages/something-else/package.json', + content: { name: '@a/c' }, + }, + ]; + const res = await apis.checkMonorepos(config); + expect(res.monorepoPackages).toMatchSnapshot(); + }); it('adds lerna packages', async () => { config.packageFiles = [ { packageFile: 'package.json', + content: {}, }, { packageFile: 'packages/something/package.json', @@ -93,6 +111,17 @@ describe('workers/repository/apis', () => { const res = await apis.checkMonorepos(config); expect(res.monorepoPackages).toMatchSnapshot(); }); + it('skips if no lerna packages', async () => { + config.packageFiles = [ + { + packageFile: 'package.json', + content: {}, + }, + ]; + config.api.getFileJson.mockReturnValue({}); + const res = await apis.checkMonorepos(config); + expect(res.monorepoPackages).toMatchSnapshot(); + }); }); describe('detectSemanticCommits', () => { it('disables semantic commits', async () => { diff --git a/test/workers/repository/index.spec.js b/test/workers/repository/index.spec.js index f6b87e2af86b496516a7271f9a557b86b968ce5b..f653f35bd7221be6ea600661beda4e65adfca91d 100644 --- a/test/workers/repository/index.spec.js +++ b/test/workers/repository/index.spec.js @@ -47,6 +47,7 @@ describe('workers/repository', () => { apis.mergeRenovateJson = jest.fn(input => input); apis.detectPackageFiles = jest.fn(); apis.resolvePackageFiles = jest.fn(input => input); + apis.checkMonorepos = jest.fn(input => input); onboarding.getOnboardingStatus = jest.fn(); onboarding.ensurePr = jest.fn(); upgrades.determineRepoUpgrades = jest.fn(() => []);