Skip to content

Commit 471d172

Browse files
ci(check-ci-skip): fix commitMessagesMetadata.forEach is not a function
Primary Changes ---------------- 1. Changed the method in getting the commit message from GitHub API to shell command to avoid the rate limits in calling the API. 2. Same goes for the author of commit message, we use shell command to fetch the username. Fixes hyperledger-cacti#3614 Signed-off-by: bado <[email protected]>
1 parent 36959b3 commit 471d172

File tree

2 files changed

+85
-77
lines changed

2 files changed

+85
-77
lines changed

.github/workflows/ci.yaml

+10-1
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ env:
1717
jobs:
1818
ActionLint:
1919
needs: check-ci-skip
20+
if: needs.check-ci-skip.outputs.should_skip == 'false'
2021
uses: ./.github/workflows/actionlint.yaml
2122
DCI-Lint:
2223
name: DCI-Lint
2324
needs: check-ci-skip
25+
if: needs.check-ci-skip.outputs.should_skip == 'false'
2426
runs-on: ubuntu-22.04
2527
steps:
2628
- id: lint-git-repo
@@ -33,13 +35,18 @@ jobs:
3335

3436
check-ci-skip:
3537
runs-on: ubuntu-22.04
38+
outputs:
39+
should_skip: ${{ steps.check.outputs.should_skip }}
3640
steps:
3741
- uses: actions/[email protected]
3842
- name: Check CI Skip
39-
run: node tools/ci-skip-for-maintainers.js ${{ github.event.pull_request.url }} ${{ github.event.pull_request.user.login }}
43+
run: node tools/ci-skip-for-maintainers.js
44+
env:
45+
GITHUB_ACTOR: ${{ github.actor }}
4046

4147
check-coverage:
4248
needs: check-ci-skip
49+
if: needs.check-ci-skip.outputs.should_skip == 'false'
4350
outputs:
4451
run-coverage: ${{ steps.set-output.outputs.run-coverage }}
4552
runs-on: ubuntu-22.04
@@ -51,6 +58,7 @@ jobs:
5158

5259
compute_changed_packages:
5360
needs: check-ci-skip
61+
if: needs.check-ci-skip.outputs.should_skip == 'false'
5462
outputs:
5563
cmd-api-server-changed: ${{ steps.changes.outputs.cmd-api-server-changed }}
5664
plugin-ledger-connector-polkadot-changed: ${{ steps.changes.outputs.plugin-ledger-connector-polkadot-changed }}
@@ -187,6 +195,7 @@ jobs:
187195
188196
build-dev:
189197
needs: check-ci-skip
198+
if: needs.check-ci-skip.outputs.should_skip == 'false'
190199
continue-on-error: false
191200
env:
192201
DEV_BUILD_DISABLED: false

tools/ci-skip-for-maintainers.js

+75-76
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { readFileSync } from "fs";
2-
3-
//A new tag exclusively for MAINTAINERS that allows skipping the CI check
2+
import { execSync } from "child_process";
3+
import fs from "fs";
4+
// Constants
45
const SKIP_CACTI = "skip-cacti-ci";
56
const MaintainersFile = "MAINTAINERS.md";
6-
//regular expression to get the maintainers in MAINTAINERS.md
77
const NAMES_REGEX = /\|\s*([A-Za-z\s]+)\s*/;
88
const LINKS_REGEX = /\|\s*\[([^\]]+)\]\[[^\]]+\]\s*/;
99
const TAGS_REGEX = /\|\s*([A-Za-z0-9_-]+|-)*\s*/;
@@ -12,90 +12,89 @@ const MAINTAINERS_REGEX = new RegExp(
1212
"g",
1313
);
1414

