Skip to content

Commit

Permalink
Allow auto-merge to be configurable
Browse files Browse the repository at this point in the history
Add a new input setting that, if present, allows selecting also those
PRs that don't have the `auto-merge` enabled.

Fixes: #17
  • Loading branch information
rmariano committed Aug 31, 2023
1 parent 00f3aa1 commit 5f4c351
Show file tree
Hide file tree
Showing 7 changed files with 4,081 additions and 4,036 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@ Notice: this is an option provided by github rest api. In this github action, we

The direction of the sort. Can be either `asc` or `desc`. Default: `desc` when sort is `created` or sort is not specified, otherwise `asc`.

### `require_auto_merge_enabled`

**Optional**

Check if having auto-merge enabled in the PR is required, in order for the PR to
be considered. It defaults to `true`, but if set to `false`, all PRs are
considered for update (not just those with auto-merge enabled.)

This github action doesn't set any default parameters.

## Example usage
Expand All @@ -100,6 +108,7 @@ jobs:
require_passed_checks: false
sort: 'created'
direction: 'desc'
require_auto_merge_enabled: false
```
Replace the `VERSION_YOU_WANT_TO_USE` with the actual version you want to use, check the version format [here](https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstepsuses)
Expand Down
175 changes: 74 additions & 101 deletions dest/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1461,7 +1461,7 @@ exports.Octokit = Octokit;

Object.defineProperty(exports, "__esModule", ({ value: true }));

var isPlainObject = __nccwpck_require__(558);
var isPlainObject = __nccwpck_require__(287);
var universalUserAgent = __nccwpck_require__(429);

function lowercaseKeys(object) {
Expand Down Expand Up @@ -1849,52 +1849,6 @@ exports.endpoint = endpoint;
//# sourceMappingURL=index.js.map


/***/ }),

/***/ 558:
/***/ ((__unused_webpack_module, exports) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({ value: true }));

/*!
* is-plain-object <https://github.com/jonschlinkert/is-plain-object>
*
* Copyright (c) 2014-2017, Jon Schlinkert.
* Released under the MIT License.
*/

function isObject(o) {
return Object.prototype.toString.call(o) === '[object Object]';
}

function isPlainObject(o) {
var ctor,prot;

if (isObject(o) === false) return false;

// If has modified constructor
ctor = o.constructor;
if (ctor === undefined) return true;

// If has modified prototype
prot = ctor.prototype;
if (isObject(prot) === false) return false;

// If constructor does not have an Object-specific method
if (prot.hasOwnProperty('isPrototypeOf') === false) {
return false;
}

// Most likely a plain Object
return true;
}

exports.isPlainObject = isPlainObject;


/***/ }),

/***/ 668:
Expand Down Expand Up @@ -3382,7 +3336,7 @@ function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'defau

var endpoint = __nccwpck_require__(440);
var universalUserAgent = __nccwpck_require__(429);
var isPlainObject = __nccwpck_require__(62);
var isPlainObject = __nccwpck_require__(287);
var nodeFetch = _interopDefault(__nccwpck_require__(467));
var requestError = __nccwpck_require__(537);

Expand Down Expand Up @@ -3524,52 +3478,6 @@ exports.request = request;
//# sourceMappingURL=index.js.map


/***/ }),

/***/ 62:
/***/ ((__unused_webpack_module, exports) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({ value: true }));

/*!
* is-plain-object <https://github.com/jonschlinkert/is-plain-object>
*
* Copyright (c) 2014-2017, Jon Schlinkert.
* Released under the MIT License.
*/

function isObject(o) {
return Object.prototype.toString.call(o) === '[object Object]';
}

function isPlainObject(o) {
var ctor,prot;

if (isObject(o) === false) return false;

// If has modified constructor
ctor = o.constructor;
if (ctor === undefined) return true;

// If has modified prototype
prot = ctor.prototype;
if (isObject(prot) === false) return false;

// If constructor does not have an Object-specific method
if (prot.hasOwnProperty('isPrototypeOf') === false) {
return false;
}

// Most likely a plain Object
return true;
}

exports.isPlainObject = isPlainObject;


/***/ }),

/***/ 682:
Expand Down Expand Up @@ -3775,6 +3683,52 @@ class Deprecation extends Error {
exports.Deprecation = Deprecation;


/***/ }),

/***/ 287:
/***/ ((__unused_webpack_module, exports) => {

"use strict";


Object.defineProperty(exports, "__esModule", ({ value: true }));

/*!
* is-plain-object <https://github.com/jonschlinkert/is-plain-object>
*
* Copyright (c) 2014-2017, Jon Schlinkert.
* Released under the MIT License.
*/

function isObject(o) {
return Object.prototype.toString.call(o) === '[object Object]';
}

function isPlainObject(o) {
var ctor,prot;

if (isObject(o) === false) return false;

// If has modified constructor
ctor = o.constructor;
if (ctor === undefined) return true;

// If has modified prototype
prot = ctor.prototype;
if (isObject(prot) === false) return false;

// If constructor does not have an Object-specific method
if (prot.hasOwnProperty('isPrototypeOf') === false) {
return false;
}

// Most likely a plain Object
return true;
}

exports.isPlainObject = isPlainObject;


/***/ }),

/***/ 467:
Expand Down Expand Up @@ -5841,7 +5795,13 @@ var core = __nccwpck_require__(186);
// CONCATENATED MODULE: ./src/lib/github.js
const github_core = __nccwpck_require__(186);
const github = __nccwpck_require__(438);
const { log, printFailReason, wait, isStringTrue } = __nccwpck_require__(103);
const {
log,
printFailReason,
wait,
isStringTrue,
isStringFalse,
} = __nccwpck_require__(103);

const getOctokit = () => {
const token = github_core.getInput('token');
Expand Down Expand Up @@ -5988,6 +5948,20 @@ const getApprovalStatus = async (pullNumber) => {
};
};

const filterApplicablePRs = (openPRs) => {
const autoMergeEnabledConfigured = github_core.getInput(
'require_auto_merge_enabled',
);
if (
autoMergeEnabledConfigured === false ||
isStringFalse(autoMergeEnabledConfigured)
) {
return openPRs;
}
const autoMergeEnabledPRs = openPRs.filter((item) => item.auto_merge);
log(`Count of auto-merge enabled PRs: ${autoMergeEnabledPRs.length}`);
return autoMergeEnabledPRs;
};
/**
* find a applicable PR to update
*/
Expand All @@ -5997,12 +5971,9 @@ const getAutoUpdateCandidate = async (openPRs) => {
const requirePassedChecks = isStringTrue(
github_core.getInput('require_passed_checks'),
);
const applicablePRs = filterApplicablePRs(openPRs);

// only update `auto merge` enabled PRs
const autoMergeEnabledPRs = openPRs.filter((item) => item.auto_merge);
log(`Count of auto-merge enabled PRs: ${autoMergeEnabledPRs.length}`);

for (const pr of autoMergeEnabledPRs) {
for (const pr of applicablePRs) {
const {
number: pullNumber,
head: { sha },
Expand Down Expand Up @@ -6106,13 +6077,15 @@ __nccwpck_require__.r(__webpack_exports__);
/* harmony export */ "log": () => /* binding */ log,
/* harmony export */ "printFailReason": () => /* binding */ printFailReason,
/* harmony export */ "wait": () => /* binding */ wait,
/* harmony export */ "isStringTrue": () => /* binding */ isStringTrue
/* harmony export */ "isStringTrue": () => /* binding */ isStringTrue,
/* harmony export */ "isStringFalse": () => /* binding */ isStringFalse
/* harmony export */ });
const log = console.info.bind(null, 'LOG >');
const printFailReason = (pullNumber, reason) =>
log(`Won't update #${pullNumber}, the reason:\n > ${reason}`);
const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const isStringTrue = (str = '') => str.toLowerCase() === 'true';
const isStringFalse = (str = '') => str.toLowerCase() === 'false';


