-
Notifications
You must be signed in to change notification settings - Fork 3.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11783 from CesiumGS/cla-checking-final
Automate CLA checking
- Loading branch information
Showing
5 changed files
with
207 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
import { Octokit } from "@octokit/core"; | ||
import { google } from "googleapis"; | ||
import Handlebars from "handlebars"; | ||
import fs from "fs-extra"; | ||
|
||
const PULL_REQUST_INFO = { | ||
id: process.env.PULL_REQUEST_ID, | ||
owner: process.env.GITHUB_REPOSITORY.split("/")[0], | ||
repoName: process.env.GITHUB_REPOSITORY.split("/")[1], | ||
username: process.env.GITHUB_ACTOR, | ||
gitHubToken: process.env.GITHUB_TOKEN, | ||
}; | ||
|
||
const GOOGLE_SHEETS_INFO = { | ||
APIKeys: process.env.GOOGLE_KEYS, | ||
individualCLASheetId: process.env.INDIVIDUAL_CLA_SHEET_ID, | ||
corporateCLASheetId: process.env.CORPORATE_CLA_SHEET_ID, | ||
}; | ||
|
||
const CONTRIBUTORS_URL = | ||
"https://github.com/CesiumGS/cesium/blob/main/CONTRIBUTORS.md"; | ||
|
||
const main = async () => { | ||
let hasSignedCLA; | ||
let errorFoundOnCLACheck; | ||
|
||
try { | ||
hasSignedCLA = await checkIfUserHasSignedAnyCLA(); | ||
} catch (error) { | ||
errorFoundOnCLACheck = error.toString(); | ||
} | ||
|
||
const response = await postCommentOnPullRequest( | ||
hasSignedCLA, | ||
errorFoundOnCLACheck | ||
); | ||
}; | ||
|
||
const checkIfUserHasSignedAnyCLA = async () => { | ||
let foundIndividualCLA = await checkIfIndividualCLAFound(); | ||
if (foundIndividualCLA) { | ||
return true; | ||
} | ||
|
||
let foundCorporateCLA = await checkIfCorporateCLAFound(); | ||
return foundCorporateCLA; | ||
}; | ||
|
||
const checkIfIndividualCLAFound = async () => { | ||
const response = await getValuesFromGoogleSheet( | ||
GOOGLE_SHEETS_INFO.individualCLASheetId, | ||
"D2:D" | ||
); | ||
|
||
const rows = response.data.values; | ||
for (let i = 0; i < rows.length; i++) { | ||
if (rows[i].length === 0) { | ||
continue; | ||
} | ||
|
||
const rowUsername = rows[i][0].toLowerCase(); | ||
if (PULL_REQUST_INFO.username.toLowerCase() === rowUsername) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
}; | ||
|
||
const checkIfCorporateCLAFound = async () => { | ||
const response = await getValuesFromGoogleSheet( | ||
GOOGLE_SHEETS_INFO.corporateCLASheetId, | ||
"H2:H" | ||
); | ||
|
||
const rows = response.data.values; | ||
for (let i = 0; i < rows.length; i++) { | ||
if (rows[i].length === 0) { | ||
continue; | ||
} | ||
|
||
// We're more lenient with the ScheduleA username check since it's an unformatted text field. | ||
let rowScheduleA = rows[i][0].toLowerCase(); | ||
rowScheduleA = rowScheduleA.replace(/\n/g, " "); | ||
const words = rowScheduleA.split(" "); | ||
|
||
for (let j = 0; j < words.length; j++) { | ||
// Checking for substrings because many GitHub usernames added as "github.com/username". | ||
if (words[j].includes(PULL_REQUST_INFO.username.toLowerCase())) { | ||
return true; | ||
} | ||
} | ||
} | ||
|
||
return false; | ||
}; | ||
|
||
const getValuesFromGoogleSheet = async (sheetId, cellRanges) => { | ||
const googleSheetsApi = await getGoogleSheetsApiClient(); | ||
|
||
return googleSheetsApi.spreadsheets.values.get({ | ||
spreadsheetId: sheetId, | ||
range: cellRanges, | ||
}); | ||
}; | ||
|
||
const getGoogleSheetsApiClient = async () => { | ||
const googleConfigFilePath = "GoogleConfig.json"; | ||
fs.writeFileSync(googleConfigFilePath, GOOGLE_SHEETS_INFO.APIKeys); | ||
|
||
const auth = new google.auth.GoogleAuth({ | ||
keyFile: googleConfigFilePath, | ||
scopes: ["https://www.googleapis.com/auth/spreadsheets"], | ||
}); | ||
const googleAuthClient = await auth.getClient(); | ||
|
||
return google.sheets({ version: "v4", auth: googleAuthClient }); | ||
}; | ||
|
||
const postCommentOnPullRequest = async (hasSignedCLA, errorFoundOnCLACheck) => { | ||
const octokit = new Octokit(); | ||
|
||
return octokit.request( | ||
`POST /repos/${PULL_REQUST_INFO.owner}/${PULL_REQUST_INFO.repoName}/issues/${PULL_REQUST_INFO.id}/comments`, | ||
{ | ||
owner: PULL_REQUST_INFO.username, | ||
repo: PULL_REQUST_INFO.repoName, | ||
issue_number: PULL_REQUST_INFO.id, | ||
body: getCommentBody(hasSignedCLA, errorFoundOnCLACheck), | ||
headers: { | ||
authorization: `bearer ${PULL_REQUST_INFO.gitHubToken}`, | ||
accept: "application/vnd.github+json", | ||
"X-GitHub-Api-Version": "2022-11-28", | ||
}, | ||
} | ||
); | ||
}; | ||
|
||
const getCommentBody = (hasSignedCLA, errorFoundOnCLACheck) => { | ||
const commentTemplate = fs.readFileSync( | ||
"./.github/actions/check-for-CLA/templates/pullRequestComment.hbs", | ||
"utf-8" | ||
); | ||
|
||
const getCommentFromTemplate = Handlebars.compile(commentTemplate); | ||
const commentBody = getCommentFromTemplate({ | ||
errorCla: errorFoundOnCLACheck, | ||
hasCla: hasSignedCLA, | ||
username: PULL_REQUST_INFO.username, | ||
contributorsUrl: CONTRIBUTORS_URL, | ||
}); | ||
|
||
return commentBody; | ||
}; | ||
|
||
main(); |
20 changes: 20 additions & 0 deletions
20
.github/actions/check-for-CLA/templates/pullRequestComment.hbs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
{{#if errorCla}} | ||
:red_circle: There was an error checking the CLA! If this is your first contribution, please send in a [Contributor License Agreement](https://github.com/CesiumGS/cesium/blob/main/CONTRIBUTING.md#contributor-license-agreement-cla). | ||
``` | ||
{{ errorCla }} | ||
``` | ||
{{else}} | ||
{{#if hasCla}} | ||
Thank you for the pull request, @{{ username }}! | ||
|
||
:white_check_mark: We can confirm we have a CLA on file for you. | ||
{{else}} | ||
Thank you for the pull request, @{{ username }}! Welcome to the Cesium community! | ||
|
||
In order for us to review your PR, please complete the following steps: | ||
- [ ] Send in a [Contributor License Agreement](https://github.com/CesiumGS/cesium/blob/main/CONTRIBUTING.md#contributor-license-agreement-cla) (CLA) | ||
- [ ] Add yourself to the [contributors]({{ contributorsUrl }}) file | ||
|
||
Review [Pull Request Guidelines](https://github.com/CesiumGS/cesium/blob/main/CONTRIBUTING.md#pull-request-guidelines) to make sure your PR gets accepted quickly. | ||
{{/if}} | ||
{{/if}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
name: CLA Checking | ||
on: | ||
pull_request: | ||
types: [opened] | ||
|
||
jobs: | ||
check-cla: | ||
runs-on: ubuntu-latest | ||
permissions: | ||
issues: write | ||
pull-requests: write | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: install node 20 | ||
uses: actions/setup-node@v3 | ||
with: | ||
node-version: '20' | ||
- name: install npm packages | ||
run: npm install googleapis @octokit/core handlebars fs-extra | ||
- name: run script | ||
run: node .github/actions/check-for-CLA/index.js | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
PULL_REQUEST_ID: ${{ github.event.number }} | ||
GOOGLE_KEYS: ${{ secrets.GOOGLE_KEYS }} | ||
INDIVIDUAL_CLA_SHEET_ID: ${{ secrets.INDIVIDUAL_CLA_SHEET_ID }} | ||
CORPORATE_CLA_SHEET_ID: ${{ secrets.CORPORATE_CLA_SHEET_ID }} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters