From cf997547b4fa83c5aab87ba67dc62137d0d68d42 Mon Sep 17 00:00:00 2001 From: Kenichi Kamiya Date: Thu, 30 Jun 2022 01:33:50 +0900 Subject: [PATCH 1/4] Add test for library and application pattern Commit message is different between application and library. Current parser targets only for application pattern. This commit will cover libraries. https://github.com/dependabot/dependabot-core/blob/7444344c03b86112b4801eec92b0909e05dbfe33/common/lib/dependabot/pull_request_creator/message_builder.rb#L71-L110 https://github.com/dependabot/dependabot-core/blob/7444344c03b86112b4801eec92b0909e05dbfe33/common/lib/dependabot/pull_request_creator/message_builder.rb#L126-L130 https://github.com/dependabot/dependabot-core/blob/7444344c03b86112b4801eec92b0909e05dbfe33/common/lib/dependabot/pull_request_creator/message_builder.rb#L181-L216 --- src/main.test.ts | 71 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/src/main.test.ts b/src/main.test.ts index c863b229..e0ad5e6d 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -61,7 +61,7 @@ test('it does nothing if there is no metadata in the commit', async () => { /* eslint-enable no-unused-expressions */ }) -test('it sets the updated dependency as an output for subsequent actions', async () => { +test('it sets the updated dependency as an output for subsequent actions when given a commit message for application', async () => { const mockCommitMessage = 'Bumps [coffee-rails](https://github.com/rails/coffee-rails) from 4.0.1 to 4.2.2.\n' + '- [Release notes](https://github.com/rails/coffee-rails/releases)\n' + @@ -131,6 +131,75 @@ test('it sets the updated dependency as an output for subsequent actions', async expect(core.setOutput).toBeCalledWith('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 +Updates the requirements on [rubocop](https://github.com/rubocop/rubocop) to permit the latest version. +- [Release notes](https://github.com/rubocop/rubocop/releases) +- [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md) +- [Commits](rubocop/rubocop@v1.30.1...v1.31.0) + +--- +updated-dependencies: +- dependency-name: rubocop + dependency-type: direct:development +... + +Signed-off-by: dependabot[bot] ` + const mockAlert = { alertState: 'FIXED', ghsaId: 'GSHA', cvss: 3.4 } + + jest.spyOn(core, 'getInput').mockImplementation(jest.fn((name) => { return name === 'github-token' ? 'mock-token' : '' })) + jest.spyOn(util, 'getBranchNames').mockReturnValue({ headName: 'dependabot|bundler|feature1', baseName: 'main' }) + 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 1 updated dependency') + ) + + expect(core.setOutput).toHaveBeenCalledWith( + 'updated-dependencies-json', + [ + { + dependencyName: 'rubocop', + dependencyType: 'direct:development', + updateType: 'version-update:semver-minor', + directory: '/', + packageEcosystem: 'bundler', + targetBranch: 'main', + prevVersion: '1.30.1', + newVersion: '1.31.0', + compatScore: 0, + alertState: '', + ghsaId: '', + cvss: 0 + } + ] + ) + + expect(core.setOutput).toBeCalledWith('dependency-names', 'rubocop') + expect(core.setOutput).toBeCalledWith('dependency-type', 'direct:development') + expect(core.setOutput).toBeCalledWith('update-type', 'version-update:semver-minor') + expect(core.setOutput).toBeCalledWith('directory', '/') + expect(core.setOutput).toBeCalledWith('package-ecosystem', 'bundler') + expect(core.setOutput).toBeCalledWith('target-branch', 'main') + expect(core.setOutput).toBeCalledWith('previous-version', '1.30.1') + expect(core.setOutput).toBeCalledWith('new-version', '1.31.0') + expect(core.setOutput).toBeCalledWith('compatibility-score', 0) + expect(core.setOutput).toBeCalledWith('alert-state', '') + expect(core.setOutput).toBeCalledWith('ghsa-id', '') + expect(core.setOutput).toBeCalledWith('cvss', 0) +}) + test('if there are multiple dependencies, it summarizes them', async () => { const mockCommitMessage = 'Bump coffee-rails from 4.0.1 to 4.2.2 in api/main\n' + From e4063e40b9bbb6a5cce89d899e53535b04274603 Mon Sep 17 00:00:00 2001 From: Kenichi Kamiya Date: Thu, 30 Jun 2022 01:59:20 +0900 Subject: [PATCH 2/4] Fit parser for libraries --- src/dependabot/update_metadata.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/dependabot/update_metadata.ts b/src/dependabot/update_metadata.ts index 21fb7851..ac85c35d 100644 --- a/src/dependabot/update_metadata.ts +++ b/src/dependabot/update_metadata.ts @@ -28,6 +28,7 @@ export interface scoreLookup { export async function parse (commitMessage: string, branchName: string, mainBranch: string, lookup?: alertLookup, getScore?: scoreLookup): Promise> { const bumpFragment = commitMessage.match(/^Bumps .* from (?\d[^ ]*) to (?\d[^ ]*)\.$/m) + const updateFragment = commitMessage.match(/^Update .* requirement from \S*? ?(?\d[^ ]*) to \S*? ?(?\d[^ ]*)$/m) const yamlFragment = commitMessage.match(/^-{3}\n(?[\S|\s]*?)\n^\.{3}\n/m) const lookupFn = lookup ?? (() => Promise.resolve({ alertState: '', ghsaId: '', cvss: 0 })) const scoreFn = getScore ?? (() => Promise.resolve(0)) @@ -38,8 +39,8 @@ export async function parse (commitMessage: string, branchName: string, mainBran // Since we are on the `dependabot` branch (9 letters), the 10th letter in the branch name is the delimiter const delim = branchName[10] const chunks = branchName.split(delim) - const prev = bumpFragment?.groups?.from ?? '' - const next = bumpFragment?.groups?.to ?? '' + const prev = bumpFragment?.groups?.from ?? (updateFragment?.groups?.from ?? '') + const next = bumpFragment?.groups?.to ?? (updateFragment?.groups?.to ?? '') if (data['updated-dependencies']) { return await Promise.all(data['updated-dependencies'].map(async (dependency, index) => { From f45919f08bd8ad6b3aea3a21467013be28a90d17 Mon Sep 17 00:00:00 2001 From: Kenichi Kamiya Date: Thu, 30 Jun 2022 02:04:21 +0900 Subject: [PATCH 3/4] `npm run build` --- dist/index.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/dist/index.js b/dist/index.js index 3d4bf343..38d52a66 100644 --- a/dist/index.js +++ b/dist/index.js @@ -8950,9 +8950,10 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); exports.calculateUpdateType = exports.parse = void 0; const YAML = __importStar(__nccwpck_require__(4083)); function parse(commitMessage, branchName, mainBranch, lookup, getScore) { - var _a, _b, _c, _d; + var _a, _b, _c, _d, _e, _f, _g, _h; return __awaiter(this, void 0, void 0, function* () { const bumpFragment = commitMessage.match(/^Bumps .* from (?\d[^ ]*) to (?\d[^ ]*)\.$/m); + const updateFragment = commitMessage.match(/^Update .* requirement from \S*? ?(?\d[^ ]*) to \S*? ?(?\d[^ ]*)$/m); const yamlFragment = commitMessage.match(/^-{3}\n(?[\S|\s]*?)\n^\.{3}\n/m); const lookupFn = lookup !== null && lookup !== void 0 ? lookup : (() => Promise.resolve({ alertState: '', ghsaId: '', cvss: 0 })); const scoreFn = getScore !== null && getScore !== void 0 ? getScore : (() => Promise.resolve(0)); @@ -8961,8 +8962,8 @@ function parse(commitMessage, branchName, mainBranch, lookup, getScore) { // Since we are on the `dependabot` branch (9 letters), the 10th letter in the branch name is the delimiter const delim = branchName[10]; const chunks = branchName.split(delim); - const prev = (_b = (_a = bumpFragment === null || bumpFragment === void 0 ? void 0 : bumpFragment.groups) === null || _a === void 0 ? void 0 : _a.from) !== null && _b !== void 0 ? _b : ''; - const next = (_d = (_c = bumpFragment === null || bumpFragment === void 0 ? void 0 : bumpFragment.groups) === null || _c === void 0 ? void 0 : _c.to) !== null && _d !== void 0 ? _d : ''; + const prev = (_b = (_a = bumpFragment === null || bumpFragment === void 0 ? void 0 : bumpFragment.groups) === null || _a === void 0 ? void 0 : _a.from) !== null && _b !== void 0 ? _b : ((_d = (_c = updateFragment === null || updateFragment === void 0 ? void 0 : updateFragment.groups) === null || _c === void 0 ? void 0 : _c.from) !== null && _d !== void 0 ? _d : ''); + const next = (_f = (_e = bumpFragment === null || bumpFragment === void 0 ? void 0 : bumpFragment.groups) === null || _e === void 0 ? void 0 : _e.to) !== null && _f !== void 0 ? _f : ((_h = (_g = updateFragment === null || updateFragment === void 0 ? void 0 : updateFragment.groups) === null || _g === void 0 ? void 0 : _g.to) !== null && _h !== void 0 ? _h : ''); if (data['updated-dependencies']) { return yield Promise.all(data['updated-dependencies'].map((dependency, index) => __awaiter(this, void 0, void 0, function* () { const dirname = `/${chunks.slice(2, -1 * (1 + (dependency['dependency-name'].match(/\//g) || []).length)).join(delim) || ''}`; From 0a3f18375a9a1749a02dce2656df58200e195cfc Mon Sep 17 00:00:00 2001 From: Kenichi Kamiya Date: Sun, 22 Jan 2023 21:17:04 +0900 Subject: [PATCH 4/4] Adjust indent style with existing code https://github.com/dependabot/fetch-metadata/pull/224#issuecomment-1399120739 --- src/main.test.ts | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/main.test.ts b/src/main.test.ts index c3b51523..b5ca4c50 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -133,19 +133,20 @@ test('it sets the updated dependency as an output for subsequent actions when gi }) 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 -Updates the requirements on [rubocop](https://github.com/rubocop/rubocop) to permit the latest version. -- [Release notes](https://github.com/rubocop/rubocop/releases) -- [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md) -- [Commits](rubocop/rubocop@v1.30.1...v1.31.0) - ---- -updated-dependencies: -- dependency-name: rubocop - dependency-type: direct:development -... - -Signed-off-by: dependabot[bot] ` + const mockCommitMessage = + 'Update rubocop requirement from ~> 1.30.1 to ~> 1.31.0\n' + + 'Updates the requirements on [rubocop](https://github.com/rubocop/rubocop) to permit the latest version.\n' + + '- [Release notes](https://github.com/rubocop/rubocop/releases)\n' + + '- [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md)\n' + + '- [Commits](rubocop/rubocop@v1.30.1...v1.31.0)\n' + + '\n' + + '---\n' + + 'updated-dependencies:\n' + + '- dependency-name: rubocop\n' + + ' dependency-type: direct:development\n' + + '...\n' + + '\n' + + 'Signed-off-by: dependabot[bot] ' const mockAlert = { alertState: 'FIXED', ghsaId: 'GSHA', cvss: 3.4 } jest.spyOn(core, 'getInput').mockImplementation(jest.fn((name) => { return name === 'github-token' ? 'mock-token' : '' }))