Skip to content

Commit c96e4e8

Browse files
committed
Add support for remote config urls and github repos
1 parent 481d359 commit c96e4e8

File tree

5 files changed

+315
-117
lines changed

5 files changed

+315
-117
lines changed

action.yml

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,39 @@
1-
name: "PR Title Checker"
2-
description: "Checks if the PR Title follows contribution guidelines."
1+
name: PR Title Checker
2+
description: Checks if the PR Title follows contribution guidelines
33
branding:
4-
icon: "tag"
5-
color: "purple"
6-
4+
icon: tag
5+
color: purple
76
inputs:
87
GITHUB_TOKEN:
9-
description: "Override GitHub Token"
8+
description: Override GitHub Token
109
required: false
11-
use_local_configuration_file:
12-
description: "use a local configuration file rather than pulling one from the repo"
13-
default: "false"
1410
pass_on_octokit_error:
15-
description: "force CI to pass if an octokit error (e.g. missing GITHUB_TOKEN) occurs"
16-
default: "false"
11+
description: force CI to pass if an octokit error (e.g. missing GITHUB_TOKEN) occurs
12+
default: false
1713
configuration_path:
18-
description: "config file path"
19-
default: ".github/pr-title-checker-config.json"
20-
14+
description: config file path
15+
default: .github/pr-title-checker-config.json
16+
local_configuration_path:
17+
description: use a local configuration file present in file system of the instance running the action
18+
required: false
19+
remote_configuration_url:
20+
description: pull local configuration file from the internet using the url provided
21+
required: false
22+
github_configuration_owner:
23+
description: the owner of the repo in which the config file is present. defaults to the owner of the repo in which the action is run
24+
required: false
25+
github_configuration_repo:
26+
description: the repo in which the config file is present. defaults to the repo in which the action is run
27+
required: false
28+
github_configuration_path:
29+
description: the path to the config file in the github repo. defaults to .github/pr-title-checker-config.json
30+
required: false
31+
github_configuration_ref:
32+
description: the named branch, tag, or SHA from which the config file is pulled. defaults to the latest commit on the default branch
33+
required: false
34+
github_configuration_token:
35+
description: the github access token to be used to access the config file using other github_configuration_* parameters. can differ from GITHUB_TOKEN. defaults to GITHUB_TOKEN
36+
required: false
2137
runs:
22-
using: "node16"
23-
main: "dist/index.js"
38+
using: node16
39+
main: dist/index.js

dist/index.js

