Skip to content

[ci] Testing code coverage workflow #18710

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Draft
wants to merge 25 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7f02f66
[coverage] Use alma9 to run code coverage
pcanal Apr 22, 2025
970aff4
[coverage] Update yml to match newer build_root.py syntax
pcanal Apr 22, 2025
5e3ce5b
[coverage] filter out builtins and \*-prefix
pcanal Apr 22, 2025
853e20d
[coverage] filter out bindings/pyroot/cppyy
pcanal Apr 23, 2025
81edd6d
[coverage] Reduce verbosity of gcovr (more than 77M of debug output)
pcanal Apr 23, 2025
74357e8
[coverage] Use multiple cores for gcovr
pcanal Apr 23, 2025
ae15c55
[coverage] Update to v5 of codecov-action
pcanal Apr 23, 2025
23abdc6
[ci][coverage] Extend env output
pcanal Apr 23, 2025
78c798a
[coverage] Generate artifact for coverage nigthlies
pcanal Apr 24, 2025
c4e3929
[ci][coverage] Add S3 authentication.
pcanal Apr 30, 2025
4dcae56
REVERTME [coverage] enable for pull request for testing
pcanal Apr 22, 2025
ee5040f
REVERTME [coverage] Run also on v6-36-00-patches pull requests
pcanal Apr 23, 2025
c025fff
REVERTME [coverage] Cache the coverage build for testing
pcanal Apr 22, 2025
703ff2f
REVERT we have an artifact already
pcanal Apr 23, 2025
6cd902c
REVERTME: force generation of artifact
pcanal Apr 25, 2025
24f0f95
Revert "REVERTME: force generation of artifact"
pcanal Apr 30, 2025
cb3d172
REVERTME: Force reconfiguration in CI
pcanal Apr 29, 2025
28c3acb
REVERTME: Skip the build for now
pcanal Apr 30, 2025
fe3686b
REVERTME [coverage] disable most builds for testing
pcanal Apr 22, 2025
f3bea81
[test] Dont rebuild library within test
pcanal May 15, 2025
47a476e
[coverage] Exclude test from coverage run.
pcanal May 15, 2025
4d8863f
[coverage] Exclude test from coverage run.
pcanal May 15, 2025
d87b559
[coverage] Extract part of the (long) gcovr command line
pcanal May 16, 2025
92818fd
[coverage] Ignore missing source file (eg. ACLiC)
pcanal May 15, 2025
642fad6
[coverage] Extract from gcovr command line dict related opt
pcanal May 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions .github/workflows/root-ci-config/build_root.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ def main():
platform_machine = platform.machine()

obj_prefix = f'{args.platform}/{macos_version_prefix}{args.base_ref}/{args.buildtype}_{platform_machine}/{options_hash}'
if args.coverage:
obj_prefix = obj_prefix + "-coverage"

# Make testing of CI in forks not impact artifacts
if 'root-project/root' not in args.repository:
Expand Down Expand Up @@ -132,8 +134,12 @@ def main():
# "official" branches (master, v?-??-??-patches), i.e. not for pull_request
# We also want to upload any successful build, even if it fails testing
# later on.
if not pull_request and not args.incremental and not args.coverage:
if not pull_request and not args.incremental:
archive_and_upload(yyyy_mm_dd, obj_prefix)
#if args.coverage: # for now, force it.
# if we were to actually upload the artefact we probably need to exclude all
# coverage run-time files ('*.gcda' and `*.gcov`)
# archive_and_upload(yyyy_mm_dd, obj_prefix)

if args.binaries:
create_binaries(args.buildtype)
Expand Down Expand Up @@ -394,14 +400,14 @@ def build(options, buildtype):
if result != 0:
die(result, "Failed to create build directory")

if not os.path.exists(os.path.join(WORKDIR, "build", "CMakeCache.txt")):
if True: # or not os.path.exists(os.path.join(WORKDIR, "build", "CMakeCache.txt")):
cmake_configure(options, buildtype)
else:
cmake_dump_config()

dump_requested_config(options)

cmake_build(buildtype)
# cmake_build(buildtype)


