diff --git a/couchdb/repositories/_design/branch_by_group/views/branch_by_group/map.js b/couchdb/repositories/_design/branch_by_group/views/branch_by_group/map.js index be4f9aa8..1dfac370 100644 --- a/couchdb/repositories/_design/branch_by_group/views/branch_by_group/map.js +++ b/couchdb/repositories/_design/branch_by_group/views/branch_by_group/map.js @@ -3,7 +3,12 @@ function (doc) { if (doc.head && typeof doc.head === 'string') { var branchName = doc.head.split('/') if (branchName[1]) { - emit([doc.repositoryId, branchName[1]]) + var initialGroup = branchName[1].split('initial-') + if (initialGroup[1]) { + emit([doc.repositoryId, initialGroup[1]]) + } else { + emit([doc.repositoryId, branchName[1]]) + } } } } diff --git a/jobs/create-initial-subgroup-branch.js b/jobs/create-initial-subgroup-branch.js index 64aa5e9b..2e1ffdd5 100644 --- a/jobs/create-initial-subgroup-branch.js +++ b/jobs/create-initial-subgroup-branch.js @@ -10,6 +10,8 @@ const { updateRepoDoc } = require('../lib/repository-docs') const githubQueue = require('../lib/github-queue') const upsert = require('../lib/upsert') const { getUpdatedDependenciesForFiles } = require('../utils/initial-branch-utils') +const { getGroupBranchesToDelete } = require('../lib/branches-to-delete') +const deleteBranches = require('../lib/delete-branches') // If we update dependencies, find any open PRs for that dependency and close the PRs by commit message @@ -24,6 +26,20 @@ module.exports = async function ({ repositoryId, groupName }) { log.info('started') + // delete existing initial subgroup branches + const configChanges = { added: [], removed: [], modified: [groupName] } + const groupBranchesToDelete = _.flatten(await getGroupBranchesToDelete({configChanges, repositories, repositoryId})) + if (groupBranchesToDelete && groupBranchesToDelete.length) { + await Promise.mapSeries( + groupBranchesToDelete, + deleteBranches.bind(null, { + installationId, + fullName: repoDoc.fullName, + repositoryId + }) + ) + } + await updateRepoDoc({installationId, doc: repoDoc, log}) const config = getConfig(repoDoc) const pathsForGroup = config.groups[groupName].packages diff --git a/test/jobs/create-initial-subgroup-branch.js b/test/jobs/create-initial-subgroup-branch.js index 0477d9b6..2cb95675 100644 --- a/test/jobs/create-initial-subgroup-branch.js +++ b/test/jobs/create-initial-subgroup-branch.js @@ -160,6 +160,148 @@ describe('create initial subgroup branch', () => { expect(newBranch.initial).toBeFalsy() }) + test('create a subgroup branch, with existing initial subgroub branch', async () => { + const { repositories } = await dbs() + const configFileContent = { + groups: { + frontend: { + packages: [ + 'packages/frontend/package.json', + 'packages/lalalalala/package.json' + ] + }, + backend: { + packages: [ + 'packages/backend/package.json' + ] + } + } + } + await repositories.put({ + _id: '11112', + fullName: 'hans/monorepo', + accountId: '123', + enabled: true, + headSha: 'hallo', + packages: { + 'packages/frontend/package.json': { + name: 'testpkg', + dependencies: { + lodash: '^1.0.0' + } + }, + 'packages/backend/package.json': { + name: 'testpkg', + dependencies: { + lodash: '^1.0.0' + } + }, + 'packages/lalalalala/package.json': { + name: 'testpkg', + dependencies: { + lodash: '^1.0.0' + } + } + }, + greenkeeper: configFileContent + }) + await repositories.put({ + _id: '11112:branch:initialGroup', + type: 'branch', + sha: '1234abcd', + repositoryId: '11112', + head: 'greenkeeper/initial-frontend', + initial: false, + subgroupInitial: true, + group: 'frontend' + }) + + expect.assertions(8) + + const httpRequests = nock('https://api.github.com') + .post('/installations/37/access_tokens') + .optionally() + .reply(200, { + token: 'secret' + }) + .get('/rate_limit') + .optionally() + .reply(200, {}) + .get('/repos/hans/monorepo/contents/greenkeeper.json') + .reply(200, { + type: 'file', + path: 'greenkeeper.json', + name: 'greenkeeper.json', + content: Buffer.from(JSON.stringify(configFileContent)).toString('base64') + }) + .get('/repos/hans/monorepo/contents/packages/frontend/package.json') + .reply(200, { + path: 'packages/frontend/package.json', + name: 'package.json', + content: encodePkg({ + name: 'testpkg', + dependencies: { + lodash: '^1.0.0' + } + }) + }) + .get('/repos/hans/monorepo/contents/packages/lalalalala/package.json') + .reply(200, { + path: 'packages/lalalalala/package.json', + name: 'package.json', + content: encodePkg({ + name: 'testpkg', + dependencies: { + lodash: '^1.0.0' + } + }) + }) + .get('/repos/hans/monorepo') + .reply(200, { + default_branch: 'master' + }) + .delete('/repos/hans/monorepo/git/refs/heads/greenkeeper/initial-frontend') + .reply(200, {}) + + const npmHttpRequests = nock('https://registry.npmjs.org') + .get('/lodash') + .reply(200, { + 'dist-tags': { + latest: '3.0.0-rc1' + }, + versions: { + '2.0.0-rc1': true, + '2.0.0-rc2': true, + '2.0.0': true, + '3.0.0-rc1': true, + '1.0.0': true + } + }) + + // mock relative dependencies + jest.mock('../../lib/create-branch', () => ({ transforms }) => { + transforms.forEach(t => { + const newPkg = JSON.parse( + t.transform(JSON.stringify({ dependencies: { lodash: '^1.0.0' } })) + ) + expect(newPkg.dependencies['lodash']).toEqual('^2.0.0') + }) + + return '1234abcd' + }) + const createInitialSubgroupBranch = require('../../jobs/create-initial-subgroup-branch') + const newJob = await createInitialSubgroupBranch({repositoryId: '11112', groupName: 'frontend'}) + const oldBranch = await repositories.get('11112:branch:initialGroup') + expect(oldBranch.referenceDeleted).toBeTruthy() + const newBranch = await repositories.get('11112:branch:1234abcd') + + expect(httpRequests.isDone()).toBeTruthy() + expect(npmHttpRequests.isDone()).toBeTruthy() + expect(newJob).toBeFalsy() // This only creates branches + expect(newBranch.type).toEqual('branch') + expect(newBranch.initial).toBeFalsy() + }) + test('create a subgroup branch with all dependencies ignored from multiple sources', async () => { const { repositories } = await dbs() const configFileContent = { diff --git a/test/jobs/github-event/push.js b/test/jobs/github-event/push.js index 8d6e2500..60812895 100644 --- a/test/jobs/github-event/push.js +++ b/test/jobs/github-event/push.js @@ -1680,6 +1680,16 @@ describe('github-event push: monorepo', () => { dependency: 'lodash', dependencyType: 'dependencies', head: 'greenkeeper/backend/lodash-2.0.0' + }, + { + _id: '888:branch:initialGroup', + type: 'branch', + sha: '1234abcd', + repositoryId: '888', + head: 'greenkeeper/initial-frontend', + initial: false, + subgroupInitial: true, + group: 'frontend' } ]) ]) @@ -1732,6 +1742,8 @@ describe('github-event push: monorepo', () => { expect(true).toBeFalsy() return {} }) + .delete('/repos/hans/monorepo/git/refs/heads/greenkeeper/initial-frontend') + .reply(200, {}) const newJob = await githubPush({ installation: { @@ -1789,6 +1801,8 @@ describe('github-event push: monorepo', () => { expect(frontend.referenceDeleted).toBeTruthy() const backend = await repositories.get('888:branch:1234abcb') expect(backend.referenceDeleted).toBeFalsy() + const subgroupInitial = await repositories.get('888:branch:initialGroup') + expect(subgroupInitial.referenceDeleted).toBeTruthy() expect(repo.headSha).toEqual('9049f1265b7d61be4a8904a9a27120d2064dab3b') })