From 5f1fc5fa00ddbdf2ff7d70c2ac91a6377031cd38 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Wed, 24 Jul 2024 14:32:57 -0600 Subject: [PATCH 1/7] CI: install some more llvm/clang packages for coverage and sanitizers --- .gitlab-ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8465c87ae..687d00364 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,7 +16,7 @@ workflow: variables: FDO_UPSTREAM_REPO: 'cairo/cairo' FDO_DISTRIBUTION_VERSION: '40' - FDO_DISTRIBUTION_TAG: '2024-06-06.0' + FDO_DISTRIBUTION_TAG: '2024-07-24-coverage.0' # TODO: should probably get its own image at some point instead of reusing the GStreamer one # See https://gitlab.freedesktop.org/gstreamer/gstreamer/-/blob/main/.gitlab-image-tags.yml for latest @@ -97,6 +97,12 @@ fedora image: util-linux poppler-utils clang + clang-analyzer + clang-tools-extra + compiler-rt + libasan + libubsan + llvm .build fedora: extends: From b5c6ef285395e56cb2e002e64bbee5d4a29df3a0 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Fri, 26 Jul 2024 10:20:25 -0600 Subject: [PATCH 2/7] CI: Install rust and grcov The Rust toolchain is so that we can build and install grcov, which is Mozilla's tool to aggregate test coverage data into a report. --- .gitlab-ci.yml | 13 ++++- .gitlab-ci/env.sh | 2 + .gitlab-ci/install-grcov.sh | 8 +++ .gitlab-ci/install-rust-tools.sh | 11 ++++ .gitlab-ci/install-rust.sh | 92 ++++++++++++++++++++++++++++++++ 5 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 .gitlab-ci/env.sh create mode 100644 .gitlab-ci/install-grcov.sh create mode 100644 .gitlab-ci/install-rust-tools.sh create mode 100644 .gitlab-ci/install-rust.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 687d00364..da4a78eae 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,7 +16,7 @@ workflow: variables: FDO_UPSTREAM_REPO: 'cairo/cairo' FDO_DISTRIBUTION_VERSION: '40' - FDO_DISTRIBUTION_TAG: '2024-07-24-coverage.0' + FDO_DISTRIBUTION_TAG: '2024-07-26-coverage.0' # TODO: should probably get its own image at some point instead of reusing the GStreamer one # See https://gitlab.freedesktop.org/gstreamer/gstreamer/-/blob/main/.gitlab-image-tags.yml for latest @@ -26,6 +26,9 @@ variables: DEFAULT_MESON_ARGS: > --default-library=both + RUST_STABLE: "1.80.0" + RUSTUP_VERSION: "1.27.1" + stages: - prep - build @@ -103,6 +106,14 @@ fedora image: libasan libubsan llvm + wget + FDO_DISTRIBUTION_EXEC: >- + bash .gitlab-ci/install-rust.sh --rustup-version ${RUSTUP_VERSION} \ + --stable ${RUST_STABLE} \ + --arch x86_64-unknown-linux-gnu && + bash .gitlab-ci/install-rust-tools.sh && + bash .gitlab-ci/install-grcov.sh && + rm -rf /root/.cargo /root/.cache # cleanup compilation dirs; binaries are installed now .build fedora: extends: diff --git a/.gitlab-ci/env.sh b/.gitlab-ci/env.sh new file mode 100644 index 000000000..b5761529f --- /dev/null +++ b/.gitlab-ci/env.sh @@ -0,0 +1,2 @@ +export RUSTUP_HOME='/usr/local/rustup' +export PATH=$PATH:/usr/local/cargo/bin diff --git a/.gitlab-ci/install-grcov.sh b/.gitlab-ci/install-grcov.sh new file mode 100644 index 000000000..43edaa73f --- /dev/null +++ b/.gitlab-ci/install-grcov.sh @@ -0,0 +1,8 @@ +source ./.gitlab-ci/env.sh + +set -eu +export CARGO_HOME='/usr/local/cargo' + +# Coverage tools +cargo install grcov +rustup component add llvm-tools-preview diff --git a/.gitlab-ci/install-rust-tools.sh b/.gitlab-ci/install-rust-tools.sh new file mode 100644 index 000000000..23e55f4d9 --- /dev/null +++ b/.gitlab-ci/install-rust-tools.sh @@ -0,0 +1,11 @@ +source ./.gitlab-ci/env.sh + +set -eu +export CARGO_HOME='/usr/local/cargo' + +rustup component add clippy +rustup component add rustfmt +# cargo install --force cargo-c +cargo install --version ^1.0 gitlab_clippy +cargo install --force cargo-deny +# cargo install --force cargo-outdated diff --git a/.gitlab-ci/install-rust.sh b/.gitlab-ci/install-rust.sh new file mode 100644 index 000000000..93cdb4abd --- /dev/null +++ b/.gitlab-ci/install-rust.sh @@ -0,0 +1,92 @@ +#!/bin/bash + +set -o errexit -o pipefail -o noclobber -o nounset + +source ./.gitlab-ci/env.sh + +export CARGO_HOME='/usr/local/cargo' + +PARSED=$(getopt --options '' --longoptions 'rustup-version:,stable:,minimum:,nightly,arch:' --name "$0" -- "$@") +if [ $? -ne 0 ]; then + echo 'Terminating...' >&2 + exit 1 +fi + +eval set -- "$PARSED" +unset PARSED + +RUSTUP_VERSION= +STABLE= +MINIMUM= +NIGHTLY= +ARCH= + +while true; do + case "$1" in + '--rustup-version') + RUSTUP_VERSION=$2 + shift 2 + ;; + + '--stable') + STABLE=$2 + shift 2 + ;; + + '--minimum') + MINIMUM=$2 + shift 2 + ;; + + '--nightly') + NIGHTLY=1 + shift 1 + ;; + + '--arch') + ARCH=$2 + shift 2 + ;; + + '--') + shift + break + ;; + + *) + echo "Programming error" + exit 3 + ;; + esac +done + +if [ -z "$RUSTUP_VERSION" ]; then + echo "missing --rustup-version argument" + exit 1 +fi + +if [ -z "$STABLE" ]; then + echo "missing --stable argument, please pass the stable version of rustc you want" + exit 1 +fi + +if [ -z "$ARCH" ]; then + echo "missing --arch argument, please pass an architecture triple like x86_64-unknown-linux-gnu" + exit 1 +fi + +RUSTUP_URL=https://static.rust-lang.org/rustup/archive/$RUSTUP_VERSION/$ARCH/rustup-init +wget $RUSTUP_URL + +chmod +x rustup-init +./rustup-init -y --no-modify-path --profile minimal --default-toolchain $STABLE +rm rustup-init +chmod -R a+w $RUSTUP_HOME $CARGO_HOME + +if [ -n "$MINIMUM" ]; then + rustup toolchain install $MINIMUM +fi + +if [ -n "$NIGHTLY" ]; then + rustup toolchain install nightly +fi From 744f4d75b33355b9b2d29c809b0c44bd3ea90b0b Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Fri, 26 Jul 2024 11:09:47 -0600 Subject: [PATCH 3/7] CI: Add a basic test coverage job Later we'll add one coverage job per backend, and aggregate all of the results at the end for the coverage report. --- .gitlab-ci.yml | 25 +++++++++++++++++++++++++ .gitlab-ci/build-with-coverage.sh | 17 +++++++++++++++++ .gitlab-ci/gen-coverage.sh | 14 ++++++++++++++ 3 files changed, 56 insertions(+) create mode 100644 .gitlab-ci/build-with-coverage.sh create mode 100644 .gitlab-ci/gen-coverage.sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index da4a78eae..55aff0b80 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -477,3 +477,28 @@ macOS x86 host: - export CAIRO_TEST_IGNORE_quartz_rgb24=$(tr '\n' ',' < .gitlab-ci/ignore-quartz-rgb24.txt) - export CAIRO_TEST_TARGET=quartz - (cd build/test && srcdir=../../test ./cairo-test-suite) + +coverage: + stage: 'analysis' + extends: + - '.fdo.distribution-image@fedora' + needs: + - job: 'fedora image' + artifacts: false + script: + - source ./.gitlab-ci/env.sh + - bash -x ./.gitlab-ci/build-with-coverage.sh + - bash -x ./.gitlab-ci/gen-coverage.sh + coverage: '/Coverage: \d+\.\d+/' + artifacts: + name: "cairo-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + expire_in: 2 days + when: always + reports: + coverage_report: + coverage_format: cobertura + path: public/coverage.xml + paths: + - "_build/meson-logs" + - public + diff --git a/.gitlab-ci/build-with-coverage.sh b/.gitlab-ci/build-with-coverage.sh new file mode 100644 index 000000000..ed867986d --- /dev/null +++ b/.gitlab-ci/build-with-coverage.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +set -eux -o pipefail + +export CFLAGS="-coverage -ftest-coverage -fprofile-arcs" + +export CAIRO_TEST_IGNORE_image_argb32=$(tr '\n' ',' < .gitlab-ci/ignore-image-argb32.txt) +export CAIRO_TEST_IGNORE_image_rgb24=$(tr '\n' ',' < .gitlab-ci/ignore-image-rgb24.txt) +export CAIRO_TEST_IGNORE_image16_rgb24=$(tr '\n' ',' < .gitlab-ci/ignore-image16-rgb24.txt) +export CAIRO_TEST_TARGET=image,image16 + +meson setup --buildtype=debug _build . +meson compile -C _build + +export srcdir=../../test +cd _build/test +xvfb-run ./cairo-test-suite diff --git a/.gitlab-ci/gen-coverage.sh b/.gitlab-ci/gen-coverage.sh new file mode 100644 index 000000000..cfc78e240 --- /dev/null +++ b/.gitlab-ci/gen-coverage.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +set -eux -o pipefail + +mkdir -p public +grcov _build --source-dir ./ --prefix-dir ../ --output-type cobertura --branch --ignore-not-existing -o public/coverage.xml +grcov _build --source-dir ./ --prefix-dir ../ --output-type html --branch --ignore-not-existing -o public/coverage + +# Print "Coverage: 42.42" so .gitlab-ci.yml will pick it up with a regex +# +# We scrape this from the HTML report, not the JSON summary, because coverage.json +# uses no decimal places, just something like "42%". + +grep -Eo 'abbr title.* %' public/coverage/index.html | head -n 1 | grep -Eo '[0-9.]+ %' | grep -Eo '[0-9.]+' | awk '{ print "Coverage:", $1 }' From 2366646d9324141cb4af4ae052600a8cbfc4fd62 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Fri, 26 Jul 2024 13:41:47 -0600 Subject: [PATCH 4/7] Deploy the coverage report to gitlab pages It should appear in https://cairo.pages.gitlab.freedesktop.org/coverage --- .gitlab-ci.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 55aff0b80..252cd5831 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -33,6 +33,7 @@ stages: - prep - build - test + - deploy # Global CI policy: This can be used to configure global behaviour our our jobs default: @@ -502,3 +503,16 @@ coverage: - "_build/meson-logs" - public +pages: + stage: 'deploy' + needs: [ coverage ] + script: + # No-op, just to gitlab thinks there's something to do. + # The jobs that this job depends on have already populated public/ + - echo + artifacts: + paths: + - public + rules: + # Restrict to the main branch so not every branch tries to deploy the web site + - if: ($CI_DEFAULT_BRANCH == $CI_COMMIT_BRANCH) From e6e76c5c25faf86ce6b914d05a3e942899013e2a Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Fri, 26 Jul 2024 19:15:48 -0600 Subject: [PATCH 5/7] Move the analysis stage to just before deploy --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 252cd5831..59c711283 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -33,6 +33,7 @@ stages: - prep - build - test + - analysis - deploy # Global CI policy: This can be used to configure global behaviour our our jobs From acb5e2e80abc66243ef787b2687e58faa5795cc4 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Wed, 24 Jul 2024 14:41:16 -0600 Subject: [PATCH 6/7] CI: Add a job for static analysis We add this in a new 'analysis' stage in the CI, which is where we'll put jobs for sanitizers, test coverage reports, etc. --- .gitlab-ci.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 59c711283..ef690c447 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -31,6 +31,7 @@ variables: stages: - prep + - analysis - build - test - analysis @@ -504,6 +505,18 @@ coverage: - "_build/meson-logs" - public +# Run static analysis. +static-scan: + stage: 'analysis' + extends: + - '.fdo.distribution-image@fedora' + variables: + MESON_ARGS: > + --buildtype=debug + script: + - meson setup ${MESON_ARGS} builddir . + - ninja -C builddir scan-build + pages: stage: 'deploy' needs: [ coverage ] From dd4da92782454a21ed344f5c2b8575f43d0b9343 Mon Sep 17 00:00:00 2001 From: Federico Mena Quintero Date: Fri, 26 Jul 2024 16:10:26 -0600 Subject: [PATCH 7/7] Keep artifacts for the static-scan job --- .gitlab-ci.yml | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ef690c447..96d8c1cb1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -481,6 +481,23 @@ macOS x86 host: - export CAIRO_TEST_TARGET=quartz - (cd build/test && srcdir=../../test ./cairo-test-suite) +# Run static analysis. +static-scan: + stage: 'analysis' + extends: + - '.fdo.distribution-image@fedora' + variables: + MESON_ARGS: > + --buildtype=debug + script: + - meson setup ${MESON_ARGS} _scan_build . + - ninja -C _scan_build scan-build + artifacts: + name: "cairo-${CI_JOB_NAME}-${CI_COMMIT_REF_NAME}" + when: always + paths: + - "_scan_build/meson-logs/scanbuild" + coverage: stage: 'analysis' extends: @@ -505,18 +522,6 @@ coverage: - "_build/meson-logs" - public -# Run static analysis. -static-scan: - stage: 'analysis' - extends: - - '.fdo.distribution-image@fedora' - variables: - MESON_ARGS: > - --buildtype=debug - script: - - meson setup ${MESON_ARGS} builddir . - - ninja -C builddir scan-build - pages: stage: 'deploy' needs: [ coverage ]