diff --git a/libcxx/utils/ci/Dockerfile b/libcxx/utils/ci/Dockerfile --- a/libcxx/utils/ci/Dockerfile +++ b/libcxx/utils/ci/Dockerfile @@ -24,12 +24,33 @@ # as /llvm in the container. Be careful, the state in /llvm is shared between # the container and the host machine. # +# Finally, a pre-built version of this image is available on DockerHub as +# ldionne/libcxx-builder. To use the pre-built version of the image, use +# +# $ docker pull ldionne/libcxx-builder +# $ docker run -it ldionne/libcxx-builder +# +# To update the image, rebuild it and push it to ldionne/libcxx-builder (which +# will obviously only work if you have permission to do so). +# +# $ docker build -t ldionne/libcxx-builder . +# $ docker push ldionne/libcxx-builder +# FROM ubuntu:bionic RUN apt-get update RUN apt-get install -y bash curl +# Install various tools used by the build or the test suite +RUN apt-get install -y ninja-build python3 sphinx-doc git + +# Install the Phabricator Python module to allow uploading results to Phabricator. +# This MUST be done before installing a recent GCC, otherwise /usr/bin/gcc is +# overwritten to an older GCC. +RUN apt-get install -y python3-pip +RUN pip3 install phabricator + # Install the most recently released LLVM RUN apt-get install -y lsb-release wget software-properties-common RUN bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)" @@ -39,25 +60,26 @@ # Install a recent GCC RUN add-apt-repository ppa:ubuntu-toolchain-r/test RUN apt-get update && apt install -y gcc-10 g++-10 -RUN ln -s $(find /usr/bin -regex '.+/g\+\+-[a-zA-Z0-9.]+') /usr/bin/g++ -RUN ln -s $(find /usr/bin -regex '.+/gcc-[a-zA-Z0-9.]+') /usr/bin/gcc +RUN ln -f -s /usr/bin/g++-10 /usr/bin/g++ +RUN ln -f -s /usr/bin/gcc-10 /usr/bin/gcc # Install a recent CMake RUN wget https://github.com/Kitware/CMake/releases/download/v3.18.2/cmake-3.18.2-Linux-x86_64.sh -O /tmp/install-cmake.sh RUN bash /tmp/install-cmake.sh --prefix=/usr --exclude-subdir --skip-license RUN rm /tmp/install-cmake.sh -# Install other tools used by the build or the test suite -RUN apt-get install -y ninja-build python3 sphinx-doc +# Change the user to a non-root user, since some of the libc++ tests +# (e.g. filesystem) require running as non-root. Also setup passwordless sudo. +RUN apt-get install -y sudo +RUN echo "ALL ALL = (ALL) NOPASSWD: ALL" >> /etc/sudoers +RUN useradd --create-home libcxx-builder +USER libcxx-builder +WORKDIR /home/libcxx-builder -# Install the Buildkite agent and dependencies +# Install the Buildkite agent and dependencies. This must be done as non-root +# for the Buildkite agent to be installed in a path where we can find it. RUN bash -c "$(curl -sL https://raw.githubusercontent.com/buildkite/agent/master/install.sh)" -RUN apt-get install -y git -ENV PATH="${PATH}:/root/.buildkite-agent/bin" - -# Install the Phabricator Python module to allow uploading results to Phabricator -RUN apt-get install -y python3-pip -RUN pip3 install phabricator +ENV PATH="${PATH}:/home/libcxx-builder/.buildkite-agent/bin" # By default, start the Buildkite agent (this requires a token). CMD buildkite-agent start --tags "queue=libcxx-builders" diff --git a/libcxx/utils/ci/buildkite-pipeline.yml b/libcxx/utils/ci/buildkite-pipeline.yml --- a/libcxx/utils/ci/buildkite-pipeline.yml +++ b/libcxx/utils/ci/buildkite-pipeline.yml @@ -16,66 +16,61 @@ steps: - label: "C++03" - command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-cxx03" + command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-cxx03 | libcxx/utils/ci/phabricator-report" agents: queue: "libcxx-builders" - label: "C++11" - command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-cxx11" + command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-cxx11 | libcxx/utils/ci/phabricator-report" agents: queue: "libcxx-builders" - label: "C++14" - command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-cxx14" + command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-cxx14 | libcxx/utils/ci/phabricator-report" agents: queue: "libcxx-builders" - label: "C++17" - command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-cxx17" + command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-cxx17 | libcxx/utils/ci/phabricator-report" agents: queue: "libcxx-builders" - label: "C++20" - command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-cxx2a" + command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-cxx2a | libcxx/utils/ci/phabricator-report" agents: queue: "libcxx-builders" - label: "-fno-exceptions" - command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-noexceptions" - agents: - queue: "libcxx-builders" - - - label: "32 bits" - command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-32bit" + command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-noexceptions | libcxx/utils/ci/phabricator-report" agents: queue: "libcxx-builders" - label: "GCC/C++20" - command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-gcc" + command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-gcc | libcxx/utils/ci/phabricator-report" agents: queue: "libcxx-builders" - label: "ASAN" - command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-asan" + command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-asan | libcxx/utils/ci/phabricator-report" agents: queue: "libcxx-builders" - label: "TSAN" - command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-tsan" + command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-tsan | libcxx/utils/ci/phabricator-report" agents: queue: "libcxx-builders" - label: "UBSAN" - command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-ubsan" + command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-ubsan | libcxx/utils/ci/phabricator-report" agents: queue: "libcxx-builders" - label: "With LLVM's libunwind" - command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-with_llvm_unwinder" + command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-with_llvm_unwinder | libcxx/utils/ci/phabricator-report" agents: queue: "libcxx-builders" - label: "Single-threaded" - command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-singlethreaded" + command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-singlethreaded | libcxx/utils/ci/phabricator-report" agents: queue: "libcxx-builders" diff --git a/libcxx/utils/ci/phabricator-report b/libcxx/utils/ci/phabricator-report --- a/libcxx/utils/ci/phabricator-report +++ b/libcxx/utils/ci/phabricator-report @@ -12,12 +12,57 @@ 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=""" @@ -60,7 +105,7 @@ # 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, @@ -78,7 +123,10 @@ token = os.environ['CONDUIT_TOKEN'] phab = phabricator.Phabricator(token=token, host=LLVM_REVIEWS_API) - phab.harbormaster.sendmessage(buildTargetPHID=phabricatorID, type=result, unit=[resultObject]) + exponentialBackoffRetry( + lambda: phab.harbormaster.sendmessage(buildTargetPHID=phabricatorID, type=result, unit=[resultObject]), + exception=socket.timeout + ) if __name__ == '__main__': main(sys.argv[1:]) diff --git a/libcxx/utils/ci/run-buildbot.sh b/libcxx/utils/ci/run-buildbot.sh --- a/libcxx/utils/ci/run-buildbot.sh +++ b/libcxx/utils/ci/run-buildbot.sh @@ -121,5 +121,5 @@ echo "+++ Running the libc++abi tests" ninja -C "${BUILD_DIR}" check-cxxabi -echo "+++ Running the libc++ benchmarks" -ninja -C "${BUILD_DIR}" check-cxx-benchmarks +# echo "+++ Running the libc++ benchmarks" +# ninja -C "${BUILD_DIR}" check-cxx-benchmarks