diff --git a/lib/api/github.js b/lib/api/github.js index f47cfb6861365a2a19d4c4930a0f43efbc59f9dc..036c188b079d474d2ea887387878d1c29ef0775d 100644 --- a/lib/api/github.js +++ b/lib/api/github.js @@ -35,6 +35,7 @@ module.exports = { updatePr, mergePr, // file + getSubDirectories, commitFilesToBranch, getFile, getFileContent, @@ -602,6 +603,18 @@ async function getFileJson(filePath, branchName) { return fileJson; } +async function getSubDirectories(path) { + logger.trace(`getSubDirectories(path=${path})`); + const res = await ghGot(`repos/${config.repoName}/contents/${path}`); + const directoryList = []; + res.body.forEach(item => { + if (item.type === 'dir') { + directoryList.push(item.name); + } + }); + return directoryList; +} + // Add a new commit, create branch if not existing async function commitFilesToBranch( branchName, diff --git a/lib/api/gitlab.js b/lib/api/gitlab.js index 568755a7f6ecd0dde2b5ab54016cc113f168e7ab..ecce630629a390f2e455de12b670c676c3d3ca8f 100644 --- a/lib/api/gitlab.js +++ b/lib/api/gitlab.js @@ -28,6 +28,7 @@ module.exports = { updatePr, mergePr, // file + getSubDirectories, commitFilesToBranch, getFile, getFileContent, @@ -436,6 +437,20 @@ async function updateFile(branchName, filePath, fileContents, message) { await glGot.put(url, opts); } +async function getSubDirectories(path) { + logger.trace(`getSubDirectories(path=${path})`); + const res = await glGot( + `projects/${config.repoName}/repository/tree?path=${path}` + ); + const directoryList = []; + res.body.forEach(item => { + if (item.type === 'tree') { + directoryList.push(item.name); + } + }); + return directoryList; +} + // Add a new commit, create branch if not existing async function commitFilesToBranch( branchName, diff --git a/lib/workers/dep-type/index.js b/lib/workers/dep-type/index.js index a3d653a8fac62442ba1663fe6183f1fb35951b5f..746ba1c70e54ecaa2c2ba79789ee35d032b13e67 100644 --- a/lib/workers/dep-type/index.js +++ b/lib/workers/dep-type/index.js @@ -26,9 +26,14 @@ async function renovateDepType(packageContent, config) { logger.debug(`currentDeps length is ${currentDeps.length}`); logger.debug({ currentDeps }, `currentDeps`); // Filter out ignored dependencies - const filteredDeps = currentDeps.filter( + let filteredDeps = currentDeps.filter( dependency => config.ignoreDeps.indexOf(dependency.depName) === -1 ); + if (config.lernaPackages) { + filteredDeps = filteredDeps.filter( + dependency => config.lernaPackages.indexOf(dependency.depName) === -1 + ); + } logger.debug(`filteredDeps length is ${filteredDeps.length}`); logger.debug({ filteredDeps }, `filteredDeps`); // Obtain full config for each dependency diff --git a/lib/workers/repository/apis.js b/lib/workers/repository/apis.js index 266dad516142d6b5cfebb7ad3859d24b822647b6..d558eca8485bf3773f17eb641e05d417b986155d 100644 --- a/lib/workers/repository/apis.js +++ b/lib/workers/repository/apis.js @@ -10,6 +10,7 @@ module.exports = { setNpmrc, initApis, mergeRenovateJson, + checkForLerna, detectPackageFiles, }; @@ -28,6 +29,19 @@ async function setNpmrc(config) { } } +async function checkForLerna(config) { + const lernaJson = await config.api.getFileContent('lerna.json'); + if (!lernaJson) { + return {}; + } + config.logger.debug('Found lerna config'); + const lernaPackages = await config.api.getSubDirectories('packages'); + if (lernaPackages.length === 0) { + return {}; + } + return { lernaPackages }; +} + async function initApis(inputConfig, token) { function getPlatformApi(platform) { if (platform === 'github') { @@ -48,6 +62,8 @@ async function initApis(inputConfig, token) { ); // Check for presence of .npmrc in repository Object.assign(config, platformConfig); + const lernaConfig = await module.exports.checkForLerna(config); + Object.assign(config, lernaConfig); await module.exports.setNpmrc(config); return config; } diff --git a/test/api/__snapshots__/github.spec.js.snap b/test/api/__snapshots__/github.spec.js.snap index b87fdc7ff754ea2bad84d96d1fdb658b2cca90a5..a4459f8fe5a1de178d00ce328bbd99ab491ccf6f 100644 --- a/test/api/__snapshots__/github.spec.js.snap +++ b/test/api/__snapshots__/github.spec.js.snap @@ -908,6 +908,34 @@ Array [ ] `; +exports[`api/github getSubDirectories(path) should return subdirectories 1`] = ` +Array [ + Array [ + "repos/some/repo", + ], + Array [ + "repos/some/repo/git/refs/heads/master", + ], + Array [ + "repos/some/repo/branches/master/protection/required_status_checks", + Object { + "headers": Object { + "accept": "application/vnd.github.loki-preview+json", + }, + }, + ], + Array [ + "repos/some/repo/contents/some-path", + ], +] +`; + +exports[`api/github getSubDirectories(path) should return subdirectories 2`] = ` +Array [ + "a", +] +`; + exports[`api/github initRepo should detect repoForceRebase 1`] = ` Object { "repoForceRebase": true, diff --git a/test/api/__snapshots__/gitlab.spec.js.snap b/test/api/__snapshots__/gitlab.spec.js.snap index eb2b7dce456b52a5dbd6f2455b911cc149736154..4471d3836068beb18400f9c94049be461f006d61 100644 --- a/test/api/__snapshots__/gitlab.spec.js.snap +++ b/test/api/__snapshots__/gitlab.spec.js.snap @@ -85,6 +85,29 @@ Array [ ] `; +exports[`api/gitlab createFile(branchName, filePath, fileContents, message) getSubDirectories(path) should return subdirectories 1`] = ` +Array [ + Array [ + "projects/owned", + ], + Array [ + "projects/some%2Frepo", + ], + Array [ + "user", + ], + Array [ + "projects/some%2Frepo/repository/tree?path=some-path", + ], +] +`; + +exports[`api/gitlab createFile(branchName, filePath, fileContents, message) getSubDirectories(path) should return subdirectories 2`] = ` +Array [ + "a", +] +`; + exports[`api/gitlab createFile(branchName, filePath, fileContents, message) updateFile(branchName, filePath, fileContents, message) creates file with v3 1`] = ` Array [ Array [ diff --git a/test/api/github.spec.js b/test/api/github.spec.js index dbf992b5ffe4cc1fb8c74da7c199be828b4d1f39..4aa8f16b0f53385fb9edf011af1e580178221705 100644 --- a/test/api/github.spec.js +++ b/test/api/github.spec.js @@ -1291,6 +1291,18 @@ describe('api/github', () => { expect(content).toBeNull(); }); }); + describe('getSubDirectories(path)', () => { + it('should return subdirectories', async () => { + await initRepo('some/repo', 'token'); + ghGot.mockImplementationOnce(() => ({ + body: [{ type: 'dir', name: 'a' }, { type: 'file', name: 'b' }], + })); + const dirList = await github.getSubDirectories('some-path'); + expect(ghGot.mock.calls).toMatchSnapshot(); + expect(dirList).toHaveLength(1); + expect(dirList).toMatchSnapshot(); + }); + }); describe('commitFilesToBranch(branchName, files, message, parentBranch)', () => { beforeEach(async () => { await initRepo('some/repo', 'token'); diff --git a/test/api/gitlab.spec.js b/test/api/gitlab.spec.js index 7082b9acb00885892ac374a466d6df19dfe6c607..48813649d750c3ef9f2a04c55059db2c5947e654 100644 --- a/test/api/gitlab.spec.js +++ b/test/api/gitlab.spec.js @@ -639,6 +639,18 @@ describe('api/gitlab', () => { expect(glGot.post.mock.calls[0][1].body.branch_name).toBeDefined(); }); }); + describe('getSubDirectories(path)', () => { + it('should return subdirectories', async () => { + await initRepo('some/repo', 'token'); + glGot.mockImplementationOnce(() => ({ + body: [{ type: 'tree', name: 'a' }, { type: 'file', name: 'b' }], + })); + const dirList = await gitlab.getSubDirectories('some-path'); + expect(glGot.mock.calls).toMatchSnapshot(); + expect(dirList).toHaveLength(1); + expect(dirList).toMatchSnapshot(); + }); + }); describe('commitFilesToBranch(branchName, files, message, parentBranch)', () => { it('creates branch', async () => { glGot.mockReturnValueOnce({ statusCode: 404 }); diff --git a/test/workers/dep-type/index.spec.js b/test/workers/dep-type/index.spec.js index de5b480edf8a05e8e5296cbe520c742761fcc04b..cb04b3b5133a75ed630fd1d884faeff4c50b3c14 100644 --- a/test/workers/dep-type/index.spec.js +++ b/test/workers/dep-type/index.spec.js @@ -15,6 +15,7 @@ describe('lib/workers/dep-type/index', () => { beforeEach(() => { config = { ignoreDeps: ['a', 'b'], + lernaPackages: ['e'], }; }); it('returns empty if config is disabled', async () => { @@ -31,6 +32,7 @@ describe('lib/workers/dep-type/index', () => { packageJson.extractDependencies.mockReturnValueOnce([ { depName: 'a' }, { depName: 'b' }, + { depName: 'e' }, ]); const res = await depTypeWorker.renovateDepType({}, config); expect(res).toMatchObject([]); diff --git a/test/workers/repository/__snapshots__/apis.spec.js.snap b/test/workers/repository/__snapshots__/apis.spec.js.snap index 9cfb0ef22e78290f26267da85034e9ce6eac7acf..c7d31a9b5f269acc4f30a3e8d1a217842a6dd79c 100644 --- a/test/workers/repository/__snapshots__/apis.spec.js.snap +++ b/test/workers/repository/__snapshots__/apis.spec.js.snap @@ -1,5 +1,16 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`workers/repository/apis checkForLerna(config) ignores zero length lerna 1`] = `Object {}`; + +exports[`workers/repository/apis checkForLerna(config) returns lerna package names 1`] = ` +Object { + "lernaPackages": Array [ + "a", + "b", + ], +} +`; + 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 c86a30be32251cda4772c31721c2cc80d8945437..3368686add6468f162000f8a49470a416e9d49b4 100644 --- a/test/workers/repository/apis.spec.js +++ b/test/workers/repository/apis.spec.js @@ -42,6 +42,30 @@ describe('workers/repository/apis', () => { await apis.setNpmrc(config); }); }); + describe('checkForLerna(config)', () => { + it('ignores zero length lerna', async () => { + const config = { + api: { + getFileContent: jest.fn(() => 'some content'), + getSubDirectories: jest.fn(() => []), + }, + logger, + }; + const res = await apis.checkForLerna(config); + expect(res).toMatchSnapshot(); + }); + it('returns lerna package names', async () => { + const config = { + api: { + getFileContent: jest.fn(() => 'some content'), + getSubDirectories: jest.fn(() => ['a', 'b']), + }, + logger, + }; + const res = await apis.checkForLerna(config); + expect(res).toMatchSnapshot(); + }); + }); describe('initApis(config)', () => { beforeEach(() => { jest.resetAllMocks();