15-
const main = async () => {
16-
const markdownContent = readFileSync(MaintainersFile, "utf-8");
15+
const getMaintainersFileContent = () => {
16+
try {
17+
return readFileSync(MaintainersFile, "utf-8");
18+
} catch (error) {
19+
console.error(`Error reading ${MaintainersFile}:`, error.message);
20+
process.exit(1);
21+
}
22+
};
1723

18-
const args = process.argv.slice(2);
19-
const pullReqUrl = args[0];
20-
const committerLogin = args[1];
24+
// Function to get the latest commit message author
25+
const getCommitterAuthor = () => {
26+
return process.env.GITHUB_ACTOR || "unknown";
27+
};
2128

22-
//Uncomment these lines and change it for local machine testing purposes:
23-
//const pullReqUrl = "https://api.github.com/repos/<username>/cactus/pulls/<number>";
24-
//const committerLogin = "<username>";
29+
// Function to get the latest commit message
30+
const getLatestCommitMessage = () => {
31+
const commitMsgBuffer = execSync("git log -1 --pretty=%B");
32+
const commitMsgString = commitMsgBuffer.toString();
33+
const commitMsgTrim = commitMsgString.trim();
34+
return commitMsgTrim;
35+
};
2536

26-
const fetchJsonFromUrl = async (url) => {
27-
const fetchResponse = await fetch(url);
28-
return fetchResponse.json();
29-
};
37+
// Function to check if SKIP_CACTI tag is in the commit message
38+
const checkSkipCI = (commitMessage) => {
39+
if (commitMessage.includes(SKIP_CACTI)) {
40+
console.log("Skip requested in commit message.");
41+
return true;
42+
}
43+
console.log("No skip request found.");
44+
return false;
45+
};
3046

31-
let commitMessageList = [];
32-
const commitMessagesMetadata = await fetchJsonFromUrl(
33-
pullReqUrl + "/commits",
34-
);
47+
// Function to extract maintainers from the MAINTAINERS.md file content
48+
const extractMaintainers = (maintainerMetaData) => {
49+
let match;
50+
const maintainers = [];
51+
while ((match = MAINTAINERS_REGEX.exec(maintainerMetaData)) !== null) {
52+
const github = match[2];
53+
maintainers.push(github);
54+
}
55+
return maintainers;
56+
};
3557

36-
commitMessagesMetadata.forEach((commitMessageMetadata) => {
37-
// get commit message body
38-
commitMessageList.push(commitMessageMetadata["commit"]["message"]);
39-
});
58+
// Function to check if committer is an active maintainer
59+
const checkCommitterIsMaintainer = (committerAuthor, activeMaintainers) => {
60+
if (activeMaintainers.includes(committerAuthor)) {
61+
console.log("The author of this PR is an active maintainer.");
62+
return true;
63+
}
64+
console.log(
65+
"CI will not be skipped. \nThe author of this PR is not an active maintainer.\nPlease refer to https://github.com/hyperledger/cacti/blob/main/MAINTAINERS.md for the list of active maintainers.",
66+
);
67+
return false;
68+
};
4069

41-
// Check if skip-ci is found in commit message
42-
const checkSkipCI = () => {
43-
for (let commitMessageListIndex in commitMessageList) {
44-
let commitMessage = commitMessageList[commitMessageListIndex];
45-
if (commitMessage.includes(SKIP_CACTI)) {
46-
console.log("Skip requested in commit message.");
47-
return true;
48-
} else {
49-
console.log("No skip request found.");
50-
}
51-
return false;
52-
}
53-
};
70+
// Main function to determine whether to skip CI or proceed
71+
const main = async () => {
72+
const markdownContent = getMaintainersFileContent();
73+
const committerAuthor = getCommitterAuthor();
74+
const commitMessage = getLatestCommitMessage();
75+
const shouldSkipCI = checkSkipCI(commitMessage);
76+
const outputPath = process.env.GITHUB_OUTPUT;
5477

55-
// Function to extract active maintainers
56-
const extractMaintainers = (maintainerMetaData) => {
57-
let match;
58-
const maintainers = [];
59-
while ((match = MAINTAINERS_REGEX.exec(maintainerMetaData)) !== null) {
60-
const github = match[2];
61-
maintainers.push(github);
62-
}
63-
return maintainers;
64-
};
65-
// Get the maintainers
6678
const activeMaintainers = extractMaintainers(markdownContent);
67-
activeMaintainers.forEach((maintainers) => {
68-
maintainers;
69-
});
70-
71-
// Check if committer is a trusted maintainer
72-
const checkCommitterIsMaintainer = () => {
73-
if (activeMaintainers.includes(committerLogin)) {
74-
console.log("The author of this PR is an active maintainer.");
75-
return true;
76-
} else {
77-
console.log(
78-
"CI will not be skipped. \nThe author of this PR is not an active maintainer.\nPlease refer to https://github.com/hyperledger/cacti/blob/main/MAINTAINERS.md for the list of active maintainers.",
79-
);
80-
return false;
81-
}
82-
};
83-
84-
// Main logic
85-
86-
const shouldSkipCI = checkSkipCI();
79+
const isMaintainer = checkCommitterIsMaintainer(
80+
committerAuthor,
81+
activeMaintainers,
82+
);
83+
// Final decision: skip if either shouldSkipCI or isMaintainer is true
84+
const shouldSkip = shouldSkipCI || isMaintainer;
85+
// Write only once to GITHUB_OUTPUT
86+
if (!outputPath) {
87+
console.error("GITHUB_OUTPUT is not defined. Exiting.");
88+
process.exit(1);
89+
}
90+
fs.appendFileSync(outputPath, `should_skip=${shouldSkip}\n`);
8791

88-
if (shouldSkipCI) {
89-
const isMaintainer = checkCommitterIsMaintainer();
90-
if (isMaintainer) {
91-
console.log(
92-
"Exit with an error code so as to pause the dependent workflows. CI skipped as per request.",
93-
);
94-
process.exit(1); // Exit successfully to skip CI
95-
}
92+
if (shouldSkip) {
93+
console.log("CI skipped as per request. Exiting with code 0.");
94+
process.exit(0); // Normal exit
9695
} else {
9796
console.log("No skip requested. Proceeding with CI.");
98-
process.exit(0); // Exit successfully to run CI
97+
process.exit(0);
9998
}
10099
};
101100

0 commit comments

Comments
 (0)