[libc++] Initial support for pre-commit CI with Buildkite

This commit adds basic files and scripts that are used for the Buildkite
pre-commit CI setup. This was tested to mostly work on a fork of llvm-project,
however some adjustments will have to be made as we complete the real
setup.
This commit is contained in:
Louis Dionne 2020-09-23 09:20:03 -04:00
parent 1fa06162c1
commit 9f21d341e8
5 changed files with 366 additions and 0 deletions

View File

@ -0,0 +1,63 @@
#===----------------------------------------------------------------------===##
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#===----------------------------------------------------------------------===##
#
# This Dockerfile describes the base image used to run the various libc++
# build bots. By default, the image runs the Buildkite Agent, however one
# can also just start the image with a shell to debug CI failures.
#
# To start a Buildkite Agent, run it as:
# $ docker run --env-file secrets.env -it $(docker build -q .)
#
# The environment variables in `secrets.env` must be replaced by the actual
# tokens for this to work. These should obviously never be checked in.
#
# To start a shell in the Docker image, use:
# $ docker run -it --volume "$(git rev-parse --show-toplevel):/llvm" --workdir "/llvm" $(docker build -q .) bash
#
# This will fire up the Docker container and mount the root of the monorepo
# as /llvm in the container. Be careful, the state in /llvm is shared between
# the container and the host machine.
#
FROM ubuntu:bionic
RUN apt-get update
RUN apt-get install -y bash curl
# 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)"
RUN ln -s $(find /usr/bin -regex '.+/clang\+\+-[a-zA-Z0-9.]+') /usr/bin/clang++
RUN ln -s $(find /usr/bin -regex '.+/clang-[a-zA-Z0-9.]+') /usr/bin/clang
# 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
# 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
# Install the Buildkite agent and dependencies
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
# By default, start the Buildkite agent (this requires a token).
CMD buildkite-agent start --tags "queue=libcxx-builders"

View File

@ -0,0 +1,81 @@
#===----------------------------------------------------------------------===##
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#===----------------------------------------------------------------------===##
#
# This file describes the various pre-commit CI bots used to test libc++.
#
# This file should never contain logic -- all the logic must be offloaded
# into scripts. This is critical to being able to reproduce CI issues outside
# of the CI environment, which is important for debugging.
#
steps:
- label: "C++03"
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 | 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 | 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 | 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 | 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 | libcxx/utils/ci/phabricator-report"
agents:
queue: "libcxx-builders"
- label: "32 bits"
command: "set -o pipefail && libcxx/utils/ci/run-buildbot.sh x86_64-ubuntu-32bit | 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 | 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 | 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 | 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 | 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 | 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 | libcxx/utils/ci/phabricator-report"
agents:
queue: "libcxx-builders"

View File

@ -0,0 +1,86 @@
#!/usr/bin/env python3
#===----------------------------------------------------------------------===##
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#===----------------------------------------------------------------------===##
import argparse
import io
import os
import phabricator
import re
import subprocess
import sys
import time
LLVM_REVIEWS_API = "https://reviews.llvm.org/api/"
def main(argv):
parser = argparse.ArgumentParser(
description="""
This script gathers information about a Buildkite build and updates the
Phabricator review associated to the HEAD commit with those results.
The intended usage of this script is to pipe the output of a command defined
in a Buildkite pipeline into it. The script will echo everything to stdout,
like tee, but will also update the Phabricator review associated to HEAD
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.
""")
parser.add_argument('--token', type=str, required=True,
help="The Conduit token to use to authenticate with {}.".format(LLVM_REVIEWS_API))
args = parser.parse_args(argv)
for var in ('BUILDKITE_LABEL', 'BUILDKITE_JOB_ID', 'BUILDKITE_BUILD_URL', 'CONDUIT_TOKEN'):
if var not in os.environ:
raise RuntimeError(
'The {} environment variable must exist -- are you running '
'this script from a Buildkite agent?'.format(var))
# First, read all the log input and write it line-by-line to stdout.
# This is important so that we can follow progress in the Buildkite
# console. Since we're being piped into in real time, it's also the
# moment to time the duration of the job.
start = time.time()
log = io.StringIO()
while True:
line = sys.stdin.readline()
if line == '':
break
sys.stdout.write(line)
sys.stdout.flush() # flush every line to avoid buffering
log.write(line)
end = time.time()
# 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'
resultObject = {
'name': '{BUILDKITE_LABEL} ({BUILDKITE_BUILD_URL}#{BUILDKITE_JOB_ID})'.format(**os.environ),
'result': result,
'duration': end - start,
'details': log
}
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 __name__ == '__main__':
main(sys.argv[1:])

125
libcxx/utils/ci/run-buildbot.sh Executable file
View File