@github_log_group("Create binary packages")
Expand Down Expand Up @@ -499,9 +505,15 @@ def get_base_head_sha(directory: str, repository: str, merge_sha: str, head_sha:
@github_log_group("Create Test Coverage in XML")
def create_coverage_xml() -> None:
builddir = os.path.join(WORKDIR, "build")
ignore_directories="runtutorials|interpreter|.*-prefix|bindings/pyroot/cppyy"
ignore_subpattern="runtutorials|externals|ginclude|googletest-prefix|macosx|winnt|geombuilder|cocoa|quartz|win32gdk|x11|x11ttf|eve|fitpanel|ged|gui|guibuilder|guihtml|qtgsi|qtroot|recorder|sessionviewer|tmvagui|treeviewer|geocad|fitsio|gviz|qt|gviz3d|x3d|spectrum|spectrumpainter|dcache|hdfs|foam|genetic|mlp|quadp|splot|memstat|rpdutils|proof|odbc|llvm|test|interpreter"
ignore_errors="--gcov-ignore-errors=source_not_found --gcov-ignore-errors=no_working_dir_found"
exclude_dictionaries="--exclude='.*/G__.*' --gcov-exclude='.*_ACLiC_dict[.].*' '--exclude=.*_ACLiC_dict[.].*'"
# The output of -v is huge (several 10s of MB at least), we could filter
# the output of -v to keep just the line with ` Processing file:`
result = subprocess_with_log(f"""
cd '{builddir}'
gcovr --output=cobertura-cov.xml --cobertura-pretty --gcov-ignore-errors=no_working_dir_found --merge-mode-functions=merge-use-line-min --exclude-unreachable-branches --exclude-directories="runtutorials|interpreter" --exclude='.*/G__.*' --exclude='.*/(runtutorials|externals|ginclude|googletest-prefix|macosx|winnt|geombuilder|cocoa|quartz|win32gdk|x11|x11ttf|eve|fitpanel|ged|gui|guibuilder|guihtml|qtgsi|qtroot|recorder|sessionviewer|tmvagui|treeviewer|geocad|fitsio|gviz|qt|gviz3d|x3d|spectrum|spectrumpainter|dcache|hdfs|foam|genetic|mlp|quadp|splot|memstat|rpdutils|proof|odbc|llvm|test|interpreter)/.*' --gcov-exclude='.*_ACLiC_dict[.].*' '--exclude=.*_ACLiC_dict[.].*' -v -r ../src ../build
gcovr -j {os.cpu_count()} --output=cobertura-cov.xml --cobertura-pretty {ignore_errors} --merge-mode-functions=merge-use-line-min --exclude-unreachable-branches --exclude-directories="{ignore_directories}" --exclude='.*/({ignore_subpattern})/.*' {exclude_dictionaries} -r ../src ../build
""")

if result != 0:
Expand Down
98 changes: 49 additions & 49 deletions .github/workflows/root-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -96,19 +96,19 @@ jobs:
# Common configs: {Release,Debug,RelWithDebInfo)
# Build options: https://root.cern/install/build_from_source/#all-build-options
include:
- platform: mac13
arch: ARM64
overrides: ["builtin_zlib=ON"]
- platform: mac14
arch: X64
overrides: ["CMAKE_CXX_STANDARD=20"]
- platform: mac15
arch: ARM64
overrides: ["CMAKE_CXX_STANDARD=23"]
- platform: mac-beta
is_special: true
arch: ARM64
overrides: ["CMAKE_CXX_STANDARD=23"]
# - platform: mac13
# arch: ARM64
# overrides: ["builtin_zlib=ON"]
# - platform: mac14
# arch: X64
# overrides: ["CMAKE_CXX_STANDARD=20"]
# - platform: mac15
# arch: ARM64
# overrides: ["CMAKE_CXX_STANDARD=23"]
# - platform: mac-beta
# is_special: true
# arch: ARM64
# overrides: ["CMAKE_CXX_STANDARD=23"]

runs-on: # Using '[self-hosted, ..., ...]' does not work for some reason :)
- self-hosted
Expand Down Expand Up @@ -240,14 +240,14 @@ jobs:
# for pull requests and on branch pushes. This is further complicated
# by the fact that event_name is a string, but we need an array. So
# we construct a JSON string that we can then convert into an array.
event_name: ${{ fromJSON(format('["{0}"]', github.event_name)) }}
config: ["RelWithDebInfo", "Release"]
target_arch: [x64, x86]
exclude:
- event_name: pull_request
config: RelWithDebInfo
- event_name: push
config: RelWithDebInfo
# event_name: ${{ fromJSON(format('["{0}"]', github.event_name)) }}
# config: ["RelWithDebInfo", "Release"]
# target_arch: [x64, x86]
# exclude:
# - event_name: pull_request
# config: RelWithDebInfo
# - event_name: push
# config: RelWithDebInfo
# This is this platform is subject to timeouts when building from
# scratch.
#- target_arch: x86
Expand Down Expand Up @@ -361,40 +361,40 @@ jobs:
# Common configs: {Release,Debug,RelWithDebInfo)
# Build options: https://root.cern/install/build_from_source/#all-build-options
include:
- image: fedora41
- image: fedora42
overrides: ["CMAKE_CXX_STANDARD=23"]
- image: alma8
- image: alma9
overrides: ["CMAKE_BUILD_TYPE=Debug"]
- image: ubuntu22
overrides: ["imt=Off", "CMAKE_BUILD_TYPE=Debug"]
# - image: fedora41
# - image: fedora42
# overrides: ["CMAKE_CXX_STANDARD=23"]
# - image: alma8
# - image: alma9
# overrides: ["CMAKE_BUILD_TYPE=Debug"]
# - image: ubuntu22
# overrides: ["imt=Off", "CMAKE_BUILD_TYPE=Debug"]
- image: ubuntu2404
overrides: ["CMAKE_BUILD_TYPE=Debug"]
- image: ubuntu2504
overrides: ["CMAKE_CXX_STANDARD=23"]
- image: debian125
overrides: ["CMAKE_CXX_STANDARD=20", "dev=ON"]
# Special builds
- image: alma9
is_special: true
property: modules_off
overrides: ["runtime_cxxmodules=Off"]
# - image: ubuntu2504
# overrides: ["CMAKE_CXX_STANDARD=23"]
# - image: debian125
# overrides: ["CMAKE_CXX_STANDARD=20", "dev=ON"]
# # Special builds
# - image: alma9
# is_special: true
# property: modules_off
# overrides: ["runtime_cxxmodules=Off"]
- image: alma9
is_special: true
property: march_native
overrides: ["CMAKE_BUILD_TYPE=RelWithDebInfo", "CMAKE_CXX_FLAGS=-march=native", "CMAKE_C_FLAGS=-march=native", "fortran=OFF"]
- image: alma9
is_special: true
property: arm64
overrides: ["CMAKE_BUILD_TYPE=RelWithDebInfo"]
architecture: ARM64
- image: alma9-clang
is_special: true
property: clang
overrides: ["CMAKE_C_COMPILER=clang", "CMAKE_CXX_COMPILER=clang++"]
- image: alma10
is_special: true
# - image: alma9
# is_special: true
# property: arm64
# overrides: ["CMAKE_BUILD_TYPE=RelWithDebInfo"]
# architecture: ARM64
# - image: alma9-clang
# is_special: true
# property: clang
# overrides: ["CMAKE_C_COMPILER=clang", "CMAKE_CXX_COMPILER=clang++"]
# - image: alma10
# is_special: true
# Disable GPU builds until the DNS problem is solved
# - image: ubuntu2404-cuda
# is_special: true
Expand Down
75 changes: 55 additions & 20 deletions .github/workflows/test-coverage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ on:

# https://github.com/root-project/root/pull/12112#issuecomment-1411004278
# DISABLED: takes 4 hours! Might clang-coverage be a solution?
#pull_request:
# branches:
# - 'master'
# paths-ignore:
# - 'doc/**'
# - 'documentation/**'
pull_request:
branches:
- 'master'
- 'v6-36-00-patches'
paths-ignore:
- 'doc/**'
- 'documentation/**'

workflow_call:
inputs:
Expand All @@ -24,6 +25,9 @@ on:
type: string
required: true
default: master
ref_name:
type: string
default: master

# Enables manual start of workflow
workflow_dispatch:
Expand Down Expand Up @@ -58,27 +62,53 @@ jobs:

name: Build and test to determine coverage

env:
PYTHONUNBUFFERED: true
OS_APPLICATION_CREDENTIAL_ID: '7f5b64a265244623a3a933308569bdba'
OS_APPLICATION_CREDENTIAL_SECRET: ${{ secrets.OS_APPLICATION_CREDENTIAL_SECRET }}
OS_AUTH_TYPE: 'v3applicationcredential'
OS_AUTH_URL: 'https://keystone.cern.ch/v3'
OS_IDENTITY_API_VERSION: 3
OS_INTERFACE: 'public'
OS_REGION_NAME: 'cern'
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

container:
image: registry.cern.ch/root-ci/fedora38:buildready
image: registry.cern.ch/root-ci/alma9:buildready
options: '--security-opt label=disable --rm'
env:
OS_APPLICATION_CREDENTIAL_ID: '7f5b64a265244623a3a933308569bdba'
PYTHONUNBUFFERED: true

steps:
- name: Set up Python Virtual Env
# if the `if` expr is false, `if` still has exit code 0.
# if the `if` block is entered, the block's exit code becomes the exit
# code of the `if`.
run: 'if [ -d /py-venv/ROOT-CI/bin/ ]; then . /py-venv/ROOT-CI/bin/activate && echo PATH=$PATH >> $GITHUB_ENV; fi'

# This should be part of the container image
- name: Install cov packages
run: |
sudo dnf -y update
sudo dnf -y install lcov
dnf -y update
dnf -y install lcov
pip3 install gcovr

# This checks out the merge commit if this is a PR
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{ inputs.ref_name }}

