From 8001861ce31da97c010fad323fe14065140a2bd6 Mon Sep 17 00:00:00 2001 From: Michael Waddell Date: Mon, 7 Feb 2022 17:39:02 -0600 Subject: [PATCH 1/7] Added directory, package-ecosystem and target_branch to output closes issue #76 --- README.md | 6 +++ action.yml | 6 +++ dist/index.js | 39 ++++++++++++++-- src/dependabot/output.test.ts | 62 +++++++++++++++++++++----- src/dependabot/output.ts | 11 +++++ src/dependabot/update_metadata.test.ts | 22 ++++++--- src/dependabot/update_metadata.ts | 16 +++++-- src/dependabot/util.ts | 12 +++++ src/dry-run.ts | 2 +- src/main.test.ts | 29 ++++++++++-- src/main.ts | 4 +- 11 files changed, 182 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index f2cee63e..668c32f0 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,12 @@ Subsequent actions will have access to the following outputs: - The highest semver change being made by this PR, e.g. `version-update:semver-major`. For all possible values, see [the `ignore` documentation](https://docs.github.com/en/code-security/supply-chain-security/keeping-your-dependencies-updated-automatically/configuration-options-for-dependency-updates#ignore). - `steps.dependabot-metadata.outputs.updated-dependencies-json` - A JSON string containing the full information about each updated Dependency. +- `steps.dependabot-metadata.outputs.directory` + - The `directory` configuration that was used by dependabot for this updated Dependency. +- `steps.dependabot-metadata.outputs.package-ecosystem` + - The `package-ecosystem` configuration that was used by dependabot for this updated Dependency. +- `steps.dependabot-metadata.outputs.target_branch` + - The `target_branch` configuration that was used by dependabot for this updated Dependency. **Note:** These outputs will only be populated if the target Pull Request was opened by Dependabot and contains **only** Dependabot-created commits. diff --git a/action.yml b/action.yml index f0b0190d..574a887a 100644 --- a/action.yml +++ b/action.yml @@ -16,6 +16,12 @@ outputs: description: 'The highest semver change being made by this PR, e.g. "version-update:semver-major"' updated-dependencies-json: description: 'A JSON string containing the full information about each updated Dependency.' + directory: + description: 'The `directory` configuration that was used by dependabot for this updated Dependency.' + package-ecosystem: + description: 'The `package-ecosystem` configuration that was used by dependabot for this updated Dependency.' + target_branch: + description: 'The `target_branch` configuration that was used by dependabot for this updated Dependency.' runs: using: 'node12' main: 'dist/index.js' diff --git a/dist/index.js b/dist/index.js index da130bad..6deb35ae 100644 --- a/dist/index.js +++ b/dist/index.js @@ -13406,16 +13406,22 @@ function warnOtherCommits() { var yaml = __nccwpck_require__(3552); ;// CONCATENATED MODULE: ./src/dependabot/update_metadata.ts -function parse(commitMessage) { +function parse(commitMessage, branchName, mainBranch) { const yamlFragment = commitMessage.match(/^-{3}\n(?[\S|\s]*?)\n^\.{3}\n/m); - if (yamlFragment === null || yamlFragment === void 0 ? void 0 : yamlFragment.groups) { + if ((yamlFragment === null || yamlFragment === void 0 ? void 0 : yamlFragment.groups) && branchName.startsWith('dependabot')) { const data = yaml.parse(yamlFragment.groups.dependencies); + const delim = branchName[10]; + const chunks = branchName.split(delim); + const dirname = chunks.slice(2, -1).join(delim) || '/'; if (data['updated-dependencies']) { return data['updated-dependencies'].map(dependency => { return { dependencyName: dependency['dependency-name'], dependencyType: dependency['dependency-type'], - updateType: dependency['update-type'] + updateType: dependency['update-type'], + directory: dirname, + packageEcosystem: chunks[1], + targetBranch: mainBranch }; }); } @@ -13445,15 +13451,25 @@ function set(updatedDependencies) { }).join(', '); const dependencyType = maxDependencyTypes(updatedDependencies); const updateType = maxSemver(updatedDependencies); + const firstDependency = updatedDependencies[0]; + const directory = firstDependency === null || firstDependency === void 0 ? void 0 : firstDependency.directory; + const ecosystem = firstDependency === null || firstDependency === void 0 ? void 0 : firstDependency.packageEcosystem; + const target = firstDependency === null || firstDependency === void 0 ? void 0 : firstDependency.targetBranch; core.startGroup(`Outputting metadata for ${pluralize_default()('updated dependency', updatedDependencies.length, true)}`); core.info(`outputs.dependency-names: ${dependencyNames}`); core.info(`outputs.dependency-type: ${dependencyType}`); core.info(`outputs.update-type: ${updateType}`); + core.info(`outputs.directory: ${directory}`); + core.info(`outputs.package-ecosystem: ${ecosystem}`); + core.info(`outputs.target_branch: ${target}`); core.endGroup(); core.setOutput('updated-dependencies-json', updatedDependencies); core.setOutput('dependency-names', dependencyNames); core.setOutput('dependency-type', dependencyType); core.setOutput('update-type', updateType); + core.setOutput('directory', directory); + core.setOutput('package-ecosystem', ecosystem); + core.setOutput('target_branch', target); } function maxDependencyTypes(updatedDependencies) { const dependencyTypes = updatedDependencies.reduce(function (dependencyTypes, dependency) { @@ -13470,6 +13486,19 @@ function maxSemver(updatedDependencies) { return UPDATE_TYPES_PRIORITY.find(semverLevel => semverLevels.has(semverLevel)) || null; } +;// CONCATENATED MODULE: ./src/dependabot/util.ts +function parseNwo(nwo) { + const [owner, name] = nwo.split('/'); + if (!owner || !name) { + throw new Error(`'${nwo}' does not appear to be a valid repository NWO`); + } + return { owner: owner, repo: name }; +} +function getBranchNames(context) { + const { pull_request: pr } = context.payload; + return { headName: (pr === null || pr === void 0 ? void 0 : pr.head.ref) || '', baseName: pr === null || pr === void 0 ? void 0 : pr.base.ref }; +} + ;// CONCATENATED MODULE: ./src/main.ts var main_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } @@ -13486,6 +13515,7 @@ var main_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arg + function run() { return main_awaiter(this, void 0, void 0, function* () { const token = core.getInput('github-token'); @@ -13499,10 +13529,11 @@ function run() { const githubClient = github.getOctokit(token); // Validate the job const commitMessage = yield getMessage(githubClient, github.context); + const branchNames = getBranchNames(github.context); if (commitMessage) { // Parse metadata core.info('Parsing Dependabot metadata'); - const updatedDependencies = parse(commitMessage); + const updatedDependencies = parse(commitMessage, branchNames.headName, branchNames.baseName); if (updatedDependencies.length > 0) { set(updatedDependencies); } diff --git a/src/dependabot/output.test.ts b/src/dependabot/output.test.ts index 9a139c8f..5c8cd330 100644 --- a/src/dependabot/output.test.ts +++ b/src/dependabot/output.test.ts @@ -14,7 +14,10 @@ test('when given a single dependency it sets its values', async () => { { dependencyName: 'coffee-rails', dependencyType: 'direct:production', - updateType: 'version-update:semver-minor' + updateType: 'version-update:semver-minor', + directory: 'wwwroot', + packageEcosystem: 'nuget', + targetBranch: 'main' } ] @@ -29,6 +32,9 @@ test('when given a single dependency it sets its values', async () => { expect(core.setOutput).toBeCalledWith('dependency-names', 'coffee-rails') expect(core.setOutput).toBeCalledWith('dependency-type', 'direct:production') expect(core.setOutput).toBeCalledWith('update-type', 'version-update:semver-minor') + expect(core.setOutput).toBeCalledWith('directory', 'wwwroot') + expect(core.setOutput).toBeCalledWith('package-ecosystem', 'nuget') + expect(core.setOutput).toBeCalledWith('target_branch', 'main') }) test('when given a multiple dependencies, it uses the highest values for types', async () => { @@ -36,22 +42,34 @@ test('when given a multiple dependencies, it uses the highest values for types', { dependencyName: 'rspec', dependencyType: 'direct:development', - updateType: 'version-update:semver-minor' + updateType: 'version-update:semver-minor', + directory: '', + packageEcosystem: '', + targetBranch: '' }, { dependencyName: 'coffee-rails', dependencyType: 'indirect', - updateType: 'version-update:semver-minor' + updateType: 'version-update:semver-minor', + directory: '', + packageEcosystem: '', + targetBranch: '' }, { dependencyName: 'coffeescript', dependencyType: 'indirect', - updateType: 'version-update:semver-major' + updateType: 'version-update:semver-major', + directory: '', + packageEcosystem: '', + targetBranch: '' }, { dependencyName: 'rspec-coffeescript', dependencyType: 'indirect', - updateType: 'version-update:semver-patch' + updateType: 'version-update:semver-patch', + directory: '', + packageEcosystem: '', + targetBranch: '' } ] @@ -62,6 +80,9 @@ test('when given a multiple dependencies, it uses the highest values for types', expect(core.setOutput).toBeCalledWith('dependency-names', 'rspec, coffee-rails, coffeescript, rspec-coffeescript') expect(core.setOutput).toBeCalledWith('dependency-type', 'direct:development') expect(core.setOutput).toBeCalledWith('update-type', 'version-update:semver-major') + expect(core.setOutput).toBeCalledWith('directory', '') + expect(core.setOutput).toBeCalledWith('package-ecosystem', '') + expect(core.setOutput).toBeCalledWith('target_branch', '') }) test('when the dependency has no update type', async () => { @@ -69,7 +90,10 @@ test('when the dependency has no update type', async () => { { dependencyName: 'coffee-rails', dependencyType: 'direct:production', - updateType: '' + updateType: '', + directory: '', + packageEcosystem: '', + targetBranch: '' } ] @@ -84,6 +108,9 @@ test('when the dependency has no update type', async () => { expect(core.setOutput).toBeCalledWith('dependency-names', 'coffee-rails') expect(core.setOutput).toBeCalledWith('dependency-type', 'direct:production') expect(core.setOutput).toBeCalledWith('update-type', null) + expect(core.setOutput).toBeCalledWith('directory', '') + expect(core.setOutput).toBeCalledWith('package-ecosystem', '') + expect(core.setOutput).toBeCalledWith('target_branch', '') }) test('when given a multiple dependencies, and some do not have update types', async () => { @@ -91,22 +118,34 @@ test('when given a multiple dependencies, and some do not have update types', as { dependencyName: 'rspec', dependencyType: 'direct:development', - updateType: '' + updateType: '', + directory: '', + packageEcosystem: '', + targetBranch: '' }, { dependencyName: 'coffee-rails', dependencyType: 'indirect', - updateType: 'version-update:semver-minor' + updateType: 'version-update:semver-minor', + directory: '', + packageEcosystem: '', + targetBranch: '' }, { dependencyName: 'coffeescript', dependencyType: 'indirect', - updateType: '' + updateType: '', + directory: '', + packageEcosystem: '', + targetBranch: '' }, { dependencyName: 'rspec-coffeescript', dependencyType: 'indirect', - updateType: 'version-update:semver-patch' + updateType: 'version-update:semver-patch', + directory: '', + packageEcosystem: '', + targetBranch: '' } ] @@ -117,4 +156,7 @@ test('when given a multiple dependencies, and some do not have update types', as expect(core.setOutput).toBeCalledWith('dependency-names', 'rspec, coffee-rails, coffeescript, rspec-coffeescript') 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', '') + expect(core.setOutput).toBeCalledWith('target_branch', '') }) diff --git a/src/dependabot/output.ts b/src/dependabot/output.ts index e0966a16..3a5671cd 100644 --- a/src/dependabot/output.ts +++ b/src/dependabot/output.ts @@ -20,16 +20,27 @@ export function set (updatedDependencies: Array): void { const dependencyType = maxDependencyTypes(updatedDependencies) const updateType = maxSemver(updatedDependencies) + const firstDependency = updatedDependencies[0] + const directory = firstDependency?.directory + const ecosystem = firstDependency?.packageEcosystem + const target = firstDependency?.targetBranch + core.startGroup(`Outputting metadata for ${Pluralize('updated dependency', updatedDependencies.length, true)}`) core.info(`outputs.dependency-names: ${dependencyNames}`) core.info(`outputs.dependency-type: ${dependencyType}`) core.info(`outputs.update-type: ${updateType}`) + core.info(`outputs.directory: ${directory}`) + core.info(`outputs.package-ecosystem: ${ecosystem}`) + core.info(`outputs.target_branch: ${target}`) core.endGroup() core.setOutput('updated-dependencies-json', updatedDependencies) core.setOutput('dependency-names', dependencyNames) core.setOutput('dependency-type', dependencyType) core.setOutput('update-type', updateType) + core.setOutput('directory', directory) + core.setOutput('package-ecosystem', ecosystem) + core.setOutput('target_branch', target) } function maxDependencyTypes (updatedDependencies: Array): string { diff --git a/src/dependabot/update_metadata.test.ts b/src/dependabot/update_metadata.test.ts index 61c20cb8..844ed2a9 100644 --- a/src/dependabot/update_metadata.test.ts +++ b/src/dependabot/update_metadata.test.ts @@ -1,7 +1,7 @@ import * as updateMetadata from './update_metadata' test('it returns an empty array for a blank string', async () => { - expect(updateMetadata.parse('')).toEqual([]) + expect(updateMetadata.parse('', 'dependabot/nuget/feature1', 'main')).toEqual([]) }) test('it returns an empty array for commit message with no dependabot yaml fragment', async () => { @@ -12,7 +12,7 @@ test('it returns an empty array for commit message with no dependabot yaml fragm Signed-off-by: dependabot[bot] ` - expect(updateMetadata.parse(commitMessage)).toEqual([]) + expect(updateMetadata.parse(commitMessage, 'dependabot/nuget/feature1', 'main')).toEqual([]) }) test('it returns the updated dependency information when there is a yaml fragment', async () => { @@ -31,13 +31,16 @@ test('it returns the updated dependency information when there is a yaml fragmen '\n' + 'Signed-off-by: dependabot[bot] ' - const updatedDependencies = updateMetadata.parse(commitMessage) + const updatedDependencies = updateMetadata.parse(commitMessage, 'dependabot/nuget/feature1', 'main') expect(updatedDependencies).toHaveLength(1) expect(updatedDependencies[0].dependencyName).toEqual('coffee-rails') expect(updatedDependencies[0].dependencyType).toEqual('direct:production') expect(updatedDependencies[0].updateType).toEqual('version-update:semver-minor') + expect(updatedDependencies[0].directory).toEqual('/') + expect(updatedDependencies[0].packageEcosystem).toEqual('nuget') + expect(updatedDependencies[0].targetBranch).toEqual('main') }) test('it supports multiple dependencies within a single fragment', async () => { @@ -59,17 +62,23 @@ test('it supports multiple dependencies within a single fragment', async () => { '\n' + 'Signed-off-by: dependabot[bot] ' - const updatedDependencies = updateMetadata.parse(commitMessage) + const updatedDependencies = updateMetadata.parse(commitMessage, 'dependabot/nuget/api/main/feature1', 'main') expect(updatedDependencies).toHaveLength(2) expect(updatedDependencies[0].dependencyName).toEqual('coffee-rails') expect(updatedDependencies[0].dependencyType).toEqual('direct:production') expect(updatedDependencies[0].updateType).toEqual('version-update:semver-minor') + expect(updatedDependencies[0].directory).toEqual('api/main') + expect(updatedDependencies[0].packageEcosystem).toEqual('nuget') + expect(updatedDependencies[0].targetBranch).toEqual('main') expect(updatedDependencies[1].dependencyName).toEqual('coffeescript') expect(updatedDependencies[1].dependencyType).toEqual('indirect') expect(updatedDependencies[1].updateType).toEqual('version-update:semver-patch') + expect(updatedDependencies[1].directory).toEqual('api/main') + expect(updatedDependencies[1].packageEcosystem).toEqual('nuget') + expect(updatedDependencies[1].targetBranch).toEqual('main') }) test('it only returns information within the first fragment if there are multiple yaml documents', async () => { @@ -95,11 +104,14 @@ test('it only returns information within the first fragment if there are multipl '\n' + 'Signed-off-by: dependabot[bot] ' - const updatedDependencies = updateMetadata.parse(commitMessage) + const updatedDependencies = updateMetadata.parse(commitMessage, 'dependabot|nuget|api|feature1', 'main') expect(updatedDependencies).toHaveLength(1) expect(updatedDependencies[0].dependencyName).toEqual('coffee-rails') expect(updatedDependencies[0].dependencyType).toEqual('direct:production') expect(updatedDependencies[0].updateType).toEqual('version-update:semver-minor') + expect(updatedDependencies[0].directory).toEqual('api') + expect(updatedDependencies[0].packageEcosystem).toEqual('nuget') + expect(updatedDependencies[0].targetBranch).toEqual('main') }) diff --git a/src/dependabot/update_metadata.ts b/src/dependabot/update_metadata.ts index b3b922f3..982ed453 100644 --- a/src/dependabot/update_metadata.ts +++ b/src/dependabot/update_metadata.ts @@ -4,20 +4,30 @@ export interface updatedDependency { dependencyName: string, dependencyType: string, updateType: string, + directory: string, + packageEcosystem: string, + targetBranch: string } -export function parse (commitMessage: string): Array { +export function parse (commitMessage: string, branchName: string, mainBranch: string): Array { const yamlFragment = commitMessage.match(/^-{3}\n(?[\S|\s]*?)\n^\.{3}\n/m) - if (yamlFragment?.groups) { + if (yamlFragment?.groups && branchName.startsWith('dependabot')) { const data = YAML.parse(yamlFragment.groups.dependencies) + const delim = branchName[10] + const chunks = branchName.split(delim) + const dirname = chunks.slice(2, -1).join(delim) || '/' + if (data['updated-dependencies']) { return data['updated-dependencies'].map(dependency => { return { dependencyName: dependency['dependency-name'], dependencyType: dependency['dependency-type'], - updateType: dependency['update-type'] + updateType: dependency['update-type'], + directory: dirname, + packageEcosystem: chunks[1], + targetBranch: mainBranch } }) } diff --git a/src/dependabot/util.ts b/src/dependabot/util.ts index cf503e08..17d436c6 100644 --- a/src/dependabot/util.ts +++ b/src/dependabot/util.ts @@ -1,3 +1,5 @@ +import { Context } from '@actions/github/lib/context' + export function parseNwo (nwo: string): {owner: string; repo: string} { const [owner, name] = nwo.split('/') @@ -7,3 +9,13 @@ export function parseNwo (nwo: string): {owner: string; repo: string} { return { owner: owner, repo: name } } + +export interface branchNames { + headName: string, + baseName: string +} + +export function getBranchNames (context: Context): branchNames { + const { pull_request: pr } = context.payload + return { headName: pr?.head.ref || '', baseName: pr?.base.ref } +} diff --git a/src/dry-run.ts b/src/dry-run.ts index b8397a4e..ddcf7a89 100755 --- a/src/dry-run.ts +++ b/src/dry-run.ts @@ -43,7 +43,7 @@ async function check (args: any): Promise { if (commitMessage) { console.log('This appears to be a valid Dependabot Pull Request.') - const updatedDependencies = parse(commitMessage) + const updatedDependencies = parse(commitMessage, 'dependabot/test_ecosystem/test_directory', 'test_branch') if (updatedDependencies.length > 0) { console.log('Updated dependencies:') diff --git a/src/main.test.ts b/src/main.test.ts index 0ade76df..d6f40e94 100644 --- a/src/main.test.ts +++ b/src/main.test.ts @@ -2,6 +2,7 @@ import * as core from '@actions/core' import { run } from './main' import { RequestError } from '@octokit/request-error' import * as dependabotCommits from './dependabot/verified_commits' +import * as util from './dependabot/util' beforeEach(() => { jest.restoreAllMocks() @@ -13,6 +14,7 @@ beforeEach(() => { test('it early exits with an error if github-token is not set', async () => { jest.spyOn(core, 'getInput').mockReturnValue('') + jest.spyOn(util, 'getBranchNames').mockReturnValue({ headName: 'dependabot|nuget|feature1', baseName: 'main' }) await run() @@ -26,6 +28,7 @@ test('it early exits with an error if github-token is not set', async () => { test('it does nothing if the PR is not verified as from Dependabot', async () => { jest.spyOn(core, 'getInput').mockReturnValue('mock-token') + jest.spyOn(util, 'getBranchNames').mockReturnValue({ headName: 'dependabot|nuget|feature1', baseName: 'main' }) jest.spyOn(dependabotCommits, 'getMessage').mockImplementation(jest.fn( () => Promise.resolve(false) )) @@ -39,6 +42,7 @@ test('it does nothing if the PR is not verified as from Dependabot', async () => test('it does nothing if there is no metadata in the commit', async () => { jest.spyOn(core, 'getInput').mockReturnValue('mock-token') + jest.spyOn(util, 'getBranchNames').mockReturnValue({ headName: 'dependabot|nuget|feature1', baseName: 'main' }) jest.spyOn(dependabotCommits, 'getMessage').mockImplementation(jest.fn( () => Promise.resolve('Just a commit message, nothing to see here.') )) @@ -67,6 +71,7 @@ test('it sets the updated dependency as an output for subsequent actions', async 'Signed-off-by: dependabot[bot] ' jest.spyOn(core, 'getInput').mockReturnValue('mock-token') + jest.spyOn(util, 'getBranchNames').mockReturnValue({ headName: 'dependabot|nuget|feature1', baseName: 'main' }) jest.spyOn(dependabotCommits, 'getMessage').mockImplementation(jest.fn( () => Promise.resolve(mockCommitMessage) )) @@ -84,7 +89,10 @@ test('it sets the updated dependency as an output for subsequent actions', async { dependencyName: 'coffee-rails', dependencyType: 'direct:production', - updateType: 'version-update:semver-minor' + updateType: 'version-update:semver-minor', + directory: '/', + packageEcosystem: 'nuget', + targetBranch: 'main' } ] ) @@ -92,6 +100,9 @@ test('it sets the updated dependency as an output for subsequent actions', async expect(core.setOutput).toBeCalledWith('dependency-names', 'coffee-rails') expect(core.setOutput).toBeCalledWith('dependency-type', 'direct:production') expect(core.setOutput).toBeCalledWith('update-type', 'version-update:semver-minor') + expect(core.setOutput).toBeCalledWith('directory', '/') + expect(core.setOutput).toBeCalledWith('package-ecosystem', 'nuget') + expect(core.setOutput).toBeCalledWith('target_branch', 'main') }) test('if there are multiple dependencies, it summarizes them', async () => { @@ -114,6 +125,7 @@ test('if there are multiple dependencies, it summarizes them', async () => { 'Signed-off-by: dependabot[bot] ' jest.spyOn(core, 'getInput').mockReturnValue('mock-token') + jest.spyOn(util, 'getBranchNames').mockReturnValue({ headName: 'dependabot/npm_and_yarn/api/main/feature1', baseName: 'trunk' }) jest.spyOn(dependabotCommits, 'getMessage').mockImplementation(jest.fn( () => Promise.resolve(mockCommitMessage) )) @@ -131,12 +143,18 @@ test('if there are multiple dependencies, it summarizes them', async () => { { dependencyName: 'coffee-rails', dependencyType: 'direct:production', - updateType: 'version-update:semver-minor' + updateType: 'version-update:semver-minor', + directory: 'api/main', + packageEcosystem: 'npm_and_yarn', + targetBranch: 'trunk' }, { dependencyName: 'coffeescript', dependencyType: 'indirect', - updateType: 'version-update:semver-major' + updateType: 'version-update:semver-major', + directory: 'api/main', + packageEcosystem: 'npm_and_yarn', + targetBranch: 'trunk' } ] ) @@ -144,10 +162,14 @@ test('if there are multiple dependencies, it summarizes them', async () => { expect(core.setOutput).toBeCalledWith('dependency-names', 'coffee-rails, coffeescript') expect(core.setOutput).toBeCalledWith('dependency-type', 'direct:production') expect(core.setOutput).toBeCalledWith('update-type', 'version-update:semver-major') + expect(core.setOutput).toBeCalledWith('directory', 'api/main') + expect(core.setOutput).toBeCalledWith('package-ecosystem', 'npm_and_yarn') + expect(core.setOutput).toBeCalledWith('target_branch', 'trunk') }) test('it sets the action to failed if there is an unexpected exception', async () => { jest.spyOn(core, 'getInput').mockReturnValue('mock-token') + jest.spyOn(util, 'getBranchNames').mockReturnValue({ headName: 'dependabot|nuget|feature1', baseName: 'main' }) jest.spyOn(dependabotCommits, 'getMessage').mockImplementation(jest.fn( () => Promise.reject(new Error('Something bad happened!')) )) @@ -161,6 +183,7 @@ test('it sets the action to failed if there is an unexpected exception', async ( test('it sets the action to failed if there is a request error', async () => { jest.spyOn(core, 'getInput').mockReturnValue('mock-token') + jest.spyOn(util, 'getBranchNames').mockReturnValue({ headName: 'dependabot|nuget|feature1', baseName: 'main' }) jest.spyOn(dependabotCommits, 'getMessage').mockImplementation(jest.fn( () => Promise.reject(new RequestError('Something bad happened!', 500, { headers: {}, diff --git a/src/main.ts b/src/main.ts index 8298e837..40a9bff1 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,6 +4,7 @@ import { RequestError } from '@octokit/request-error' import * as verifiedCommits from './dependabot/verified_commits' import * as updateMetadata from './dependabot/update_metadata' import * as output from './dependabot/output' +import * as util from './dependabot/util' export async function run (): Promise { const token = core.getInput('github-token') @@ -22,12 +23,13 @@ export async function run (): Promise { // Validate the job const commitMessage = await verifiedCommits.getMessage(githubClient, github.context) + const branchNames = util.getBranchNames(github.context) if (commitMessage) { // Parse metadata core.info('Parsing Dependabot metadata') - const updatedDependencies = updateMetadata.parse(commitMessage) + const updatedDependencies = updateMetadata.parse(commitMessage, branchNames.headName, branchNames.baseName) if (updatedDependencies.length > 0) { output.set(updatedDependencies) From 4d237c6cf08834a7c5835246ebbca53d51541fe3 Mon Sep 17 00:00:00 2001 From: Michael Waddell Date: Wed, 9 Feb 2022 13:42:39 -0600 Subject: [PATCH 2/7] Update src/dependabot/update_metadata.ts Co-authored-by: Nish Sinha --- src/dependabot/update_metadata.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dependabot/update_metadata.ts b/src/dependabot/update_metadata.ts index 982ed453..756a4c14 100644 --- a/src/dependabot/update_metadata.ts +++ b/src/dependabot/update_metadata.ts @@ -15,7 +15,8 @@ export function parse (commitMessage: string, branchName: string, mainBranch: st if (yamlFragment?.groups && branchName.startsWith('dependabot')) { const data = YAML.parse(yamlFragment.groups.dependencies) - const delim = branchName[10] + # 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 dirname = chunks.slice(2, -1).join(delim) || '/' From 9967bee0bad56831ed79cfe8f1b632102d52f304 Mon Sep 17 00:00:00 2001 From: Michael Waddell Date: Wed, 9 Feb 2022 13:45:29 -0600 Subject: [PATCH 3/7] fixing comment style --- src/dependabot/update_metadata.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dependabot/update_metadata.ts b/src/dependabot/update_metadata.ts index 756a4c14..2533bc7b 100644 --- a/src/dependabot/update_metadata.ts +++ b/src/dependabot/update_metadata.ts @@ -15,7 +15,7 @@ export function parse (commitMessage: string, branchName: string, mainBranch: st if (yamlFragment?.groups && branchName.startsWith('dependabot')) { const data = YAML.parse(yamlFragment.groups.dependencies) - # Since we are on the `dependabot` branch (9 letters), the 10th letter in the branch name is the delimiter + // 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 dirname = chunks.slice(2, -1).join(delim) || '/' From 74c5483adb28c5bd0b87d5ce4dbbe37af2572164 Mon Sep 17 00:00:00 2001 From: Michael Waddell Date: Wed, 9 Feb 2022 13:45:56 -0600 Subject: [PATCH 4/7] Using branchNames per @Nishnha's suggestion --- dist/index.js | 1 + src/dry-run.ts | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/dist/index.js b/dist/index.js index 6deb35ae..fbdabbd5 100644 --- a/dist/index.js +++ b/dist/index.js @@ -13410,6 +13410,7 @@ function parse(commitMessage, branchName, mainBranch) { const yamlFragment = commitMessage.match(/^-{3}\n(?[\S|\s]*?)\n^\.{3}\n/m); if ((yamlFragment === null || yamlFragment === void 0 ? void 0 : yamlFragment.groups) && branchName.startsWith('dependabot')) { const data = yaml.parse(yamlFragment.groups.dependencies); + // 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 dirname = chunks.slice(2, -1).join(delim) || '/'; diff --git a/src/dry-run.ts b/src/dry-run.ts index ddcf7a89..f9597d13 100755 --- a/src/dry-run.ts +++ b/src/dry-run.ts @@ -7,7 +7,7 @@ import { hideBin } from 'yargs/helpers' import { getMessage } from './dependabot/verified_commits' import { parse } from './dependabot/update_metadata' -import { parseNwo } from './dependabot/util' +import { getBranchNames, parseNwo } from './dependabot/util' async function check (args: any): Promise { try { @@ -42,8 +42,9 @@ async function check (args: any): Promise { if (commitMessage) { console.log('This appears to be a valid Dependabot Pull Request.') + const branchNames = getBranchNames(github.context) - const updatedDependencies = parse(commitMessage, 'dependabot/test_ecosystem/test_directory', 'test_branch') + const updatedDependencies = parse(commitMessage, branchNames.headName, branchNames.baseName) if (updatedDependencies.length > 0) { console.log('Updated dependencies:') From 7b566f4b942ebebc884426ae6b42e1c8fc3d9a90 Mon Sep 17 00:00:00 2001 From: Michael Waddell Date: Wed, 9 Feb 2022 13:56:31 -0600 Subject: [PATCH 5/7] linting --- src/dependabot/update_metadata.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dependabot/update_metadata.ts b/src/dependabot/update_metadata.ts index 2533bc7b..36ac2ced 100644 --- a/src/dependabot/update_metadata.ts +++ b/src/dependabot/update_metadata.ts @@ -16,7 +16,7 @@ export function parse (commitMessage: string, branchName: string, mainBranch: st const data = YAML.parse(yamlFragment.groups.dependencies) // Since we are on the `dependabot` branch (9 letters), the 10th letter in the branch name is the delimiter - const delim = branchName[10] + const delim = branchName[10] const chunks = branchName.split(delim) const dirname = chunks.slice(2, -1).join(delim) || '/' From ca81f5871d88aacebe621c4f62eeb67678300204 Mon Sep 17 00:00:00 2001 From: Michael Waddell Date: Wed, 9 Feb 2022 14:20:09 -0600 Subject: [PATCH 6/7] have to make a call-out to get the details of the PR --- src/dry-run.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/dry-run.ts b/src/dry-run.ts index f9597d13..c5327b29 100755 --- a/src/dry-run.ts +++ b/src/dry-run.ts @@ -39,10 +39,17 @@ async function check (args: any): Promise { // Retries the commit message if the PR is from Dependabot const commitMessage = await getMessage(githubClient, actionContext) + const pull_request: any = await (await githubClient.rest.pulls.get({ owner: repoDetails.owner, repo: repoDetails.repo, pull_number: args.prNumber })).data + + const newContext = new Context() + newContext.payload = { + pull_request: pull_request, + repository: actionContext.payload.repository + } if (commitMessage) { console.log('This appears to be a valid Dependabot Pull Request.') - const branchNames = getBranchNames(github.context) + const branchNames = getBranchNames(newContext) const updatedDependencies = parse(commitMessage, branchNames.headName, branchNames.baseName) From aa297d42a6757363260fc555bac125addfaa4cc4 Mon Sep 17 00:00:00 2001 From: Michael Waddell Date: Wed, 9 Feb 2022 14:21:04 -0600 Subject: [PATCH 7/7] linting --- src/dry-run.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dry-run.ts b/src/dry-run.ts index c5327b29..8d7343a0 100755 --- a/src/dry-run.ts +++ b/src/dry-run.ts @@ -39,11 +39,11 @@ async function check (args: any): Promise { // Retries the commit message if the PR is from Dependabot const commitMessage = await getMessage(githubClient, actionContext) - const pull_request: any = await (await githubClient.rest.pulls.get({ owner: repoDetails.owner, repo: repoDetails.repo, pull_number: args.prNumber })).data + const pullRequest: any = await (await githubClient.rest.pulls.get({ owner: repoDetails.owner, repo: repoDetails.repo, pull_number: args.prNumber })).data const newContext = new Context() newContext.payload = { - pull_request: pull_request, + pull_request: pullRequest, repository: actionContext.payload.repository }