From 2fa1f2853d1a32e13a542da0481cb0e252c60b61 Mon Sep 17 00:00:00 2001 From: bado Date: Tue, 5 Nov 2024 12:29:02 +0800 Subject: [PATCH] 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 #3614 Signed-off-by: bado --- .github/workflows/ci.yaml | 9 +- tools/ci-skip-for-maintainers.js | 149 +++++++++++++++---------------- 2 files changed, 79 insertions(+), 79 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 4ed27ca2ee..7dca23dfad 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -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 @@ -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 @@ -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 }} @@ -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 diff --git a/tools/ci-skip-for-maintainers.js b/tools/ci-skip-for-maintainers.js index 911c637ca4..9aba68dd87 100644 --- a/tools/ci-skip-for-maintainers.js +++ b/tools/ci-skip-for-maintainers.js @@ -1,9 +1,9 @@ import { readFileSync } from "fs"; - -//A new tag exclusively for MAINTAINERS that allows skipping the CI check +import { execSync } from "child_process"; +import fs from "fs"; +// 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*/; @@ -12,90 +12,83 @@ 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//cactus/pulls/"; - //const committerLogin = ""; +// 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; +}; - const fetchJsonFromUrl = async (url) => { - const fetchResponse = await fetch(url); - return fetchResponse.json(); - }; +// 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; +}; - let commitMessageList = []; - const commitMessagesMetadata = await fetchJsonFromUrl( - pullReqUrl + "/commits", - ); +// 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; +}; - commitMessagesMetadata.forEach((commitMessageMetadata) => { - // get commit message body - commitMessageList.push(commitMessageMetadata["commit"]["message"]); - }); +// 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; +}; - // 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; + const shouldSkipCI = checkSkipCI(commitMessage); + fs.appendFileSync(outputPath, `should_skip=${shouldSkipCI}\n`); + if (!shouldSkipCI) { + console.log("No skip requested. Proceeding with CI."); + 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(); - - 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 - } + const isMaintainer = checkCommitterIsMaintainer( + committerLogin, + activeMaintainers, + ); + fs.appendFileSync(outputPath, `should_skip=${isMaintainer}\n`); + if (isMaintainer) { + console.log( + "CI skipped as per request. Exit with an error to PAUSE dependent workflows.", + ); + process.exit(0); } else { - console.log("No skip requested. Proceeding with CI."); - process.exit(0); // Exit successfully to run CI + process.exit(0); } };