From 9e8fb5b31bffc46285ed71aef2a5e7d878ad4f10 Mon Sep 17 00:00:00 2001 From: Nish Sinha Date: Thu, 8 Jun 2023 14:57:21 -0400 Subject: [PATCH] Add tests for grouped updates --- src/dependabot/output.test.ts | 2 + src/dependabot/update_metadata.test.ts | 47 ++++++++++ src/dependabot/update_metadata.ts | 2 +- src/main.test.ts | 115 +++++++++++++++++++++++++ 4 files changed, 165 insertions(+), 1 deletion(-) diff --git a/src/dependabot/output.test.ts b/src/dependabot/output.test.ts index 80d46ee9..59e1e5f6 100644 --- a/src/dependabot/output.test.ts +++ b/src/dependabot/output.test.ts @@ -20,6 +20,7 @@ const baseDependency = { newVersion: '', compatScore: 0, maintainerChanges: false, + dependencyGroup: '', alertState: '', ghsaId: '', cvss: 0 @@ -38,6 +39,7 @@ test('when given a single dependency it sets its values', async () => { newVersion: '1.1.3-beta', compatScore: 43, maintainerChanges: true, + dependencyGroup: '', alertState: 'FIXED', ghsaId: 'VERY_LONG_ID', cvss: 4.6 diff --git a/src/dependabot/update_metadata.test.ts b/src/dependabot/update_metadata.test.ts index 83592f61..3569473d 100644 --- a/src/dependabot/update_metadata.test.ts +++ b/src/dependabot/update_metadata.test.ts @@ -61,6 +61,7 @@ test('it returns the updated dependency information when there is a yaml fragmen expect(updatedDependencies[0].alertState).toEqual('DISMISSED') expect(updatedDependencies[0].ghsaId).toEqual('GHSA-III-BBB') expect(updatedDependencies[0].cvss).toEqual(4.6) + expect(updatedDependencies[0].dependencyGroup).toEqual('') }) test('it supports multiple dependencies within a single fragment', async () => { @@ -122,6 +123,8 @@ test('it supports multiple dependencies within a single fragment', async () => { expect(updatedDependencies[0].alertState).toEqual('DISMISSED') expect(updatedDependencies[0].ghsaId).toEqual('GHSA-III-BBB') expect(updatedDependencies[0].cvss).toEqual(4.6) + expect(updatedDependencies[0].dependencyGroup).toEqual('') + expect(updatedDependencies[0].dependencyGroup).toEqual('') expect(updatedDependencies[1].dependencyName).toEqual('coffeescript') expect(updatedDependencies[1].dependencyType).toEqual('indirect') @@ -135,6 +138,7 @@ test('it supports multiple dependencies within a single fragment', async () => { expect(updatedDependencies[1].alertState).toEqual('') expect(updatedDependencies[1].ghsaId).toEqual('') expect(updatedDependencies[1].cvss).toEqual(0) + expect(updatedDependencies[1].dependencyGroup).toEqual('') }) test('it returns the updated dependency information when there is a leading v in the commit message versions', async () => { @@ -170,6 +174,47 @@ test('it returns the updated dependency information when there is a leading v in expect(updatedDependencies[0].alertState).toEqual('DISMISSED') expect(updatedDependencies[0].ghsaId).toEqual('GHSA-III-BBB') expect(updatedDependencies[0].cvss).toEqual(4.6) + expect(updatedDependencies[0].dependencyGroup).toEqual('') +}) + +test('it supports returning information about grouped updates', async () => { + const commitMessage = + 'Bumps the docker group with 3 updates: [github.com/docker/cli](https://github.com/docker/cli), [github.com/docker/docker](https://github.com/docker/docker) and [github.com/moby/moby](https://github.com/moby/moby).\n' + + '\n' + + 'Updates `github.com/docker/cli` from 24.0.1+incompatible to 24.0.2+incompatible\n' + + '- [Commits](docker/cli@v24.0.1...v24.0.2)\n' + + '\n' + + 'Updates `github.com/docker/docker` from 24.0.1+incompatible to 24.0.2+incompatible\n' + + '- [Release notes](https://github.com/docker/docker/releases)\n' + + '- [Commits](moby/moby@v24.0.1...v24.0.2)\n' + + '\n' + + 'Updates `github.com/moby/moby` from 24.0.1+incompatible to 24.0.2+incompatible\n' + + '- [Release notes](https://github.com/moby/moby/releases)\n' + + '- [Commits](moby/moby@v24.0.1...v24.0.2)\n' + + '\n' + + '---\n' + + 'updated-dependencies:\n' + + '- dependency-name: github.com/docker/cli\n' + + ' dependency-type: direct:production\n' + + ' update-type: version-update:semver-patch\n' + + '- dependency-name: github.com/docker/docker\n' + + ' dependency-type: direct:production\n' + + ' update-type: version-update:semver-patch\n' + + '- dependency-name: github.com/moby/moby\n' + + ' dependency-type: direct:production\n' + + ' update-type: version-update:semver-patch\n' + + '...\n' + + '\n' + + 'Signed-off-by: dependabot[bot] \n' + + const getAlert = async () => Promise.resolve({ alertState: 'DISMISSED', ghsaId: 'GHSA-III-BBB', cvss: 4.6 }) + const getScore = async () => Promise.resolve(43) + const updatedDependencies = await updateMetadata.parse(commitMessage, '', 'dependabot/docker/gh-base-image/docker-1234566789', 'main', getAlert, getScore) + + expect(updatedDependencies).toHaveLength(3) + + expect(updatedDependencies[0].dependencyName).toEqual('github.com/docker/cli') + expect(updatedDependencies[0].dependencyGroup).toEqual('docker') }) test('it only returns information within the first fragment if there are multiple yaml documents', async () => { @@ -211,6 +256,7 @@ test('it only returns information within the first fragment if there are multipl expect(updatedDependencies[0].alertState).toEqual('') expect(updatedDependencies[0].ghsaId).toEqual('') expect(updatedDependencies[0].cvss).toEqual(0) + expect(updatedDependencies[0].dependencyGroup).toEqual('') }) test('it properly handles dependencies which contain slashes', async () => { @@ -247,6 +293,7 @@ test('it properly handles dependencies which contain slashes', async () => { expect(updatedDependencies[0].alertState).toEqual('') expect(updatedDependencies[0].ghsaId).toEqual('') expect(updatedDependencies[0].cvss).toEqual(0) + expect(updatedDependencies[0].dependencyGroup).toEqual('') }) test('calculateUpdateType should handle all paths', () => { diff --git a/src/dependabot/update_metadata.ts b/src/dependabot/update_metadata.ts index af937a00..edc67663 100644 --- a/src/dependabot/update_metadata.ts +++ b/src/dependabot/update_metadata.ts @@ -45,7 +45,7 @@ export async function parse (commitMessage: string, body: string, branchName: st const chunks = branchName.split(delim) const prev = bumpFragment?.groups?.from ?? (updateFragment?.groups?.from ?? '') const next = bumpFragment?.groups?.to ?? (updateFragment?.groups?.to ?? '') - const dependencyGroup = groupName?.groups?.name ?? '' + const dependencyGroup = groupName?.groups?.name ?? '' if (data['updated-dependencies']) { return await Promise.all(data['updated-dependencies'].map(async (dependency, index) => { diff --git a/src/main.test.ts b/src/main.test.ts index f0fbeda1..f47b2586 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -112,6 +112,7 @@ test('it sets the updated dependency as an output for subsequent actions when gi newVersion: '4.2.2', compatScore: 0, maintainerChanges: false, + dependencyGroup: '', alertState: '', ghsaId: '', cvss: 0 @@ -129,6 +130,7 @@ test('it sets the updated dependency as an output for subsequent actions when gi expect(core.setOutput).toBeCalledWith('new-version', '4.2.2') expect(core.setOutput).toBeCalledWith('compatibility-score', 0) expect(core.setOutput).toBeCalledWith('maintainer-changes', false) + expect(core.setOutput).toBeCalledWith('dependency-group', '') expect(core.setOutput).toBeCalledWith('alert-state', '') expect(core.setOutput).toBeCalledWith('ghsa-id', '') expect(core.setOutput).toBeCalledWith('cvss', 0) @@ -179,6 +181,7 @@ test('it sets the updated dependency as an output for subsequent actions when th directory: '/', packageEcosystem: 'nuget', maintainerChanges: false, + dependencyGroup: '', targetBranch: 'main', prevVersion: 'v4.0.1', newVersion: 'v4.2.2', @@ -200,11 +203,118 @@ test('it sets the updated dependency as an output for subsequent actions when th expect(core.setOutput).toBeCalledWith('new-version', 'v4.2.2') expect(core.setOutput).toBeCalledWith('compatibility-score', 0) expect(core.setOutput).toBeCalledWith('maintainer-changes', false) + expect(core.setOutput).toBeCalledWith('dependency-group', '') expect(core.setOutput).toBeCalledWith('alert-state', '') expect(core.setOutput).toBeCalledWith('ghsa-id', '') expect(core.setOutput).toBeCalledWith('cvss', 0) }) +test('it supports returning information about grouped updates', async () => { + const mockCommitMessage = + 'Bumps the docker group with 3 updates: [github.com/docker/cli](https://github.com/docker/cli), [github.com/docker/docker](https://github.com/docker/docker) and [github.com/moby/moby](https://github.com/moby/moby).\n' + + '\n' + + 'Updates `github.com/docker/cli` from 24.0.1+incompatible to 24.0.2+incompatible\n' + + '- [Commits](docker/cli@v24.0.1...v24.0.2)\n' + + '\n' + + 'Updates `github.com/docker/docker` from 24.0.1+incompatible to 24.0.2+incompatible\n' + + '- [Release notes](https://github.com/docker/docker/releases)\n' + + '- [Commits](moby/moby@v24.0.1...v24.0.2)\n' + + '\n' + + 'Updates `github.com/moby/moby` from 24.0.1+incompatible to 24.0.2+incompatible\n' + + '- [Release notes](https://github.com/moby/moby/releases)\n' + + '- [Commits](moby/moby@v24.0.1...v24.0.2)\n' + + '\n' + + '---\n' + + 'updated-dependencies:\n' + + '- dependency-name: github.com/docker/cli\n' + + ' dependency-type: direct:production\n' + + ' update-type: version-update:semver-patch\n' + + '- dependency-name: github.com/docker/docker\n' + + ' dependency-type: direct:production\n' + + ' update-type: version-update:semver-patch\n' + + '- dependency-name: github.com/moby/moby\n' + + ' dependency-type: direct:production\n' + + ' update-type: version-update:semver-patch\n' + + '...\n' + + '\n' + + 'Signed-off-by: dependabot[bot] \n' + + const mockAlert = { alertState: '', ghsaId: '', cvss: 0 } + + jest.spyOn(core, 'getInput').mockReturnValue('mock-token') + jest.spyOn(util, 'getBranchNames').mockReturnValue({ headName: 'dependabot/docker/gh-base-image/docker-1234566789', baseName: 'trunk' }) + jest.spyOn(dependabotCommits, 'getMessage').mockImplementation(jest.fn( + () => Promise.resolve(mockCommitMessage) + )) + jest.spyOn(dependabotCommits, 'getAlert').mockImplementation(jest.fn( + () => Promise.resolve(mockAlert) + )) + jest.spyOn(dependabotCommits, 'getCompatibility').mockImplementation(jest.fn( + () => Promise.resolve(34) + )) + jest.spyOn(core, 'setOutput').mockImplementation(jest.fn()) + + await run() + + expect(core.startGroup).toHaveBeenCalledWith( + expect.stringContaining('Outputting metadata for 3 updated dependencies') + ) + + expect(core.setOutput).toHaveBeenCalledWith( + 'updated-dependencies-json', + [ + { + dependencyName: 'github.com/docker/cli', + dependencyType: 'direct:production', + updateType: 'version-update:semver-patch', + directory: '/', + packageEcosystem: 'docker', + targetBranch: 'trunk', + prevVersion: '24.0.1', + newVersion: '24.0.2', + compatScore: 34, + maintainerChanges: false, + dependencyGroup: 'docker', + alertState: '', + ghsaId: '', + cvss: 0 + }, + { + dependencyName: 'github.com/docker/docker', + dependencyType: 'direct:production', + updateType: 'version-update:semver-patch', + directory: '/', + packageEcosystem: 'docker', + targetBranch: 'trunk', + prevVersion: '24.0.1', + newVersion: '24.0.2', + compatScore: 34, + maintainerChanges: false, + dependencyGroup: 'docker', + alertState: '', + ghsaId: '', + cvss: 0 + }, + { + dependencyName: 'github.com/moby/moby', + dependencyType: 'direct:production', + updateType: 'version-update:semver-patch', + directory: '/', + packageEcosystem: 'docker', + targetBranch: 'trunk', + prevVersion: '24.0.1', + newVersion: '24.0.2', + compatScore: 34, + maintainerChanges: false, + dependencyGroup: 'docker', + alertState: '', + ghsaId: '', + cvss: 0 + } + ] + ) +}) + test('it sets the updated dependency as an output for subsequent actions when given a commit message for library', async () => { const mockCommitMessage = 'Update rubocop requirement from ~> 1.30.1 to ~> 1.31.0\n' + @@ -253,6 +363,7 @@ test('it sets the updated dependency as an output for subsequent actions when gi packageEcosystem: 'bundler', targetBranch: 'main', maintainerChanges: false, + dependencyGroup: '', prevVersion: '1.30.1', newVersion: '1.31.0', compatScore: 0, @@ -273,6 +384,7 @@ test('it sets the updated dependency as an output for subsequent actions when gi expect(core.setOutput).toBeCalledWith('new-version', '1.31.0') expect(core.setOutput).toBeCalledWith('compatibility-score', 0) expect(core.setOutput).toBeCalledWith('maintainer-changes', false) + expect(core.setOutput).toBeCalledWith('dependency-group', '') expect(core.setOutput).toBeCalledWith('alert-state', '') expect(core.setOutput).toBeCalledWith('ghsa-id', '') expect(core.setOutput).toBeCalledWith('cvss', 0) @@ -332,6 +444,7 @@ test('if there are multiple dependencies, it summarizes them', async () => { newVersion: '4.2.2', compatScore: 34, maintainerChanges: false, + dependencyGroup: '', alertState: '', ghsaId: '', cvss: 0 @@ -347,6 +460,7 @@ test('if there are multiple dependencies, it summarizes them', async () => { newVersion: '', compatScore: 34, maintainerChanges: false, + dependencyGroup: '', alertState: '', ghsaId: '', cvss: 0 @@ -364,6 +478,7 @@ test('if there are multiple dependencies, it summarizes them', async () => { expect(core.setOutput).toBeCalledWith('new-version', '4.2.2') expect(core.setOutput).toBeCalledWith('compatibility-score', 34) expect(core.setOutput).toBeCalledWith('maintainer-changes', false) + expect(core.setOutput).toBeCalledWith('dependency-group', '') expect(core.setOutput).toBeCalledWith('alert-state', '') expect(core.setOutput).toBeCalledWith('ghsa-id', '') expect(core.setOutput).toBeCalledWith('cvss', 0)