88variables that are available in the Github Action environment. Specifically:
99
1010* GITHUB_WORKSPACE: directory where the git clone is located
11+ * GITHUB_SHA: the git commit SHA of the artificial Github PR test merge commit
1112* GITHUB_BASE_REF: the git ref for the base branch
12- * GITHUB_HEAD_REF: the git commit ref of the head branch
1313* GITHUB_TOKEN: token authorizing Github API usage
1414* GITHUB_REPOSITORY: "org/repo" name of the Github repository of this PR
1515* GITHUB_REF: string that includes this Github PR number
16- * GITHUB_RUN_ID: unique ID for each workflow run
17- * GITHUB_SERVER_URL: the URL of the GitHub server
1816
19- This script tests each git commit between (and not including) GITHUB_HEAD_REF and
17+ This script tests each git commit between (and not including) GITHUB_SHA and
2018GITHUB_BASE_REF multiple ways:
2119
22201. Ensure that the committer and author do not match any bad patterns (e.g.,
5553NACP = "bot:notacherrypick"
5654
5755GITHUB_WORKSPACE = os .environ .get ('GITHUB_WORKSPACE' )
56+ GITHUB_SHA = os .environ .get ('GITHUB_SHA' )
5857GITHUB_BASE_REF = os .environ .get ('GITHUB_BASE_REF' )
59- GITHUB_HEAD_REF = os .environ .get ('GITHUB_HEAD_REF' )
6058GITHUB_TOKEN = os .environ .get ('GITHUB_TOKEN' )
6159GITHUB_REPOSITORY = os .environ .get ('GITHUB_REPOSITORY' )
6260GITHUB_REF = os .environ .get ('GITHUB_REF' )
63- GITHUB_RUN_ID = os .environ .get ('GITHUB_RUN_ID' )
64- GITHUB_SERVER_URL = os .environ .get ('GITHUB_SERVER_URL' )
65- PR_NUM = os .environ .get ('PR_NUM' )
6661
6762# Sanity check
6863if (GITHUB_WORKSPACE is None or
64+ GITHUB_SHA is None or
6965 GITHUB_BASE_REF is None or
70- GITHUB_HEAD_REF is None or
7166 GITHUB_TOKEN is None or
7267 GITHUB_REPOSITORY is None or
73- GITHUB_REF is None or
74- GITHUB_RUN_ID is None or
75- GITHUB_SERVER_URL is None or
76- PR_NUM is None ):
68+ GITHUB_REF is None ):
7769 print ("Error: this script is designed to run as a Github Action" )
7870 exit (1 )
7971
@@ -93,50 +85,6 @@ def make_commit_message(repo, hash):
9385
9486#----------------------------------------------------------------------------
9587
96- """
97- Iterate through the BAD results, collect the error messages, and send a nicely
98- formatted comment to the PR.
99-
100- For the structure of the results dictionary, see comment for print_results()
101- below.
102-
103- """
104- def comment_on_pr (pr , results , repo ):
105- # If there are no BAD results, just return without posting a comment to the
106- # GitHub PR.
107- if len (results [BAD ]) == 0 :
108- return
109-
110- comment = "Hello! The Git Commit Checker CI bot found a few problems with this PR:"
111- for hash , entry in results [BAD ].items ():
112- comment += f"\n \n **{ hash [:8 ]} : { make_commit_message (repo , hash )} **"
113- for check_name , message in entry .items ():
114- if message is not None :
115- comment += f"\n * *{ check_name } : { message } *"
116- comment_footer = "\n \n Please fix these problems and, if necessary, force-push new commits back up to the PR branch. Thanks!"
117-
118- # GitHub says that 65536 characters is the limit of comment messages, so
119- # check if our comment is over that limit. If it is, truncate it to fit, and
120- # add a message explaining with a link to the full error list.
121- comment_char_limit = 65536
122- if len (comment + comment_footer ) >= comment_char_limit :
123- run_url = f"{ GITHUB_SERVER_URL } /{ GITHUB_REPOSITORY } /actions/runs/{ GITHUB_RUN_ID } ?check_suite_focus=true"
124- truncation_message = f"\n \n **Additional errors could not be shown...\n [Please click here for a full list of errors.]({ run_url } )**"
125- # Cut the comment down so we can get the comment itself, and the new
126- # message in.
127- comment = comment [:(comment_char_limit - len (comment_footer + truncation_message ))]
128- # In case a newline gets split in half, remove the leftover '\' (if
129- # there is one). (This is purely an aesthetics choice).
130- comment = comment .rstrip ("\\ " )
131- comment += truncation_message
132-
133- comment += comment_footer
134- pr .create_issue_comment (comment )
135-
136- return
137-
138- #----------------------------------------------------------------------------
139-
14088"""
14189The results dictionary is in the following format:
14290
@@ -294,15 +242,15 @@ def _is_entirely_submodule_updates(repo, commit):
294242#----------------------------------------------------------------------------
295243
296244def check_all_commits (config , repo ):
297- # Get a list of commits that we'll be examining. Use the programmatic form
298- # of "git log GITHUB_BASE_REF..GITHUB_HEAD_REF" (i.e., "git log
299- # ^GITHUB_BASE_REF GITHUB_HEAD_REF") to do the heavy lifting to find that
300- # set of commits. Because we're using pull_request_target, GITHUB_BASE_REF
301- # is already checked out. GITHUB_HEAD_REF has never been checked out, so we
302- # specify "origin/{GITHUB_HEAD_REF}".
245+ # Get a list of commits that we'll be examining. Use the progromatic form
246+ # of "git log GITHUB_BASE_REF..GITHUB_SHA" (i.e., "git log ^GITHUB_BASE_REF
247+ # GITHUB_SHA") to do the heavy lifting to find that set of commits.
303248 git_cli = git .cmd .Git (GITHUB_WORKSPACE )
304- hashes = git_cli .log (f"--pretty=format:%h" ,
305- f"{ GITHUB_BASE_REF } ..origin/{ GITHUB_HEAD_REF } " ).splitlines ()
249+ hashes = git_cli .log (f"--pretty=format:%h" , f"origin/{ GITHUB_BASE_REF } ..{ GITHUB_SHA } " ).splitlines ()
250+
251+ # The first entry in the list will be the artificial Github merge commit for
252+ # this PR. We don't want to examine this commit.
253+ del hashes [0 ]
306254
307255 #------------------------------------------------------------------------
308256
@@ -344,7 +292,15 @@ def check_all_commits(config, repo):
344292If "bot:notacherrypick" is in the PR description, then disable the
345293cherry-pick message requirement.
346294"""
347- def check_github_pr_description (config , pr ):
295+ def check_github_pr_description (config ):
296+ g = Github (GITHUB_TOKEN )
297+ repo = g .get_repo (GITHUB_REPOSITORY )
298+
299+ # Extract the PR number from GITHUB_REF
300+ match = re .search ("/(\d+)/" , GITHUB_REF )
301+ pr_num = int (match .group (1 ))
302+ pr = repo .get_pull (pr_num )
303+
348304 if pr .body and NACP in pr .body :
349305 config ['cherry pick required' ] = False
350306
@@ -378,17 +334,11 @@ def load_config():
378334
379335def main ():
380336 config = load_config ()
337+ check_github_pr_description (config )
381338
382- g = Github (GITHUB_TOKEN )
383- github_repo = g .get_repo (GITHUB_REPOSITORY )
384- pr_num = int (PR_NUM )
385- pr = github_repo .get_pull (pr_num )
386- check_github_pr_description (config , pr )
387-
388- local_repo = git .Repo (GITHUB_WORKSPACE )
389- results , hashes = check_all_commits (config , local_repo )
390- print_results (results , local_repo , hashes )
391- comment_on_pr (pr , results , local_repo )
339+ repo = git .Repo (GITHUB_WORKSPACE )
340+ results , hashes = check_all_commits (config , repo )
341+ print_results (results , repo , hashes )
392342
393343 if len (results [BAD ]) == 0 :
394344 print ("\n Test passed: everything was good!" )
0 commit comments