Skip to content

Fix use of async_mutex guard to avoid coroutine RAII bug on GCC 15, r… #41

Fix use of async_mutex guard to avoid coroutine RAII bug on GCC 15, r…

Fix use of async_mutex guard to avoid coroutine RAII bug on GCC 15, r… #41

Workflow file for this run

#
# Copyright (c) 2026 Sam Darwin
# Copyright (c) 2026 Michael Vandeberg
# Copyright (c) 2026 Alexander Grund
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
# Official repository: https://github.com/cppalliance/corosio/
#
# Instructions
#
# After running this workflow successfully, go to https://github.com/cppalliance/corosio/settings/pages
# and enable github pages on the code-coverage branch.
# The coverage will be hosted at https://cppalliance.org/corosio
#
name: Code Coverage
on:
push:
branches:
- master
- develop
paths:
- 'src/**'
- 'include/**'
- '.github/workflows/code-coverage.yml'
workflow_dispatch:
concurrency:
group: code-coverage-pages
cancel-in-progress: false
env:
GIT_FETCH_JOBS: 8
NET_RETRY_COUNT: 5
GCOVR_COMMIT_MSG: "Update coverage data"
BOOST_BRANCH_COVERAGE: 0
EXTRA_BOOST_LIBRARIES: "cppalliance/buffers cppalliance/capy cppalliance/http"
jobs:
build-linux:
defaults:
run:
shell: bash
name: Coverage (Linux)
runs-on: ubuntu-24.04
timeout-minutes: 120
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Install Python
uses: actions/setup-python@v6
with:
python-version: '3.13'
- name: Install Python packages
run: pip install gcovr
- name: Checkout ci-automation
uses: actions/checkout@v6
with:
repository: cppalliance/ci-automation
path: ci-automation
- name: Build and run tests & collect coverage data
run: |
set -xe
ls -al
export ORGANIZATION=${GITHUB_REPOSITORY_OWNER}
export REPONAME=$(basename ${GITHUB_REPOSITORY})
export B2_CXXSTD=20
./ci-automation/scripts/lcov-jenkins-gcc-13.sh --only-gcovr
- name: Generate badges
run: python3 ci-automation/scripts/generate_badges.py gcovr
- name: Upload coverage artifact
uses: actions/upload-artifact@v4
with:
name: coverage-linux
path: gcovr/
build-macos:
defaults:
run:
shell: bash
name: Coverage (macOS)
runs-on: macos-15
timeout-minutes: 120
steps:
- name: Clone Boost.Corosio
uses: actions/checkout@v6
with:
path: corosio-root
- name: Setup C++
uses: alandefreitas/cpp-actions/setup-cpp@v1.9.0
id: setup-cpp
with:
compiler: apple-clang
version: '*'
check-latest: true
- name: Create vcpkg.json (macOS)
run: |
cat > corosio-root/vcpkg.json << 'EOF'
{
"name": "boost-corosio-deps",
"version": "1.0.0",
"dependencies": ["wolfssl"]
}
EOF
- name: Setup vcpkg
uses: lukka/run-vcpkg@v11
with:
vcpkgDirectory: ${{ github.workspace }}/vcpkg
vcpkgGitCommitId: bd52fac7114fdaa2208de8dd1227212a6683e562
vcpkgJsonGlob: '**/corosio-root/vcpkg.json'
runVcpkgInstall: true
- name: Set vcpkg paths (macOS)
run: |
set -xe
if [[ "$(uname -m)" == "arm64" ]]; then
triplet="arm64-osx"
else
triplet="x64-osx"
fi
echo "Using triplet: ${triplet}"
vcpkg_installed=$(find "${{ github.workspace }}" -type d -name "${triplet}" -path "*/vcpkg_installed/*" | head -1)
if [ -z "$vcpkg_installed" ]; then
echo "ERROR: Could not find vcpkg_installed directory for triplet ${triplet}"
find "${{ github.workspace }}" -type d -name "vcpkg_installed" 2>/dev/null || true
exit 1
fi
echo "vcpkg_installed=${vcpkg_installed}"
echo "CMAKE_WOLFSSL_INCLUDE=${vcpkg_installed}/include" >> $GITHUB_ENV
echo "CMAKE_WOLFSSL_LIBRARY=${vcpkg_installed}/lib/libwolfssl.a" >> $GITHUB_ENV
- name: Clone Capy
uses: actions/checkout@v6
with:
repository: cppalliance/capy
ref: ${{ (github.ref_name == 'master' && github.ref_name) || 'develop' }}
path: capy-root
- name: Clone Boost
uses: alandefreitas/cpp-actions/boost-clone@v1.9.0
id: boost-clone
with:
branch: ${{ (github.ref_name == 'master' && github.ref_name) || 'develop' }}
boost-dir: boost-source
modules-exclude-paths: ''
scan-modules-dir: corosio-root
scan-modules-ignore: corosio,capy
- name: Patch Boost
id: patch
run: |
set -xe
module=${GITHUB_REPOSITORY#*/}
echo "module=$module" >> $GITHUB_OUTPUT
workspace_root=$(echo "$GITHUB_WORKSPACE" | sed 's/\\/\//g')
echo -E "workspace_root=$workspace_root" >> $GITHUB_OUTPUT
rm -r "boost-source/libs/$module" || true
rm -r "boost-source/libs/capy" || true
cd boost-source
if git sparse-checkout list > /dev/null 2>&1; then
echo "Disabling sparse checkout..."
git sparse-checkout disable
echo "Fetching any missing objects..."
git fetch origin --no-tags
git checkout
fi
cd ..
cp -rL boost-source boost-root
cd boost-root
boost_root="$(pwd)"
boost_root=$(echo "$boost_root" | sed 's/\\/\//g')
echo -E "boost_root=$boost_root" >> $GITHUB_OUTPUT
cp -r "$workspace_root"/corosio-root "libs/$module"
cp -r "$workspace_root"/capy-root "libs/capy"
- name: Build with coverage
uses: alandefreitas/cpp-actions/cmake-workflow@v1.9.0
with:
source-dir: boost-root
build-dir: __build_cmake_test__
build-type: Debug
build-target: tests
run-tests: true
install-prefix: .local
cxxstd: '20'
cc: ${{ steps.setup-cpp.outputs.cc || 'clang' }}
cxx: ${{ steps.setup-cpp.outputs.cxx || 'clang++' }}
cxxflags: '--coverage'
ccflags: '--coverage'
shared: false
cmake-version: '>=3.20'
extra-args: |
-D Boost_VERBOSE=ON
-D BOOST_INCLUDE_LIBRARIES="${{ steps.patch.outputs.module }}"
-D CMAKE_EXPORT_COMPILE_COMMANDS=ON
${{ env.CMAKE_WOLFSSL_INCLUDE && format('-D WolfSSL_INCLUDE_Dir={0}', env.CMAKE_WOLFSSL_INCLUDE) || '' }}
${{ env.CMAKE_WOLFSSL_LIBRARY && format('-D WolfSSL_LIBRARY={0}', env.CMAKE_WOLFSSL_LIBRARY) || '' }}
package: false
package-artifact: false
ref-source-dir: boost-root/libs/corosio
- name: Install Python
uses: actions/setup-python@v6
with:
python-version: '3.13'
- name: Install Python packages
run: pip install gcovr
- name: Checkout ci-automation
uses: actions/checkout@v6
with:
repository: cppalliance/ci-automation
path: ci-automation
- name: Generate gcovr report
run: |
set -xe
module=$(basename ${GITHUB_REPOSITORY})
mkdir -p gcovr
# First pass: collect raw coverage data into JSON
gcovr \
--root boost-root \
--gcov-executable "xcrun llvm-cov gcov" \
--merge-mode-functions separate \
--sort uncovered-percent \
--html-title "${module}" \
--merge-lines \
--exclude-unreachable-branches \
--exclude-throw-branches \
--exclude '.*/extra/.*' \
--exclude '.*/example/.*' \
--exclude '.*/examples/.*' \
--filter ".*/${module}/.*" \
--html --output gcovr/index.html \
--json-summary-pretty --json-summary gcovr/summary.json \
--json gcovr/coverage-raw.json \
boost-root/__build_cmake_test__
# Fix paths for repo-relative display
python3 ci-automation/scripts/fix_paths.py \
gcovr/coverage-raw.json \
gcovr/coverage-fixed.json \
--repo "${module}"
# Create symlinks so gcovr can find source files at repo-relative paths
ln -sfn "boost-root/libs/${module}/include" include 2>/dev/null || true
ln -sfn "boost-root/libs/${module}/src" src 2>/dev/null || true
# Second pass: generate nested HTML from fixed JSON with custom templates
gcovr \
-a gcovr/coverage-fixed.json \
--merge-mode-functions separate \
--sort uncovered-percent \
--html-nested \
--html-template-dir=ci-automation/gcovr-templates/html \
--html-title "${module}" \
--merge-lines \
--exclude-unreachable-branches \
--exclude-throw-branches \
--exclude '(^|.*/)test/.*' \
--exclude '.*/extra/.*' \
--exclude '.*/example/.*' \
--exclude '.*/examples/.*' \
--html --output gcovr/index.html \
--json-summary-pretty --json-summary gcovr/summary.json
- name: Generate sidebar navigation
run: python3 ci-automation/scripts/gcovr_build_tree.py gcovr
- name: Generate badges
run: python3 ci-automation/scripts/generate_badges.py gcovr --json gcovr/summary.json
- name: Upload coverage artifact
uses: actions/upload-artifact@v4
with:
name: coverage-macos
path: gcovr/
build-windows:
defaults:
run:
shell: bash
name: Coverage (Windows)
runs-on: windows-2022
timeout-minutes: 120
steps:
- name: Clone Boost.Corosio
uses: actions/checkout@v6
with:
path: corosio-root
- name: Setup C++
uses: alandefreitas/cpp-actions/setup-cpp@v1.9.0
id: setup-cpp
with:
compiler: mingw
version: '*'
check-latest: true
- name: Install OpenSSL (MinGW)
run: |
C:/msys64/usr/bin/pacman.exe -S --noconfirm mingw-w64-x86_64-openssl
echo "C:/msys64/mingw64/bin" >> $GITHUB_PATH
- name: Create vcpkg.json
run: |
cat > corosio-root/vcpkg.json << 'EOF'
{
"name": "boost-corosio-deps",
"version": "1.0.0",
"dependencies": [
{ "name": "wolfssl", "default-features": false }
]
}
EOF
- name: Setup vcpkg
uses: lukka/run-vcpkg@v11
env:
VCPKG_DEFAULT_TRIPLET: x64-mingw-static
with:
vcpkgDirectory: ${{ github.workspace }}/vcpkg
vcpkgGitCommitId: bd52fac7114fdaa2208de8dd1227212a6683e562
vcpkgJsonGlob: '**/corosio-root/vcpkg.json'
runVcpkgInstall: true
- name: Set vcpkg paths (Windows MinGW)
run: |
set -xe
triplet="x64-mingw-static"
vcpkg_installed=$(find "${{ github.workspace }}" -type d -name "${triplet}" -path "*/vcpkg_installed/*" | head -1)
if [ -z "$vcpkg_installed" ]; then
echo "ERROR: Could not find vcpkg_installed directory for triplet ${triplet}"
find "${{ github.workspace }}" -type d -name "vcpkg_installed" 2>/dev/null || true
exit 1
fi
echo "vcpkg_installed=${vcpkg_installed}"
echo "CMAKE_WOLFSSL_INCLUDE=${vcpkg_installed}/include" >> $GITHUB_ENV
echo "CMAKE_WOLFSSL_LIBRARY=${vcpkg_installed}/lib/libwolfssl.a" >> $GITHUB_ENV
echo "CMAKE_OPENSSL_ROOT=C:/msys64/mingw64" >> $GITHUB_ENV
- name: Clone Capy
uses: actions/checkout@v6
with:
repository: cppalliance/capy
ref: ${{ (github.ref_name == 'master' && github.ref_name) || 'develop' }}
path: capy-root
- name: Clone Boost
uses: alandefreitas/cpp-actions/boost-clone@v1.9.0
id: boost-clone
with:
branch: ${{ (github.ref_name == 'master' && github.ref_name) || 'develop' }}
boost-dir: boost-source
modules-exclude-paths: ''
scan-modules-dir: corosio-root
scan-modules-ignore: corosio,capy
- name: Patch Boost
id: patch
run: |
set -xe
module=${GITHUB_REPOSITORY#*/}
echo "module=$module" >> $GITHUB_OUTPUT
workspace_root=$(echo "$GITHUB_WORKSPACE" | sed 's/\\/\//g')
echo -E "workspace_root=$workspace_root" >> $GITHUB_OUTPUT
rm -r "boost-source/libs/$module" || true
rm -r "boost-source/libs/capy" || true
cd boost-source
if git sparse-checkout list > /dev/null 2>&1; then
echo "Disabling sparse checkout..."
git sparse-checkout disable
echo "Fetching any missing objects..."
git fetch origin --no-tags
git checkout
fi
cd ..
cp -rL boost-source boost-root
cd boost-root
boost_root="$(pwd)"
boost_root=$(echo "$boost_root" | sed 's/\\/\//g')
echo -E "boost_root=$boost_root" >> $GITHUB_OUTPUT
cp -r "$workspace_root"/corosio-root "libs/$module"
cp -r "$workspace_root"/capy-root "libs/capy"
- name: Build with coverage
uses: alandefreitas/cpp-actions/cmake-workflow@v1.9.0
with:
source-dir: boost-root
build-dir: __build_cmake_test__
generator: 'MinGW Makefiles'
build-type: Debug
build-target: tests
run-tests: true
install-prefix: .local
cxxstd: '20'
cc: ${{ steps.setup-cpp.outputs.cc || 'gcc' }}
cxx: ${{ steps.setup-cpp.outputs.cxx || 'g++' }}
cxxflags: '--coverage -fprofile-arcs -ftest-coverage -fprofile-update=atomic'
ccflags: '--coverage -fprofile-arcs -ftest-coverage -fprofile-update=atomic'
shared: false
cmake-version: '>=3.20'
extra-args: |
-D Boost_VERBOSE=ON
-D BOOST_INCLUDE_LIBRARIES="${{ steps.patch.outputs.module }}"
-D CMAKE_EXPORT_COMPILE_COMMANDS=ON
${{ env.CMAKE_WOLFSSL_INCLUDE && format('-D WolfSSL_INCLUDE_Dir={0}', env.CMAKE_WOLFSSL_INCLUDE) || '' }}
${{ env.CMAKE_WOLFSSL_LIBRARY && format('-D WolfSSL_LIBRARY={0}', env.CMAKE_WOLFSSL_LIBRARY) || '' }}
${{ env.CMAKE_OPENSSL_ROOT && format('-D OPENSSL_ROOT_DIR={0}', env.CMAKE_OPENSSL_ROOT) || '' }}
package: false
package-artifact: false
ref-source-dir: boost-root/libs/corosio
- name: Install Python
uses: actions/setup-python@v6
with:
python-version: '3.13'
- name: Install Python packages
run: pip install gcovr
- name: Checkout ci-automation
uses: actions/checkout@v6
with:
repository: cppalliance/ci-automation
path: ci-automation
- name: Generate gcovr report
env:
PYTHONUTF8: 1
run: |
set -xe
module=$(basename ${GITHUB_REPOSITORY})
mkdir -p gcovr
# First pass: collect raw coverage data into JSON
gcovr \
--root boost-root \
--merge-mode-functions separate \
--sort uncovered-percent \
--html-title "${module}" \
--merge-lines \
--exclude-unreachable-branches \
--exclude-throw-branches \
--exclude '.*/extra/.*' \
--exclude '.*/example/.*' \
--exclude '.*/examples/.*' \
--filter ".*/${module}/.*" \
--html --output gcovr/index.html \
--json-summary-pretty --json-summary gcovr/summary.json \
--json gcovr/coverage-raw.json \
boost-root/__build_cmake_test__
# Fix paths for repo-relative display
python3 ci-automation/scripts/fix_paths.py \
gcovr/coverage-raw.json \
gcovr/coverage-fixed.json \
--repo "${module}"
# Create symlinks so gcovr can find source files at repo-relative paths
ln -sfn "boost-root/libs/${module}/include" include 2>/dev/null || true
ln -sfn "boost-root/libs/${module}/src" src 2>/dev/null || true
# Second pass: generate nested HTML from fixed JSON with custom templates
gcovr \
-a gcovr/coverage-fixed.json \
--merge-mode-functions separate \
--sort uncovered-percent \
--html-nested \
--html-template-dir=ci-automation/gcovr-templates/html \
--html-title "${module}" \
--merge-lines \
--exclude-unreachable-branches \
--exclude-throw-branches \
--exclude '(^|.*/)test/.*' \
--exclude '.*/extra/.*' \
--exclude '.*/example/.*' \
--exclude '.*/examples/.*' \
--html --output gcovr/index.html \
--json-summary-pretty --json-summary gcovr/summary.json
- name: Generate sidebar navigation
run: python3 ci-automation/scripts/gcovr_build_tree.py gcovr
- name: Generate badges
run: python3 ci-automation/scripts/generate_badges.py gcovr --json gcovr/summary.json
- name: Upload coverage artifact
uses: actions/upload-artifact@v4
with:
name: coverage-windows
path: gcovr/
deploy:
needs: [build-linux, build-macos, build-windows]
if: ${{ !cancelled() }}
defaults:
run:
shell: bash
name: Deploy Coverage
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- name: Checkout code
uses: actions/checkout@v6
- name: Check for code-coverage Branch
run: |
set -xe
git config --global user.name cppalliance-bot
git config --global user.email cppalliance-bot@example.com
git fetch origin
if git branch -r | grep origin/code-coverage; then
echo "The code-coverage branch exists. Continuing."
else
echo "The code-coverage branch does not exist. Creating it."
git switch --orphan code-coverage
git commit --allow-empty -m "$GCOVR_COMMIT_MSG"
git push origin code-coverage
git checkout $GITHUB_REF_NAME
fi
- name: Checkout GitHub pages branch
uses: actions/checkout@v6
with:
ref: code-coverage
path: gh_pages_dir
- name: Download coverage artifacts
uses: actions/download-artifact@v4
with:
pattern: coverage-*
path: coverage-artifacts/
- name: Copy coverage results
run: |
set -xe
touch gh_pages_dir/.nojekyll
mkdir -p "gh_pages_dir/develop"
mkdir -p "gh_pages_dir/master"
# Remove old single-platform directory (migration from gcovr/ to gcovr-linux/)
rm -rf "gh_pages_dir/${GITHUB_REF_NAME}/gcovr"
# Copy each platform's results (only if artifact exists)
for platform in linux macos windows; do
if [ -d "coverage-artifacts/coverage-${platform}" ]; then
rm -rf "gh_pages_dir/${GITHUB_REF_NAME}/gcovr-${platform}"
cp -rp "coverage-artifacts/coverage-${platform}" \
"gh_pages_dir/${GITHUB_REF_NAME}/gcovr-${platform}"
fi
done
# Generate branch index pages
for branch in develop master; do
cat > "gh_pages_dir/${branch}/index.html" << 'HTMLEOF'
<html>
<head><title>Code Coverage</title></head>
<body>
<h2>Code Coverage Reports</h2>
<ul>
<li><a href="gcovr-linux/index.html">Linux (epoll)</a></li>
<li><a href="gcovr-macos/index.html">macOS (kqueue)</a></li>
<li><a href="gcovr-windows/index.html">Windows (IOCP)</a></li>
</ul>
</body>
</html>
HTMLEOF
done
# Root index
cat > gh_pages_dir/index.html << 'HTMLEOF'
<html>
<head></head>
<body>
<a href="develop/index.html">develop</a><br>
<a href="master/index.html">master</a><br>
</body>
</html>
HTMLEOF
cd gh_pages_dir
git add .
git commit --amend -m "$GCOVR_COMMIT_MSG"
git push -f origin code-coverage