From d2b39a9c26f7e1d9faa18854b990729228a62d16 Mon Sep 17 00:00:00 2001 From: Guilherme Kammsetzer <6863574+guilhermelimak@users.noreply.github.com> Date: Tue, 12 Apr 2022 18:32:10 -0300 Subject: [PATCH] Fix/fallback to title parsing (#182) * fix: fallback to PR title parsing for non package.json modules * test: remove .only from tests * test: add more PR title parsing test cases --- dist/index.js | 19 ++++++++++-- src/action.js | 17 ++++++++++- src/moduleVersionChanges.js | 2 +- test/action.test.js | 59 +++++++++++++++++++++++++++++++++++-- test/moduleChanges.js | 25 ++++++++-------- 5 files changed, 104 insertions(+), 18 deletions(-) diff --git a/dist/index.js b/dist/index.js index d5229ea4..17e9bcab 100644 --- a/dist/index.js +++ b/dist/index.js @@ -9338,7 +9338,9 @@ module.exports = async function run() { } const prDiff = await client.getPullRequestDiff(pr.number) - const moduleChanges = getModuleVersionChanges(prDiff) + + // Get changed modules from diff if available or from PR title as fallback + const moduleChanges = getModuleVersionChanges(prDiff) || parsePrTitle(pr) if (TARGET !== targetOptions.any) { logInfo(`Checking if the changes in the PR can be merged`) @@ -9389,6 +9391,19 @@ function isAMajorReleaseBump(change) { return diff === targetOptions.major } +function parsePrTitle(pullRequest) { + const expression = /bump (\S+) from (\S+) to (\S+)/i + const match = expression.exec(pullRequest.title) + + if (!match) { + return {} + } + + const [, packageName, oldVersion, newVersion] = match + + return { [packageName]: { delete: semverCoerce(oldVersion).raw, insert: semverCoerce(newVersion).raw } } +} + /***/ }), @@ -9569,7 +9584,7 @@ const getModuleVersionChanges = (prDiff) => { const parsedDiffFiles = parse(prDiff) const packageJsonChanges = parsedDiffFiles.find((file) => file.newPath === 'package.json') if (!packageJsonChanges) { - return {} + return false } const moduleChanges = {} diff --git a/src/action.js b/src/action.js index 09daff46..c0da3eb6 100644 --- a/src/action.js +++ b/src/action.js @@ -48,7 +48,9 @@ module.exports = async function run() { } const prDiff = await client.getPullRequestDiff(pr.number) - const moduleChanges = getModuleVersionChanges(prDiff) + + // Get changed modules from diff if available or from PR title as fallback + const moduleChanges = getModuleVersionChanges(prDiff) || parsePrTitle(pr) if (TARGET !== targetOptions.any) { logInfo(`Checking if the changes in the PR can be merged`) @@ -98,3 +100,16 @@ function isAMajorReleaseBump(change) { const diff = semverDiff(semverCoerce(from), semverCoerce(to)) return diff === targetOptions.major } + +function parsePrTitle(pullRequest) { + const expression = /bump (\S+) from (\S+) to (\S+)/i + const match = expression.exec(pullRequest.title) + + if (!match) { + return {} + } + + const [, packageName, oldVersion, newVersion] = match + + return { [packageName]: { delete: semverCoerce(oldVersion).raw, insert: semverCoerce(newVersion).raw } } +} diff --git a/src/moduleVersionChanges.js b/src/moduleVersionChanges.js index 8fa1f29e..662b75c2 100644 --- a/src/moduleVersionChanges.js +++ b/src/moduleVersionChanges.js @@ -45,7 +45,7 @@ const getModuleVersionChanges = (prDiff) => { const parsedDiffFiles = parse(prDiff) const packageJsonChanges = parsedDiffFiles.find((file) => file.newPath === 'package.json') if (!packageJsonChanges) { - return {} + return false } const moduleChanges = {} diff --git a/test/action.test.js b/test/action.test.js index adbb48c7..eadceb80 100644 --- a/test/action.test.js +++ b/test/action.test.js @@ -289,18 +289,20 @@ tap.test('should check submodules semver when target is set', async () => { sinon.assert.notCalled(stubs.mergeStub) }) -tap.test('should merge if no changes were made to package.json', async () => { +tap.test('should merge major bump using PR title', async () => { const PR_NUMBER = Math.random() + const { action, stubs } = buildStubbedAction({ payload: { pull_request: { number: PR_NUMBER, user: { login: BOT_NAME }, + title: 'build(deps): bump actions/checkout from 2 to 3' } }, inputs: { PR_NUMBER, - TARGET: 'main', + TARGET: 'major', EXCLUDE_PKGS: ['react'], } }) @@ -312,3 +314,56 @@ tap.test('should merge if no changes were made to package.json', async () => { sinon.assert.called(stubs.approveStub) sinon.assert.called(stubs.mergeStub) }) + +tap.test('should forbid major bump using PR title', async () => { + const PR_NUMBER = Math.random() + + const { action, stubs } = buildStubbedAction({ + payload: { + pull_request: { + number: PR_NUMBER, + user: { login: BOT_NAME }, + title: 'build(deps): bump actions/checkout from 2 to 3' + } + }, + inputs: { + PR_NUMBER, + TARGET: 'minor', + EXCLUDE_PKGS: ['react'], + } + }) + + stubs.prDiffStub.resolves(diffs.noPackageJsonChanges) + + await action() + + sinon.assert.notCalled(stubs.approveStub) + sinon.assert.notCalled(stubs.mergeStub) +}) + + +tap.test('should not merge major bump if updating github-action-merge-dependabot', async () => { + const PR_NUMBER = Math.random() + + const { action, stubs } = buildStubbedAction({ + payload: { + pull_request: { + number: PR_NUMBER, + user: { login: BOT_NAME }, + title: 'build(deps): bump github-action-merge-dependabot from 2 to 3' + } + }, + inputs: { + PR_NUMBER, + TARGET: 'any', + EXCLUDE_PKGS: ['react'], + } + }) + + stubs.prDiffStub.resolves(diffs.noPackageJsonChanges) + + await action() + + sinon.assert.notCalled(stubs.approveStub) + sinon.assert.notCalled(stubs.mergeStub) +}) diff --git a/test/moduleChanges.js b/test/moduleChanges.js index 936166e9..c64a277f 100644 --- a/test/moduleChanges.js +++ b/test/moduleChanges.js @@ -148,18 +148,19 @@ index d3dfd3d..bd28161 100644 + "github-action-merge-dependabot": "2.1.0", `, noPackageJsonChanges: ` -diff --git a/test/action.test.js b/test/action.test.js -index e8c6572..751e69d 100644 ---- a/test/action.test.js -+++ b/test/action.test.js -@@ -9,6 +9,7 @@ const core = require('@actions/core') - const github = require('@actions/github') - const toolkit = require('actions-toolkit') - -+ - const { diffs } = require('./moduleChanges') - const actionLog = require('../src/log') - const actionUtil = require('../src/util') +diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml +index e790278..678e751 100644 +--- a/.github/workflows/ci.yml ++++ b/.github/workflows/ci.yml +@@ -4,7 +4,7 @@ jobs: + build: + runs-on: ubuntu-latest + steps: +- - uses: actions/checkout@v2 ++ - uses: actions/checkout@v3 + - uses: actions/setup-node@v3 + with: + node-version-file: '.nvmrc' ` }