- name: Dump GitHub context
env:
GITHUB_CONTEXT: ${{ toJSON(github) }}
run: echo "$GITHUB_CONTEXT"
JOB_CONTEXT: ${{ toJSON(job) }}
ENV_CONTEXT: ${{ toJSON(env) }}
run: |
echo "$GITHUB_CONTEXT"
echo "--------------------------"
echo "$JOB_CONTEXT"
echo "--------------------------"
echo "$ENV_CONTEXT"

- name: Print debug info
run: 'printf "%s@%s\\n" "$(whoami)" "$(hostname)";
Expand All @@ -87,8 +117,8 @@ jobs:

- name: Apply option override from matrix for this job
env:
OVERRIDE: "coverage=On"
FILE: .github/workflows/root-ci-config/buildconfig/fedora38.txt
OVERRIDE: "coverage=ON"
FILE: .github/workflows/root-ci-config/buildconfig/alma9.txt
shell: bash
run: |
set -x
Expand All @@ -103,40 +133,45 @@ jobs:
GITHUB_PR_ORIGIN: ${{ github.event.pull_request.head.repo.clone_url }}
run: ".github/workflows/root-ci-config/build_root.py
--buildtype Debug
--platform fedora38
--incremental false
--platform alma9
--incremental true
--coverage true
--base_ref ${{ github.base_ref }}
--sha ${{ github.sha }}
--head_ref refs/pull/${{ github.event.pull_request.number }}/head:${{ github.event.pull_request.head.ref }}
--head_sha ${{ github.event.pull_request.head.sha }}
--repository ${{ github.server_url }}/${{ github.repository }}
"

