diff --git a/README.md b/README.md index 2f639467..bc7dc164 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ All configuration values, except `GITHUB_TOKEN`, are optional. - `"all"` (default): No filter, _autoupdate_ will monitor and update all pull requests. - `"labelled"`: Only monitor PRs with a particular label (or set of labels). Requires the `PR_LABELS` option to be defined to. If `PR_LABELS` is not defined, _autoupdate_ will not monitor any pull requests. - `"protected"`: Only monitor PRs that are raised against [protected branches](https://help.github.com/en/github/administering-a-repository/about-protected-branches). + - `"auto_merge"`: Only monitor PRs that have ['auto merge'](https://docs.github.com/en/github/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/automatically-merging-a-pull-request) enabled - `PR_LABELS`: Controls which labels _autoupdate_ will look for when monitoring PRs. Only used if `PR_FILTER="labelled"`. This can be either a single label or a comma-separated list of labels. diff --git a/src/autoupdater.ts b/src/autoupdater.ts index 53c5108a..fa4770a7 100644 --- a/src/autoupdater.ts +++ b/src/autoupdater.ts @@ -341,7 +341,7 @@ export class AutoUpdater { return false; } - if (this.config.pullRequestFilter() === 'protected') { + if (prFilter === 'protected') { ghCore.info('Checking if this PR is against a protected branch.'); const { data: branch } = await this.octokit.repos.getBranch({ owner: pull.head.repo.owner.login, @@ -362,6 +362,24 @@ export class AutoUpdater { return false; } + if (prFilter === 'auto_merge') { + ghCore.info('Checking if this PR has auto_merge enabled.'); + + if (pull.auto_merge === null) { + ghCore.info( + 'Pull request does not have auto_merge enabled, skipping update.', + ); + + return false; + } + + ghCore.info( + 'Pull request has auto_merge enabled and is behind base branch.', + ); + + return true; + } + ghCore.info('All checks pass and PR branch is behind base branch.'); return true; } diff --git a/src/config-loader.ts b/src/config-loader.ts index be5ed4ff..d787bd6c 100644 --- a/src/config-loader.ts +++ b/src/config-loader.ts @@ -15,7 +15,7 @@ export class ConfigLoader { } pullRequestFilter(): string { - // one of 'all', 'protected' or 'labelled'. + // one of 'all', 'protected', 'labelled' or 'auto_merge'. return this.getValue('PR_FILTER', false, 'all'); } diff --git a/test/autoupdate.test.ts b/test/autoupdate.test.ts index bc68072b..dcefb054 100644 --- a/test/autoupdate.test.ts +++ b/test/autoupdate.test.ts @@ -434,6 +434,59 @@ describe('test `prNeedsUpdate`', () => { expect(config.excludedLabels).toHaveBeenCalled(); }); + test('pull request is against branch with auto_merge enabled', async () => { + (config.pullRequestFilter as jest.Mock).mockReturnValue('auto_merge'); + (config.excludedLabels as jest.Mock).mockReturnValue([]); + + const comparePr = nock('https://api.github.com:443') + .get(`/repos/${owner}/${repo}/compare/${head}...${base}`) + .reply(200, { + behind_by: 1, + }); + + const updater = new AutoUpdater(config, emptyEvent); + + const pull = { + ...validPull, + auto_merge: { + enabled_by: { + login: 'chinthakagodawita', + }, + merge_method: 'squash', + commit_title: 'some-commit-title', + commit_message: 'fixing a thing', + }, + } as unknown as PullRequestResponse['data']; + const needsUpdate = await updater.prNeedsUpdate(pull); + + expect(needsUpdate).toEqual(true); + expect(comparePr.isDone()).toEqual(true); + expect(config.pullRequestFilter).toHaveBeenCalled(); + }); + + test('pull request is against branch with auto_merge disabled', async () => { + (config.pullRequestFilter as jest.Mock).mockReturnValue('auto_merge'); + (config.excludedLabels as jest.Mock).mockReturnValue([]); + + const comparePr = nock('https://api.github.com:443') + .get(`/repos/${owner}/${repo}/compare/${head}...${base}`) + .reply(200, { + behind_by: 1, + }); + + const updater = new AutoUpdater(config, emptyEvent); + + const pull = { + ...validPull, + auto_merge: null, + } as unknown as PullRequestResponse['data']; + const needsUpdate = await updater.prNeedsUpdate(pull); + + expect(needsUpdate).toEqual(false); + expect(comparePr.isDone()).toEqual(true); + expect(config.pullRequestFilter).toHaveBeenCalled(); + }); + test('no filters configured', async () => { (config.pullRequestFilter as jest.Mock).mockReturnValue('all'); (config.excludedLabels as jest.Mock).mockReturnValue([]);