Lines changed: 118 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -9839,15 +9839,21 @@ var __webpack_exports__ = {};
98399839
// This entry need to be wrapped in an IIFE because it need to be in strict mode.
98409840
(() => {
98419841
"use strict";
9842+
// ESM COMPAT FLAG
98429843
__nccwpck_require__.r(__webpack_exports__);
9843-
/* harmony import */ var _actions_github__WEBPACK_IMPORTED_MODULE_0__ = __nccwpck_require__(5438);
9844-
/* harmony import */ var _actions_github__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__nccwpck_require__.n(_actions_github__WEBPACK_IMPORTED_MODULE_0__);
9845-
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_1__ = __nccwpck_require__(2186);
9846-
/* harmony import */ var _actions_core__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__nccwpck_require__.n(_actions_core__WEBPACK_IMPORTED_MODULE_1__);
9847-
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2__ = __nccwpck_require__(7147);
9848-
/* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__nccwpck_require__.n(fs__WEBPACK_IMPORTED_MODULE_2__);
9849-
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3__ = __nccwpck_require__(1017);
9850-
/* harmony import */ var path__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__nccwpck_require__.n(path__WEBPACK_IMPORTED_MODULE_3__);
9844+
9845+
// EXTERNAL MODULE: ./node_modules/@actions/github/lib/github.js
9846+
var github = __nccwpck_require__(5438);
9847+
// EXTERNAL MODULE: ./node_modules/@actions/core/lib/core.js
9848+
var core = __nccwpck_require__(2186);
9849+
// EXTERNAL MODULE: external "fs"
9850+
var external_fs_ = __nccwpck_require__(7147);
9851+
// EXTERNAL MODULE: external "path"
9852+
var external_path_ = __nccwpck_require__(1017);
9853+
;// CONCATENATED MODULE: external "node:https"
9854+
const external_node_https_namespaceObject = require("node:https");
9855+
var external_node_https_default = /*#__PURE__*/__nccwpck_require__.n(external_node_https_namespaceObject);
9856+
;// CONCATENATED MODULE: ./dist/index.js
98519857
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
98529858
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
98539859
return new (P || (P = Promise))(function (resolve, reject) {
@@ -9861,71 +9867,72 @@ var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _argume
98619867

98629868

98639869

9864-
const context = _actions_github__WEBPACK_IMPORTED_MODULE_0__.context;
9870+
9871+
const context = github.context;
98659872
let octokit;
9866-
function titleCheckFailed({ config: { MESSAGES, LABEL, CHECKS } }) {
9873+
function titleCheckFailed({ config: { MESSAGES, LABEL, CHECKS }, }) {
98679874
return __awaiter(this, void 0, void 0, function* () {
98689875
try {
98699876
if (MESSAGES.notice.length) {
9870-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.notice(MESSAGES.notice);
9877+
core.notice(MESSAGES.notice);
98719878
}
98729879
yield addLabel({ name: LABEL.name });
98739880
if (CHECKS.alwaysPassCI) {
9874-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.info(MESSAGES.failure);
9881+
core.info(MESSAGES.failure);
98759882
}
98769883
else {
9877-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.setFailed(MESSAGES.failure);
9884+
core.setFailed(MESSAGES.failure);
98789885
}
98799886
}
98809887
catch (error) {
9881-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.info(error);
9888+
core.info(error);
98829889
if (CHECKS.alwaysPassCI) {
9883-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.info(`Failed to add label (${LABEL.name}) to PR`);
9890+
core.info(`Failed to add label (${LABEL.name}) to PR`);
98849891
}
98859892
else {
9886-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.setFailed(`Failed to add label (${LABEL.name}) to PR`);
9893+
core.setFailed(`Failed to add label (${LABEL.name}) to PR`);
98879894
}
98889895
}
98899896
});
98909897
}
9891-
function createLabel({ label: { name, color } }) {
9898+
function createLabel({ label: { name, color }, }) {
98929899
return __awaiter(this, void 0, void 0, function* () {
9893-
if (name === '') {
9900+
if (name === "") {
98949901
return;
98959902
}
98969903
try {
9897-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.info(`Creating label (${name})...`);
9904+
core.info(`Creating label (${name})...`);
98989905
let createResponse = yield octokit.rest.issues.createLabel({
98999906
owner: context.repo.owner,
99009907
repo: context.repo.repo,
99019908
name: name,
99029909
color: color,
99039910
});
9904-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.info(`Created label (${name}) - ${createResponse.status}`);
9911+
core.info(`Created label (${name}) - ${createResponse.status}`);
99059912
}
99069913
catch (error) {
9907-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.info(`Label (${name}) already created.`);
9914+
core.info(`Label (${name}) already created.`);
99089915
}
99099916
});
99109917
}
99119918
function addLabel({ name }) {
99129919
return __awaiter(this, void 0, void 0, function* () {
9913-
if (name === '') {
9920+
if (name === "") {
99149921
return;
99159922
}
9916-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.info(`Adding label (${name}) to PR...`);
9923+
core.info(`Adding label (${name}) to PR...`);
99179924
const addLabelResponse = yield octokit.rest.issues.addLabels({
99189925
owner: context.repo.owner,
99199926
repo: context.repo.repo,
99209927
issue_number: context.issue.number,
99219928
labels: [name],
99229929
});
9923-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.info(`Added label (${name}) to PR - ${addLabelResponse.status}`);
9930+
core.info(`Added label (${name}) to PR - ${addLabelResponse.status}`);
99249931
});
99259932
}
9926-
function removeLabel({ labels, name }) {
9933+
function removeLabel({ labels, name, }) {
99279934
return __awaiter(this, void 0, void 0, function* () {
9928-
if (name === '') {
9935+
if (name === "") {
99299936
return;
99309937
}
99319938
try {
@@ -9934,47 +9941,78 @@ function removeLabel({ labels, name }) {
99349941
.includes(name.toLowerCase())) {
99359942
return;
99369943
}
9937-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.info("No formatting necessary. Removing label...");
9944+
core.info("No formatting necessary. Removing label...");
99389945
let removeLabelResponse = yield octokit.rest.issues.removeLabel({
99399946
owner: context.repo.owner,
99409947
repo: context.repo.repo,
99419948
issue_number: context.issue.number,
99429949
name: name,
99439950
});
9944-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.info(`Removed label - ${removeLabelResponse.status}`);
9951+
core.info(`Removed label - ${removeLabelResponse.status}`);
99459952
}
99469953
catch (error) {
9947-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.info(`Failed to remove label (${name}) from PR: ${error}`);
9954+
core.info(`Failed to remove label (${name}) from PR: ${error}`);
99489955
}
99499956
});
99509957
}
9951-
function getJSON({ path, useLocalConfigFile }) {
9958+
function downloadJSON(url) {
9959+
return new Promise((resolve, reject) => {
9960+
const req = external_node_https_default().request(url, (res) => {
9961+
let responseBody = "";
9962+
res.on("data", (d) => {
9963+
responseBody += d;
9964+
});
9965+
res.on("end", () => {
9966+
resolve(JSON.parse(responseBody.toString()));
9967+
});
9968+
});
9969+
req.on("error", (e) => {
9970+
reject(e);
9971+
});
9972+
req.end();
9973+
});
9974+
}
9975+
function getJSON({ configPath, localConfigPath, remoteConfigURL, GitHubConfigOwner, GitHubConfigRepo, GitHubConfigPath, GitHubConfigRef, GitHubConfigToken, }) {
99529976
return __awaiter(this, void 0, void 0, function* () {
9953-
if (useLocalConfigFile) {
9954-
const data = (0,fs__WEBPACK_IMPORTED_MODULE_2__.readFileSync)((0,path__WEBPACK_IMPORTED_MODULE_3__.join)(process.cwd(), path));
9955-
return data.toString();
9977+
if (localConfigPath) {
9978+
core.info(`Using local config file ${localConfigPath}`);
9979+
const data = (0,external_fs_.readFileSync)((0,external_path_.join)(process.cwd(), localConfigPath));
9980+
return JSON.parse(data.toString());
99569981
}
9957-
const response = yield octokit.rest.repos.getContent({
9958-
owner: context.repo.owner,
9959-
repo: context.repo.repo,
9960-
path,
9961-
ref: context.sha,
9982+
if (remoteConfigURL) {
9983+
core.info(`Using remote config file ${remoteConfigURL}`);
9984+
const url = new URL(remoteConfigURL);
9985+
return yield downloadJSON(url);
9986+
}
9987+
const is_same_repo = GitHubConfigOwner === context.repo.owner &&
9988+
GitHubConfigRepo === context.repo.repo;
9989+
core.info(`Using config file ${GitHubConfigPath || configPath} from repo ${GitHubConfigOwner || context.repo.owner}/${GitHubConfigRepo || context.repo.repo} [ref: ${GitHubConfigRef ||
9990+
(is_same_repo ? context.sha : "latest commit on the default branch")}]`);
9991+
let _octokit = octokit;
9992+
if (GitHubConfigToken) {
9993+
_octokit = github.getOctokit(GitHubConfigToken);
9994+
}
9995+
const response = yield _octokit.rest.repos.getContent({
9996+
owner: GitHubConfigOwner || context.repo.owner,
9997+
repo: GitHubConfigRepo || context.repo.repo,
9998+
path: GitHubConfigPath || configPath,
9999+
ref: GitHubConfigRef || (is_same_repo ? context.sha : undefined),
996210000
});
9963-
return Buffer.from(response.data.content, response.data.encoding).toString();
10001+
return JSON.parse(Buffer.from(response.data.content, response.data.encoding).toString());
996410002
});
996510003
}
9966-
function handleOctokitError({ passOnOctokitError, error }) {
10004+
function handleOctokitError({ passOnOctokitError, error, }) {
996710005
return __awaiter(this, void 0, void 0, function* () {
9968-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.info(`Octokit Error - ${error}`);
10006+
core.info(`Octokit Error - ${error}`);
996910007
if (passOnOctokitError) {
9970-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.info("Passing CI regardless");
10008+
core.info("Passing CI regardless");
997110009
}
997210010
else {
9973-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.setFailed("Failing CI test");
10011+
core.setFailed("Failing CI test");
997410012
}
997510013
});
997610014
}
9977-
const run = ({ configPath, useLocalConfigFile }) => __awaiter(void 0, void 0, void 0, function* () {
10015+
const run = ({ configPath, localConfigPath, remoteConfigURL, GitHubConfigOwner, GitHubConfigRepo, GitHubConfigPath, GitHubConfigRef, GitHubConfigToken, }) => __awaiter(void 0, void 0, void 0, function* () {
997810016
if (!context || !context.payload || !context.payload.pull_request) {
997910017
return;
998010018
}
@@ -9983,11 +10021,19 @@ const run = ({ configPath, useLocalConfigFile }) => __awaiter(void 0, void 0, vo
998310021
const labels = context.payload.pull_request.labels;
998410022
let config;
998510023
try {
9986-
const configString = yield getJSON({ path: configPath, useLocalConfigFile });
9987-
config = JSON.parse(configString);
10024+
config = yield getJSON({
10025+
configPath,
10026+
localConfigPath,
10027+
remoteConfigURL,
10028+
GitHubConfigOwner,
10029+
GitHubConfigRepo,
10030+
GitHubConfigPath,
10031+
GitHubConfigRef,
10032+
GitHubConfigToken,
10033+
});
998810034
}
998910035
catch (e) {
9990-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.setFailed(`1 Couldn't retrieve or parse the config file specified - ${e}`);
10036+
core.setFailed(`Couldn't retrieve or parse the config file specified - ${e}`);
999110037
return;
999210038
}
999310039
let { CHECKS, LABEL, MESSAGES } = config;
@@ -10002,7 +10048,7 @@ const run = ({ configPath, useLocalConfigFile }) => __awaiter(void 0, void 0, vo
1000210048
for (let i = 0; i < labels.length; i++) {
1000310049
for (let j = 0; j < CHECKS.ignoreLabels.length; j++) {
1000410050
if (labels[i].name == CHECKS.ignoreLabels[j]) {
10005-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.info(`Ignoring Title Check for label - ${labels[i].name}`);
10051+
core.info(`Ignoring Title Check for label - ${labels[i].name}`);
1000610052
removeLabel({ labels, name: LABEL.name });
1000710053
return;
1000810054
}
@@ -10013,7 +10059,7 @@ const run = ({ configPath, useLocalConfigFile }) => __awaiter(void 0, void 0, vo
1001310059
for (let i = 0; i < CHECKS.prefixes.length; i++) {
1001410060
if (title.startsWith(CHECKS.prefixes[i])) {
1001510061
removeLabel({ labels, name: LABEL.name });
10016-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.info(MESSAGES.success);
10062+
core.info(MESSAGES.success);
1001710063
return;
1001810064
}
1001910065
}
@@ -10022,27 +10068,42 @@ const run = ({ configPath, useLocalConfigFile }) => __awaiter(void 0, void 0, vo
1002210068
let re = new RegExp(CHECKS.regexp, CHECKS.regexpFlags || "");
1002310069
if (re.test(title)) {
1002410070
removeLabel({ labels, name: LABEL.name });
10025-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.info(MESSAGES.success);
10071+
core.info(MESSAGES.success);
1002610072
return;
1002710073
}
1002810074
}
1002910075
yield titleCheckFailed({ config });
1003010076
}
1003110077
catch (error) {
10032-
_actions_core__WEBPACK_IMPORTED_MODULE_1__.info(error);
10078+
core.info(error);
1003310079
}
1003410080
});
10035-
const configPath = _actions_core__WEBPACK_IMPORTED_MODULE_1__.getInput("configuration_path");
10036-
const useLocalConfigFile = _actions_core__WEBPACK_IMPORTED_MODULE_1__.getInput("use_local_configuration_file") === "true";
10037-
const passOnOctokitError = _actions_core__WEBPACK_IMPORTED_MODULE_1__.getInput("pass_on_octokit_error") === "true";
10038-
const token = _actions_core__WEBPACK_IMPORTED_MODULE_1__.getInput('GITHUB_TOKEN');
10081+
const configPath = core.getInput("configuration_path");
10082+
const localConfigPath = core.getInput("local_configuration_path");
10083+
const remoteConfigURL = core.getInput("remote_configuration_url");
10084+
const GitHubConfigOwner = core.getInput("github_configuration_owner");
10085+
const GitHubConfigRepo = core.getInput("github_configuration_repo");
10086+
const GitHubConfigPath = core.getInput("github_configuration_path");
10087+
const GitHubConfigRef = core.getInput("github_configuration_ref");
10088+
const GitHubConfigToken = core.getInput("github_configuration_token");
10089+
const passOnOctokitError = core.getInput("pass_on_octokit_error") === "true";
10090+
const token = core.getInput("GITHUB_TOKEN");
1003910091
try {
10040-
octokit = _actions_github__WEBPACK_IMPORTED_MODULE_0__.getOctokit(token);
10092+
octokit = github.getOctokit(token);
10093+
run({
10094+
configPath,
10095+
localConfigPath,
10096+
remoteConfigURL,
10097+
GitHubConfigOwner,
10098+
GitHubConfigRepo,
10099+
GitHubConfigPath,
10100+
GitHubConfigRef,
10101+
GitHubConfigToken,
10102+
});
1004110103
}
1004210104
catch (e) {
1004310105
handleOctokitError({ passOnOctokitError, error: e });
1004410106
}
10045-
run({ configPath, useLocalConfigFile });
1004610107

1004710108
})();
1004810109

0 commit comments

Comments
 (0)