Skip to content

Commit

Permalink
ci(check-ci-skip): fix commitMessagesMetadata.forEach is not a function
Browse files Browse the repository at this point in the history
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 #3614

Signed-off-by: bado <zondervan.v.calvez@accenture.com>
  • Loading branch information
zondervancalvez committed Jan 9, 2025
1 parent 50d19f8 commit 9fada48
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 77 deletions.
9 changes: 8 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,12 @@ env:
jobs:
ActionLint:
needs: check-ci-skip
if: needs.check-ci-skip.outputs.should_skip == 'false'
uses: ./.github/workflows/actionlint.yaml
DCI-Lint:
name: DCI-Lint
needs: check-ci-skip
if: needs.check-ci-skip.outputs.should_skip == 'false'
runs-on: ubuntu-22.04
steps:
- id: lint-git-repo
Expand All @@ -33,13 +35,16 @@ jobs:

check-ci-skip:
runs-on: ubuntu-22.04
outputs:
should_skip: ${{ steps.check.outputs.should_skip }}
steps:
- uses: actions/checkout@v4.1.7
- name: Check CI Skip
run: node tools/ci-skip-for-maintainers.js ${{ github.event.pull_request.url }} ${{ github.event.pull_request.user.login }}
run: node tools/ci-skip-for-maintainers.js

check-coverage:
needs: check-ci-skip
if: needs.check-ci-skip.outputs.should_skip == 'false'
outputs:
run-coverage: ${{ steps.set-output.outputs.run-coverage }}
runs-on: ubuntu-22.04
Expand All @@ -51,6 +56,7 @@ jobs:

compute_changed_packages:
needs: check-ci-skip
if: needs.check-ci-skip.outputs.should_skip == 'false'
outputs:
cmd-api-server-changed: ${{ steps.changes.outputs.cmd-api-server-changed }}
plugin-ledger-connector-polkadot-changed: ${{ steps.changes.outputs.plugin-ledger-connector-polkadot-changed }}
Expand Down Expand Up @@ -187,6 +193,7 @@ jobs:
build-dev:
needs: check-ci-skip
if: needs.check-ci-skip.outputs.should_skip == 'false'
continue-on-error: false
env:
DEV_BUILD_DISABLED: false
Expand Down
148 changes: 72 additions & 76 deletions tools/ci-skip-for-maintainers.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { readFileSync } from "fs";
import { execSync } from "child_process";

//A new tag exclusively for MAINTAINERS that allows skipping the CI check
// Constants
const SKIP_CACTI = "skip-cacti-ci";
const MaintainersFile = "MAINTAINERS.md";
//regular expression to get the maintainers in MAINTAINERS.md
const NAMES_REGEX = /\|\s*([A-Za-z\s]+)\s*/;
const LINKS_REGEX = /\|\s*\[([^\]]+)\]\[[^\]]+\]\s*/;
const TAGS_REGEX = /\|\s*([A-Za-z0-9_-]+|-)*\s*/;
Expand All @@ -12,90 +12,86 @@ const MAINTAINERS_REGEX = new RegExp(
"g",
);

const main = async () => {
const markdownContent = readFileSync(MaintainersFile, "utf-8");
const getMaintainersFileContent = () => readFileSync(MaintainersFile, "utf-8");

const args = process.argv.slice(2);
const pullReqUrl = args[0];
const committerLogin = args[1];
// Function to get the latest commit message author
const getCommitterLogin = () => {
const authorBuffer = execSync("git log -1 | grep Author | cut -d' ' -f2");
const authorString = authorBuffer.toString();
const authorStringTrim = authorString.trim();
return authorStringTrim;
};

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

// Function to check if SKIP_CACTI tag is in the commit message
const checkSkipCI = (commitMessage) => {
if (commitMessage.includes(SKIP_CACTI)) {
console.log("Skip requested in commit message.");
return true;
}
console.log("No skip request found.");
return false;
};

const fetchJsonFromUrl = async (url) => {
const fetchResponse = await fetch(url);
return fetchResponse.json();
};
// Function to extract maintainers from the MAINTAINERS.md file content
const extractMaintainers = (maintainerMetaData) => {
let match;
const maintainers = [];
while ((match = MAINTAINERS_REGEX.exec(maintainerMetaData)) !== null) {
const github = match[2];
maintainers.push(github);
}
return maintainers;
};

let commitMessageList = [];
const commitMessagesMetadata = await fetchJsonFromUrl(
pullReqUrl + "/commits",
// Function to check if committer is an active maintainer
const checkCommitterIsMaintainer = (committerLogin, activeMaintainers) => {
if (activeMaintainers.includes(committerLogin)) {
console.log("The author of this PR is an active maintainer.");
return true;
}
console.log(
"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.",
);
return false;
};

commitMessagesMetadata.forEach((commitMessageMetadata) => {
// get commit message body
commitMessageList.push(commitMessageMetadata["commit"]["message"]);
});

// Check if skip-ci is found in commit message
const checkSkipCI = () => {
for (let commitMessageListIndex in commitMessageList) {
let commitMessage = commitMessageList[commitMessageListIndex];
if (commitMessage.includes(SKIP_CACTI)) {
console.log("Skip requested in commit message.");
return true;
} else {
console.log("No skip request found.");
}
return false;
}
};
// Main function to determine whether to skip CI or proceed
const main = async () => {
const markdownContent = getMaintainersFileContent();
const committerLogin = getCommitterLogin();
const commitMessage = getLatestCommitMessage();
const outputPath = process.env.GITHUB_OUTPUT;
fs.appendFileSync(outputPath, `should_skip=${isMaintainer}\n`);
const shouldSkipCI = checkSkipCI(commitMessage);
if (!shouldSkipCI) {
console.log("No skip requested. Proceeding with CI.");
console.log(`Skip CI set to: ${shouldSkipCI}`);
process.exit(0);
}

// Function to extract active maintainers
const extractMaintainers = (maintainerMetaData) => {
let match;
const maintainers = [];
while ((match = MAINTAINERS_REGEX.exec(maintainerMetaData)) !== null) {
const github = match[2];
maintainers.push(github);
}
return maintainers;
};
// Get the maintainers
const activeMaintainers = extractMaintainers(markdownContent);
activeMaintainers.forEach((maintainers) => {
maintainers;
});

// Check if committer is a trusted maintainer
const checkCommitterIsMaintainer = () => {
if (activeMaintainers.includes(committerLogin)) {
console.log("The author of this PR is an active maintainer.");
return true;
} else {
console.log(
"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.",
);
return false;
}
};

// Main logic

const shouldSkipCI = checkSkipCI();
const isMaintainer = checkCommitterIsMaintainer(
committerLogin,
activeMaintainers,
);

if (shouldSkipCI) {
const isMaintainer = checkCommitterIsMaintainer();
if (isMaintainer) {
console.log(
"Exit with an error code so as to pause the dependent workflows. CI skipped as per request.",
);
process.exit(1); // Exit successfully to skip CI
}
if (isMaintainer) {
console.log(
"CI skipped as per request. Exit with an error to PAUSE dependent workflows.",
);
console.log(`Skip CI set to: ${isMaintainer}`);
process.exit(0);
} else {
console.log("No skip requested. Proceeding with CI.");
process.exit(0); // Exit successfully to run CI
console.log(`Skip CI set to: ${isMaintainer}`);
process.exit(0);
}
};

Expand Down

0 comments on commit 9fada48

Please sign in to comment.