-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Extract CLA check into standalone Python script
- Loading branch information
Showing
2 changed files
with
89 additions
and
25 deletions.
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,72 @@ | ||
import json | ||
import sys | ||
import urllib.request | ||
|
||
JSON_HEADER = {'Content-Type': 'application/json'} | ||
TEXT_ENCODING = 'utf-8' | ||
|
||
URL_GITHUB = 'https://api.github.com/repos' | ||
URL_JUCE_CLA_CHECK = 'https://cla.juce.com/check' | ||
|
||
ALLOWED_AUTHORS = set( | ||
'web-flow' | ||
) | ||
|
||
|
||
class NoAuthorsException(Exception): | ||
__MESSAGE = "No author or committer user IDs contained within commit information." | ||
|
||
def __init__(self, commits: list): | ||
message = f'{self.__MESSAGE}\n\n{commits}' | ||
super().__init__(message) | ||
|
||
|
||
class UnsignedAuthorsException(Exception): | ||
__MESSAGE_0 = "The following GitHub users need to sign the JUCE CLA:", | ||
__MESSAGE_1 = "Please go to https://cla.juce.com to sign the JUCE Contributor Licence Agreement." | ||
|
||
def __init__(self, authors: set[str]): | ||
authors_str = ', '.join(authors) | ||
message = f'{self.__MESSAGE_0} {authors_str}\n\n{self.__MESSAGE_1}' | ||
super().__init__(message) | ||
|
||
|
||
def _json_request(url: str, data: dict | None = None) -> dict: | ||
if data is not None: | ||
data = json.dumps(data).encode(TEXT_ENCODING) | ||
request = urllib.request.Request(url, data, JSON_HEADER, JSON_HEADER) | ||
with urllib.request.urlopen(request) as response: | ||
raw_response = response.read().decode(TEXT_ENCODING) | ||
return json.loads(raw_response) | ||
|
||
|
||
def _get_authors(github_repository: str, github_event_number: int) -> set[str]: | ||
pr_commit_list = _json_request(f'{URL_GITHUB}/{github_repository}/pulls/{github_event_number}/commits') | ||
authors = set() | ||
for commit in pr_commit_list: | ||
for author_type in ['author', 'committer']: | ||
if author_type in commit: | ||
authors.add(commit[author_type]['login']) | ||
return authors - ALLOWED_AUTHORS | ||
|
||
|
||
def _verify_authors(authors: set[str]) -> None: | ||
if not authors: | ||
raise NoAuthorsException() | ||
verification = _json_request(URL_JUCE_CLA_CHECK, {'logins': list(authors)}) | ||
if verification['unsigned']: | ||
raise UnsignedAuthorsException(verification['unsigned']) | ||
|
||
|
||
def main(github_repository: str, github_event_number: int): | ||
authors = _get_authors(github_repository, github_event_number) | ||
try: | ||
_verify_authors(authors) | ||
except Exception as e: | ||
print(e.message) | ||
|
||
|
||
if __name__ == '__main__': | ||
github_repository = sys.argv[1] | ||
github_event_number = int(sys.argv[2]) | ||
main(github_repository, github_event_number) |
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 |
---|---|---|
@@ -1,32 +1,24 @@ | ||
name: check-CLA | ||
on: [pull_request_target] | ||
name: Check CLA | ||
|
||
on: | ||
pull_request: | ||
|
||
jobs: | ||
check-cla: | ||
runs-on: ubuntu-latest | ||
continue-on-error: ${{ github.repository_owner != 'juce' }} | ||
env: | ||
PR_NUMBER: ${{ github.event.number }} | ||
steps: | ||
- name: Checkout Scripts | ||
uses: actions/checkout@v4 | ||
with: | ||
sparse-checkout: | | ||
.github/scripts | ||
sparse-checkout-cone-mode: false | ||
|
||
- name: LS | ||
run: ls -la | ||
|
||
- name: check-CLA | ||
run: | | ||
import urllib.request | ||
import json | ||
import sys | ||
def jsonRequest(url, data={}): | ||
req = urllib.request.Request(url, | ||
headers={'Content-Type': 'application/json'}, | ||
data=json.dumps(data).encode('utf-8') if data else None) | ||
with urllib.request.urlopen(req) as response: | ||
return json.loads(response.read().decode('utf-8')) | ||
prCommits = jsonRequest('https://api.github.com/repos/juce-framework/JUCE/pulls/${{ github.event.number }}/commits') | ||
allAuthors = [commit[authorType]['login'] for authorType in ['author', 'committer'] for commit in prCommits if commit[authorType]] | ||
uniqueAuthors = [name for name in list(set(allAuthors)) if name != 'web-flow'] | ||
if (len(uniqueAuthors) == 0): | ||
print(f'\nNo author or committer user IDs contained within commit information\n\n{prCommits}\n') | ||
sys.exit(1) | ||
print(f'Authors: {uniqueAuthors}') | ||
claResult = jsonRequest('https://cla.juce.com/check', {'logins': uniqueAuthors}) | ||
unsignedLogins = claResult['unsigned'] | ||
if (len(unsignedLogins) != 0): | ||
print(f'\nThe following GitHub users need to sign the JUCE CLA: {", ".join(unsignedLogins)}\n\nPlease go to https://cla.juce.com to sign the JUCE Contributor Licence Agreement\n') | ||
sys.exit(1) | ||
shell: python | ||
run: python .github/scripts/check-cla.py ${{github.repository}} ${{ github.event.number }} |