From a861df71915eae6341e3b4e0b1c9f1dc186be53c Mon Sep 17 00:00:00 2001 From: jagpreetsinghsasan Date: Mon, 2 Sep 2024 07:53:04 +0000 Subject: [PATCH] ci(github): commit parity check based on similarity Primary Changes --------------- 1. Added a commit-pr similarity ratio to lessen the check strictness 2. Added an env var to the workflow to easily control the similarity ratio Changes required to incorporate 1) --------------------------------- 3. Added string-similarity-js package in package.json Fixes #3470 Signed-off-by: jagpreetsinghsasan --- .github/workflows/pr-commit-parity.yaml | 26 +++++++++++--- package.json | 1 + tools/pr-commit-parity.js | 45 ++++++++++++++++++------- yarn.lock | 8 +++++ 4 files changed, 64 insertions(+), 16 deletions(-) diff --git a/.github/workflows/pr-commit-parity.yaml b/.github/workflows/pr-commit-parity.yaml index 59492fee25..10b954261e 100644 --- a/.github/workflows/pr-commit-parity.yaml +++ b/.github/workflows/pr-commit-parity.yaml @@ -11,15 +11,33 @@ name: PR - Commit Parity - main - dev +env: + NODEJS_VERSION: v18.18.2 + jobs: pr-commit-parity: name: PR and Commit messages Parity runs-on: ubuntu-22.04 + env: + ACCEPTABLE_SIMILARITY_RATIO: 0.9 steps: - uses: actions/checkout@v3.1.0 - - name: Use Node.js v18.18.2 - uses: actions/setup-node@v4.0.2 + - name: Install Indy SDK + run: > + sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys CE7709D068DB5E88 \ + && sudo add-apt-repository "deb https://repo.sovrin.org/sdk/deb bionic stable" \ + && sudo apt-get update \ + && sudo apt-get install -y \ + libindy \ + libnullpay \ + libvcx \ + indy-cli \ + && sudo rm -f /etc/apt/sources.list.d/sovrin.list* + - name: Set up NodeJS ${{ env.NODEJS_VERSION }} + uses: actions/setup-node@v4.0.3 with: - node-version: v18.19.0 + node-version: ${{ env.NODEJS_VERSION }} + - run: npm run configure + - name: Execute pr-commit-parity script - run: node tools/pr-commit-parity.js ${{ github.event.pull_request.url }} + run: node tools/pr-commit-parity.js ${{ github.event.pull_request.url }} "$ACCEPTABLE_SIMILARITY_RATIO" diff --git a/package.json b/package.json index d07d7561ed..1ad054d6ec 100644 --- a/package.json +++ b/package.json @@ -202,6 +202,7 @@ "sort-package-json": "1.57.0", "source-map-loader": "4.0.1", "stream-browserify": "3.0.0", + "string-similarity-js": "2.1.4", "tap": "16.3.8", "tape": "5.6.6", "tape-promise": "4.0.0", diff --git a/tools/pr-commit-parity.js b/tools/pr-commit-parity.js index 94a8db81f9..1fa4cf5a7d 100644 --- a/tools/pr-commit-parity.js +++ b/tools/pr-commit-parity.js @@ -1,20 +1,30 @@ +import { stringSimilarity } from "string-similarity-js"; + export async function fetchJsonFromUrl(url) { const fetchResponse = await fetch(url); return fetchResponse.json(); } -//regex expressions +// regex expressions const PULL_REQ_REQUIREMENTS_REGEX = /\*\*Pull\sRequest\sRequirements(.|\n)*/gim; const FIXES_OR_DEPENDS_REGEX = /(Fixes|Depends)(.|\n)*/gim; const SIGNED_OFF_REGEX = /(")*Signed-off-by:(.|\s)*/gim; +const COMMIT_TITLE_REGEX = /.*\n/m; const HYPHEN_REGEX = /(-)+/gm; const BACKTICK_REGEX = /`+/gm; -const SPACE_REGEX = / +/gm; const COMMIT_TO_BE_REVIEWED_REGEX = /("#*\s*Commit\sto\sbe\sreviewed)/gim; -const WHITESPACES_HARDCODED_REGEX = /(\r\n|\n|\r|\\r|\\n)/gm; +const WHITESPACES_HARDCODED_REGEX = /(\r\n|\\r)/gm; +const NEWLINE_HARDCODED_REGEX = /\\n/gm; const args = process.argv.slice(2); + +// The following 2 lines should be commented to test this script locally const pullReqUrl = args[0]; +const ACCEPTABLE_SIMILARITY_RATIO = parseFloat(args[1]); + +// These following 2 lines should be un-commented to test this script locally +// const pullReqUrl = "https://api.github.com/repos/hyperledger/cactus/pulls/3338"; +// const ACCEPTABLE_SIMILARITY_RATIO = 0.9; const prMetadata = await fetchJsonFromUrl(pullReqUrl); const prBodyRaw = JSON.stringify(prMetadata.body); @@ -29,33 +39,44 @@ commitMessagesMetadata.forEach((commitMessageMetadata) => { .replace(HYPHEN_REGEX, "") .replace(BACKTICK_REGEX, "") .replace(WHITESPACES_HARDCODED_REGEX, "") - .replace(FIXES_OR_DEPENDS_REGEX, "") - .replace(SPACE_REGEX, ""), + .replace(FIXES_OR_DEPENDS_REGEX, ""), ); }); let prBodyStriped = prBodyRaw .replace(PULL_REQ_REQUIREMENTS_REGEX, "") .replace(FIXES_OR_DEPENDS_REGEX, "") - .replace(WHITESPACES_HARDCODED_REGEX, "") + .replace(WHITESPACES_HARDCODED_REGEX, "\n") .replace(SIGNED_OFF_REGEX, "") .replace(HYPHEN_REGEX, "") .replace(BACKTICK_REGEX, "") .replace(COMMIT_TO_BE_REVIEWED_REGEX, "") - .replace(SPACE_REGEX, ""); + .replace(NEWLINE_HARDCODED_REGEX, ""); -let PR_BODY_IN_COMMIT_MESSAGES = false; +let PR_COMMIT_PARITY = false; for (let commitMessageListIndex in commitMessageList) { let commitMessage = commitMessageList[commitMessageListIndex]; - if (commitMessage == prBodyStriped) PR_BODY_IN_COMMIT_MESSAGES = true; + if ( + stringSimilarity(commitMessage, prBodyStriped) >= + ACCEPTABLE_SIMILARITY_RATIO || + stringSimilarity( + commitMessage.replace(COMMIT_TITLE_REGEX, ""), + prBodyStriped, + ) >= ACCEPTABLE_SIMILARITY_RATIO + ) + PR_COMMIT_PARITY = true; } -if (!PR_BODY_IN_COMMIT_MESSAGES) { +if (!PR_COMMIT_PARITY) { console.error( - "PR Body does not match any existing commit message\n" + - "Please make sure that the PR Body matches to minimum one of the commit messages\n" + + "PR message and commit message are not similar. A general solution for this is to have PR message exactly same as the commit message\n" + "Please refer the following PR for reference: https://github.com/hyperledger/cacti/pull/3338\n" + "And the commit message here: https://github.com/hyperledger/cacti/pull/3338/commits/47ebdec442d30fa48c8518b876c47c38097cf028\n", + "-----------------------------------------------\n\n", + "Commit Message List (ignore extra white spaces and new lines)\n" + + commitMessageList + + "\n----------------------------------------------\nRelevant Pr Description (ignore extra white spaces and new lines)\n" + + prBodyStriped, ); process.exit(-1); } diff --git a/yarn.lock b/yarn.lock index 13638456ae..e95ded9311 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11106,6 +11106,7 @@ __metadata: sort-package-json: "npm:1.57.0" source-map-loader: "npm:4.0.1" stream-browserify: "npm:3.0.0" + string-similarity-js: "npm:2.1.4" tap: "npm:16.3.8" tape: "npm:5.6.6" tape-promise: "npm:4.0.0" @@ -49357,6 +49358,13 @@ __metadata: languageName: node linkType: hard +"string-similarity-js@npm:2.1.4": + version: 2.1.4 + resolution: "string-similarity-js@npm:2.1.4" + checksum: 10/55063198f233aca8833d8429626d9fafdeb164e0fc6a66364a4d8f509df17d49f8a8a42e4096da60c53fe4586b1bace7098c0265da590fe4ec96c3a8ecb90f69 + languageName: node + linkType: hard + "string-similarity@npm:^4.0.1": version: 4.0.4 resolution: "string-similarity@npm:4.0.4"