/***/ }),
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "update-pr-branch",
"version": "0.1.0",
"version": "0.1.1",
"description": "Automatically update PR branch",
"main": "dest/index.js",
"scripts": {
Expand Down
29 changes: 23 additions & 6 deletions src/lib/github.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
const core = require('@actions/core');
const github = require('@actions/github');
const { log, printFailReason, wait, isStringTrue } = require('./util');
const {
log,
printFailReason,
wait,
isStringTrue,
isStringFalse,
} = require('./util');

const getOctokit = () => {
const token = core.getInput('token');
Expand Down Expand Up @@ -147,6 +153,20 @@ export const getApprovalStatus = async (pullNumber) => {
};
};

export const filterApplicablePRs = (openPRs) => {
const autoMergeEnabledConfigured = core.getInput(
'require_auto_merge_enabled',
);
if (
autoMergeEnabledConfigured === false ||
isStringFalse(autoMergeEnabledConfigured)
) {
return openPRs;
}
const autoMergeEnabledPRs = openPRs.filter((item) => item.auto_merge);
log(`Count of auto-merge enabled PRs: ${autoMergeEnabledPRs.length}`);
return autoMergeEnabledPRs;
};
/**
* find a applicable PR to update
*/
Expand All @@ -156,12 +176,9 @@ export const getAutoUpdateCandidate = async (openPRs) => {
const requirePassedChecks = isStringTrue(
core.getInput('require_passed_checks'),
);
const applicablePRs = filterApplicablePRs(openPRs);

// only update `auto merge` enabled PRs
const autoMergeEnabledPRs = openPRs.filter((item) => item.auto_merge);
log(`Count of auto-merge enabled PRs: ${autoMergeEnabledPRs.length}`);

for (const pr of autoMergeEnabledPRs) {
for (const pr of applicablePRs) {
const {
number: pullNumber,
head: { sha },
Expand Down
9 changes: 9 additions & 0 deletions src/lib/github.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,15 @@ describe('getAutoUpdateCandidate()', () => {
expect(res).toBe(null);
});

[false, 'false'].forEach((value) => {
test(`Filter applicable PRs can exclude auto-merge if configured with ${value} (${typeof value})`, async () => {
const data = { require_auto_merge_enabled: value };
core.getInput.mockImplementation((name) => data[name]);
const obtained = gitLib.filterApplicablePRs(pullsList);
expect(obtained.length).toBe(pullsList.length);
});
});

test('PR with request-for-change review will not be selected', async () => {
const prList = [{ ...pullsList.data[0], auto_merge: {} }];
const mockedListReviews = jest.fn().mockResolvedValue(reviewsList);
Expand Down
1 change: 1 addition & 0 deletions src/lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export const printFailReason = (pullNumber, reason) =>
log(`Won't update #${pullNumber}, the reason:\n > ${reason}`);
export const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
export const isStringTrue = (str = '') => str.toLowerCase() === 'true';
export const isStringFalse = (str = '') => str.toLowerCase() === 'false';
Loading

0 comments on commit 5f4c351

Please sign in to comment.