@ -0,0 +1,125 @@
#!/usr/bin/env bash
#===----------------------------------------------------------------------===##
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#===----------------------------------------------------------------------===##
set -ex
BUILDER="${1}"
args=()
args+=("-DLLVM_ENABLE_PROJECTS=libcxx;libunwind;libcxxabi")
args+=("-DLIBCXX_CXX_ABI=libcxxabi")
case "${BUILDER}" in
x86_64-ubuntu-cxx03)
export CC=clang
export CXX=clang++
args+=("-DLLVM_LIT_ARGS=-sv --show-unsupported --param=std=c++03")
;;
x86_64-ubuntu-cxx11)
export CC=clang
export CXX=clang++
args+=("-DLLVM_LIT_ARGS=-sv --show-unsupported --param=std=c++11")
;;
x86_64-ubuntu-cxx14)
export CC=clang
export CXX=clang++
args+=("-DLLVM_LIT_ARGS=-sv --show-unsupported --param=std=c++14")
;;
x86_64-ubuntu-cxx17)
export CC=clang
export CXX=clang++
args+=("-DLLVM_LIT_ARGS=-sv --show-unsupported --param=std=c++17")
;;
x86_64-ubuntu-cxx2a)
export CC=clang
export CXX=clang++
args+=("-DLLVM_LIT_ARGS=-sv --show-unsupported --param=std=c++2a")
;;
x86_64-ubuntu-noexceptions)
export CC=clang
export CXX=clang++
args+=("-DLLVM_LIT_ARGS=-sv --show-unsupported")
args+=("-DLIBCXX_ENABLE_EXCEPTIONS=OFF")
args+=("-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF")
;;
x86_64-ubuntu-32bit)
export CC=clang
export CXX=clang++
args+=("-DLLVM_LIT_ARGS=-sv --show-unsupported")
args+=("-DLLVM_BUILD_32_BITS=ON")
;;
x86_64-ubuntu-gcc)
export CC=gcc
export CXX=g++
args+=("-DLLVM_LIT_ARGS=-sv --show-unsupported")
;;
x86_64-ubuntu-asan)
export CC=clang
export CXX=clang++
args+=("-DLLVM_USE_SANITIZER=Address")
args+=("-DLLVM_LIT_ARGS=-sv --show-unsupported")
;;
x86_64-ubuntu-msan)
export CC=clang
export CXX=clang++
args+=("-DLLVM_USE_SANITIZER=MemoryWithOrigins")
args+=("-DLLVM_LIT_ARGS=-sv --show-unsupported")
;;
x86_64-ubuntu-tsan)
export CC=clang
export CXX=clang++
args+=("-DLLVM_USE_SANITIZER=Thread")
args+=("-DLLVM_LIT_ARGS=-sv --show-unsupported")
;;
x86_64-ubuntu-ubsan)
export CC=clang
export CXX=clang++
args+=("-DLLVM_USE_SANITIZER=Undefined")
args+=("-DLIBCXX_ABI_UNSTABLE=ON")
args+=("-DLLVM_LIT_ARGS=-sv --show-unsupported")
;;
x86_64-ubuntu-with_llvm_unwinder)
export CC=clang
export CXX=clang++
args+=("-DLLVM_LIT_ARGS=-sv --show-unsupported")
args+=("-DLIBCXXABI_USE_LLVM_UNWINDER=ON")
;;
x86_64-ubuntu-singlethreaded)
export CC=clang
export CXX=clang++
args+=("-DLLVM_LIT_ARGS=-sv --show-unsupported")
args+=("-DLIBCXX_ENABLE_THREADS=OFF")
args+=("-DLIBCXXABI_ENABLE_THREADS=OFF")
args+=("-DLIBCXX_ENABLE_MONOTONIC_CLOCK=OFF")
;;
*)
echo "${BUILDER} is not a known configuration"
exit 1
;;
esac
UMBRELLA_ROOT="$(git rev-parse --show-toplevel)"
LLVM_ROOT="${UMBRELLA_ROOT}/llvm"
BUILD_DIR="${UMBRELLA_ROOT}/build/${BUILDER}"
echo "--- Generating CMake"
rm -rf "${BUILD_DIR}"
cmake -S "${LLVM_ROOT}" -B "${BUILD_DIR}" -GNinja -DCMAKE_BUILD_TYPE=RelWithDebInfo "${args[@]}"
echo "--- Building libc++ and libc++abi"
ninja -C "${BUILD_DIR}" check-cxx-deps cxxabi
echo "+++ Running the libc++ tests"
ninja -C "${BUILD_DIR}" check-cxx
echo "+++ Running the libc++abi tests"
ninja -C "${BUILD_DIR}" check-cxxabi
echo "+++ Running the libc++ benchmarks"
ninja -C "${BUILD_DIR}" check-cxx-benchmarks

View File

@ -0,0 +1,11 @@
#
# This file template shows which environment variables are required to run
# libc++ CI nodes. The actual values of these tokens must obviously never be
# checked in.
#
# Required to talk with the Phabricator API to update build results
CONDUIT_TOKEN=<secret>
# Required to register a new agent with Buildkite
BUILDKITE_AGENT_TOKEN=<secret>