- name: Workflow dispatch
if: github.event_name == 'workflow_dispatch'
run: ".github/workflows/root-ci-config/build_root.py
--buildtype Debug
--platform fedora38
--platform alma9
--incremental false
--coverage true
--base_ref ${{ inputs.base_ref }}
--sha ${{ github.sha }}
--head_ref ${{ inputs.head_ref }}
--head_sha ${{ inputs.head_ref }}
--repository ${{ github.server_url }}/${{ github.repository }}
"

- name: Nightly build
if: github.event_name == 'schedule'
run: ".github/workflows/root-ci-config/build_root.py
--buildtype Debug
--platform fedora38
--platform alma9
--incremental false
--coverage true
--base_ref ${{ github.ref_name }}
--sha ${{ github.sha }}
--repository ${{ github.server_url }}/${{ github.repository }}
"

- name: Upload coverage to Codecov
if: ${{ !cancelled() }}
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v5
with:
env_vars: OS,PYTHON
fail_ci_if_error: true
Expand Down
2 changes: 1 addition & 1 deletion roottest/cling/functionTemplate/testcint.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from __future__ import print_function
import ROOT
from sys import stdout

Check failure on line 3 in roottest/cling/functionTemplate/testcint.py

View workflow job for this annotation

GitHub Actions / ruff

Ruff (I001)

roottest/cling/functionTemplate/testcint.py:1:1: I001 Import block is un-sorted or un-formatted

def printme(o):
print("t now %g %d %d" % (o.get["double"](), o.get["int"](), o.get["float"]()))
stdout.flush()

ROOT.gROOT.ProcessLine(".L t.h++")
ROOT.gROOT.ProcessLine(".L t.h+")
sortedMethods = [ item for item in ROOT.t.__dict__.keys() if item[0:2] != '__' ]
sortedMethods.sort()
print("# just a comment")
Expand Down
10 changes: 6 additions & 4 deletions roottest/root/aclic/load/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ ROOTTEST_ADD_TEST(autoload
OUTREF execautoload.ref
DEPENDS autoloadtest.C)

ROOTTEST_ADD_TEST(reload
COPY_TO_BUILDDIR Reload.root
MACRO assertReload.C
OUTREF assertReload.ref)
if(NOT coverage)
ROOTTEST_ADD_TEST(reload
COPY_TO_BUILDDIR Reload.root
MACRO assertReload.C
OUTREF assertReload.ref)
endif()

ROOTTEST_ADD_TEST(linktest
MACRO execlinktest.C
Expand Down
10 changes: 6 additions & 4 deletions roottest/root/meta/tclass/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,12 @@ ROOTTEST_ADD_TEST(execInitOrder
OUTREF execInitOrder.ref
DEPENDS libInitOrder-build libInitOrderDups-build)

ROOTTEST_ADD_TEST(tclassStl
MACRO tclassStl.cxx+
OUTREF tclassStl.ref
RUN_SERIAL)
if(NOT coverage)
ROOTTEST_ADD_TEST(tclassStl
MACRO tclassStl.cxx+
OUTREF tclassStl.ref
RUN_SERIAL)
endif()

ROOTTEST_ADD_TEST(TClassAtTearDown
MACRO execTClassAtTearDown.C
Expand Down
Loading