[libcxx-commits] [libcxx] b1e7850 - [libc++][ci] Improve the phabricator-report script
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Sep 29 12:32:41 PDT 2020
Author: Louis Dionne
Date: 2020-09-29T15:32:27-04:00
New Revision: b1e78509678814de6684db3f7498d016f07a3d54
URL: https://github.com/llvm/llvm-project/commit/b1e78509678814de6684db3f7498d016f07a3d54
DIFF: https://github.com/llvm/llvm-project/commit/b1e78509678814de6684db3f7498d016f07a3d54.diff
LOG: [libc++][ci] Improve the phabricator-report script
- Detect whether a build has passed more accurately
- Retry pushing the status to Phabricator
- Allow running on a non-review branch
Added:
Modified:
libcxx/utils/ci/phabricator-report
Removed:
################################################################################
diff --git a/libcxx/utils/ci/phabricator-report b/libcxx/utils/ci/phabricator-report
index dffe00ba0b7c..71bf298e8f53 100755
--- a/libcxx/utils/ci/phabricator-report
+++ b/libcxx/utils/ci/phabricator-report
@@ -12,12 +12,57 @@ import io
import os
import phabricator
import re
+import socket
import subprocess
import sys
import time
LLVM_REVIEWS_API = "https://reviews.llvm.org/api/"
+def exponentialBackoffRetry(f, exception, maxAttempts=3):
+ """Tries calling a function, but retry with exponential backoff if the
+ function fails with the specified exception.
+ """
+ waitTime = 1
+ attempts = 0
+ while True:
+ try:
+ f()
+ break
+ except exception as e:
+ attempts += 1
+ if attempts == maxAttempts:
+ raise e
+ else:
+ time.sleep(waitTime)
+ waitTime *= 2
+
+def buildPassed(log):
+ """
+ Tries to guess whether a build has passed or not based on the logs
+ produced by it.
+
+ This is really hacky -- it would be better to use the status of the
+ script that runs the tests, however that script is being piped into
+ this script, so we can't know its exit status. What we do here is
+ basically look for abnormal CMake or Lit output, but that is tightly
+ coupled to the specific CI we're running.
+ """
+ # Lit reporting failures
+ matches = re.findall(r"^\s*Failed\s*:\s*(\d+)$", log, flags=re.MULTILINE)
+ if matches and any(int(match) > 0 for match in matches):
+ return False
+
+ # Error while running CMake
+ if 'CMake Error' in log or 'Configuring incomplete, errors occurred!' in log:
+ return False
+
+ # Ninja failed to build some target
+ if 'FAILED:' in log:
+ return False
+
+ return True
+
def main(argv):
parser = argparse.ArgumentParser(
description="""
@@ -31,8 +76,12 @@ with the results of the build.
The script is assumed to be running inside a Buildkite agent, and as such,
it assumes the existence of several environment variables that are specific
-to Buildkite. It also assumes that it is running in a context where the HEAD
-commit contains the Phabricator ID of the review to update.
+to Buildkite.
+
+It also assumes that it is running in a context where the HEAD commit contains
+the Phabricator ID of the review to update. If the commit does not contain the
+Phabricator ID, this script is basically a no-op. This allows running the CI
+on commits that are not triggered by a Phabricator review.
""")
args = parser.parse_args(argv)
@@ -60,7 +109,7 @@ commit contains the Phabricator ID of the review to update.
# Then, extract information from the environment and post-process the logs.
log.seek(0)
log = log.read()
- result = 'fail' if 'FAILED:' in log else 'pass'
+ result = 'pass' if buildPassed(log) else 'fail'
resultObject = {
'name': '{BUILDKITE_LABEL} ({BUILDKITE_BUILD_URL}#{BUILDKITE_JOB_ID})'.format(**os.environ),
'result': result,
@@ -70,15 +119,21 @@ commit contains the Phabricator ID of the review to update.
commitMessage = subprocess.check_output(['git', 'log', '--format=%B' , '-n', '1']).decode()
phabricatorID = re.search(r'^Phabricator-ID:\s+(.+)$', commitMessage, flags=re.MULTILINE)
- if not phabricatorID:
- raise RuntimeError('Could not find the Phabricator ID in the commit message. '
- 'The commit message was:\n{}'.format(commitMessage))
- else:
- phabricatorID = phabricatorID.group(1)
- token = os.environ['CONDUIT_TOKEN']
- phab = phabricator.Phabricator(token=token, host=LLVM_REVIEWS_API)
- phab.harbormaster.sendmessage(buildTargetPHID=phabricatorID, type=result, unit=[resultObject])
+ # If there's a Phabricator ID in the commit, then the build was triggered
+ # by a Phabricator review -- update the results back. Otherwise, don't
+ # do anything.
+ if phabricatorID:
+ phabricatorID = phabricatorID.group(1)
+ token = os.environ['CONDUIT_TOKEN']
+ phab = phabricator.Phabricator(token=token, host=LLVM_REVIEWS_API)
+ exponentialBackoffRetry(
+ lambda: phab.harbormaster.sendmessage(buildTargetPHID=phabricatorID, type=result, unit=[resultObject]),
+ exception=socket.timeout
+ )
+ else:
+ print('The HEAD commit does not appear to be tied to a Phabricator review -- '
+ 'not uploading the results to any review.')
if __name__ == '__main__':
main(sys.argv[1:])
More information about the libcxx-commits
mailing list