Merge pull request #299 from gregmedd/merge-release-to-main #12
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: CI | |
on: | |
push: | |
branches: [ "main", "v1.0_up-v1.6.0" ] | |
pull_request: | |
branches: ["**"] | |
permissions: | |
contents: read | |
jobs: | |
build: | |
name: Build up-cpp and dependencies | |
runs-on: ubuntu-latest | |
steps: | |
- name: Install Conan | |
id: conan | |
uses: turtlebrowser/get-conan@main | |
with: | |
version: 2.3.2 | |
- name: Fetch up-cpp | |
uses: actions/checkout@v4 | |
with: | |
path: up-cpp | |
- name: Install conan CI profile | |
shell: bash | |
run: | | |
conan profile detect | |
cp up-cpp/.github/workflows/ci_conan_profile "$(conan profile path default)" | |
conan profile show | |
- name: Fetch up-core-api conan recipe | |
uses: actions/checkout@v4 | |
with: | |
path: up-conan-recipes | |
repository: eclipse-uprotocol/up-conan-recipes | |
- name: Build up-core-api conan package | |
shell: bash | |
run: | | |
conan create --version 1.6.0-alpha3 up-conan-recipes/up-core-api/release | |
- name: Build up-cpp with tests | |
shell: bash | |
run: | | |
cd up-cpp | |
conan install --build=missing . | |
cmake --preset conan-release -DCMAKE_EXPORT_COMPILE_COMMANDS=yes | |
cd build/Release | |
cmake --build . -- -j | |
- name: Save conan cache to archive | |
shell: bash | |
run: | | |
conan cache save --file ./conan-cache.tgz '*' | |
- name: Upload build artifacts | |
uses: actions/upload-artifact@v4 | |
with: | |
name: build-artifacts | |
path: up-cpp/build/Release | |
- name: Upload compile commands | |
uses: actions/upload-artifact@v4 | |
with: | |
name: compile-commands | |
path: up-cpp/build/Release/compile_commands.json | |
- name: Upload conan cache for linting | |
uses: actions/upload-artifact@v4 | |
with: | |
name: conan-cache | |
path: ./conan-cache.tgz | |
test: | |
name: Run up-cpp tests | |
runs-on: ubuntu-latest | |
needs: build | |
steps: | |
- name: Get build artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
name: build-artifacts | |
path: up-cpp/build/Release | |
- name: Run all tests | |
shell: bash | |
run: | | |
cd up-cpp/build/Release | |
chmod +x bin/* | |
ctest | |
- name: Upload test results | |
uses: actions/upload-artifact@v4 | |
if: success() || failure() | |
with: | |
name: test-results | |
path: 'up-cpp/build/Release/test/results/*.xml' | |
# NOTE: Run dynamic analysis in unit tests | |
memcheck: | |
name: Run Valgrind Memcheck | |
runs-on: ubuntu-latest | |
needs: build | |
steps: | |
- name: Get build artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
name: build-artifacts | |
path: up-cpp/build/Release | |
- name: Install Valgrind | |
run: | | |
sudo apt-get update | |
sudo apt-get install -y valgrind | |
- name: Run Valgrind Memcheck | |
continue-on-error: true | |
run: | | |
cd up-cpp/build/Release | |
chmod +x bin/* | |
mkdir -p valgrind_logs | |
: > valgrind_logs/valgrind_memcheck_summary.log | |
declare -A EXCLUDE_TESTS | |
while IFS= read -r line; do | |
test_binary=$(echo $line | cut -d'.' -f1) | |
test_suite=$(echo $line | cut -d'.' -f2) | |
test_name=$(echo $line | cut -d'.' -f3) | |
if [[ -z "${EXCLUDE_TESTS["$test_binary"]}" ]]; then | |
EXCLUDE_TESTS["$test_binary"]="-" | |
else | |
EXCLUDE_TESTS["$test_binary"]+=":" | |
fi | |
EXCLUDE_TESTS["$test_binary"]+="$test_suite.$test_name" | |
done < valgrind_exclude_test_memcheck.txt | |
for test_binary in bin/*Test; do | |
test_binary_name=$(basename $test_binary) | |
echo "Running Valgrind on $test_binary_name" | |
if [[ -n "${EXCLUDE_TESTS[$test_binary_name]}" ]]; then | |
exclude_pattern="${EXCLUDE_TESTS[$test_binary_name]}" | |
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --log-file="valgrind_logs/$test_binary_name.log" ./$test_binary --gtest_filter="$exclude_pattern" || true | |
else | |
valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes --log-file="valgrind_logs/$test_binary_name.log" ./$test_binary || true | |
fi | |
cat "valgrind_logs/$test_binary_name.log" >> valgrind_logs/valgrind_complete_memcheck_log.log | |
if grep -q "ERROR SUMMARY: [^0]" "valgrind_logs/$test_binary_name.log"; then | |
echo "Valgrind errors found in $test_binary_name:" | |
grep -A1 "ERROR SUMMARY:" "valgrind_logs/$test_binary_name.log" >> valgrind_logs/valgrind_memcheck_summary.log | |
echo "Valgrind log for $test_binary_name:" | |
cat "valgrind_logs/$test_binary_name.log" | |
echo "------------------------" | |
fi | |
done | |
echo "Valgrind Memcheck Summary:" | |
cat valgrind_logs/valgrind_memcheck_summary.log | |
- name: Upload Valgrind Memcheck logs | |
uses: actions/upload-artifact@v4 | |
if: success() || failure() | |
with: | |
name: valgrind-memcheck-log | |
path: up-cpp/build/Release/valgrind_logs/valgrind_complete_memcheck_log.log | |
threadcheck: | |
name: Run Valgrind ThreadCheck | |
runs-on: ubuntu-latest | |
needs: build | |
steps: | |
- name: Get build artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
name: build-artifacts | |
path: up-cpp/build/Release | |
- name: Install Valgrind | |
run: | | |
sudo apt-get update | |
sudo apt-get install -y valgrind | |
- name: Run Valgrind ThreadCheck | |
continue-on-error: true | |
run: | | |
cd up-cpp/build/Release | |
chmod +x bin/* | |
mkdir -p valgrind_logs | |
: > valgrind_logs/valgrind_threadcheck_summary.log | |
: > valgrind_logs/valgrind_complete_threadcheck_log.log | |
declare -A EXCLUDE_TESTS | |
while IFS= read -r line; do | |
test_binary=$(echo $line | cut -d'.' -f1) | |
test_suite=$(echo $line | cut -d'.' -f2) | |
test_name=$(echo $line | cut -d'.' -f3) | |
if [[ -z "${EXCLUDE_TESTS["$test_binary"]}" ]]; then | |
EXCLUDE_TESTS["$test_binary"]="-" | |
else | |
EXCLUDE_TESTS["$test_binary"]+=":" | |
fi | |
EXCLUDE_TESTS["$test_binary"]+="$test_suite.$test_name" | |
done < valgrind_exclude_test_threadcheck.txt | |
for test_binary in bin/*Test; do | |
test_binary_name=$(basename $test_binary) | |
echo "Running Valgrind ThreadCheck on $test_binary_name" | |
if [[ -n "${EXCLUDE_TESTS[$test_binary_name]}" ]]; then | |
exclude_pattern="${EXCLUDE_TESTS[$test_binary_name]}" | |
valgrind --tool=drd --log-file="valgrind_logs/$test_binary_name_threadcheck.log" ./$test_binary --gtest_filter="$exclude_pattern" || true | |
else | |
valgrind --tool=drd --log-file="valgrind_logs/$test_binary_name_threadcheck.log" ./$test_binary || true | |
fi | |
cat "valgrind_logs/$test_binary_name_threadcheck.log" >> valgrind_logs/valgrind_complete_threadcheck_log.log | |
if grep -q "ERROR SUMMARY: [^0]" "valgrind_logs/$test_binary_name_threadcheck.log"; then | |
echo "Valgrind ThreadCheck errors found in $test_binary_name:" | |
grep -A1 "ERROR SUMMARY:" "valgrind_logs/$test_binary_name_threadcheck.log" >> valgrind_logs/valgrind_threadcheck_summary.log | |
echo "Valgrind ThreadCheck log for $test_binary_name:" | |
cat "valgrind_logs/$test_binary_name_threadcheck.log" | |
echo "------------------------" | |
fi | |
done | |
echo "Valgrind ThreadCheck Summary:" | |
cat valgrind_logs/valgrind_threadcheck_summary.log | |
- name: Upload Valgrind ThreadCheck logs | |
uses: actions/upload-artifact@v4 | |
if: success() || failure() | |
with: | |
name: valgrind-threadcheck-log | |
path: up-cpp/build/Release/valgrind_logs/valgrind_complete_threadcheck_log.log | |
helgrind: | |
name: Run Valgrind Helgrind | |
runs-on: ubuntu-latest | |
needs: build | |
steps: | |
- name: Get build artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
name: build-artifacts | |
path: up-cpp/build/Release | |
- name: Install Valgrind | |
run: | | |
sudo apt-get update | |
sudo apt-get install -y valgrind | |
- name: Run Valgrind Helgrind | |
continue-on-error: true | |
run: | | |
cd up-cpp/build/Release | |
chmod +x bin/* | |
mkdir -p valgrind_logs | |
: > valgrind_logs/valgrind_helgrind_summary.log | |
: > valgrind_logs/valgrind_complete_helgrind_log.log | |
declare -A EXCLUDE_TESTS | |
while IFS= read -r line; do | |
test_binary=$(echo $line | cut -d'.' -f1) | |
test_suite=$(echo $line | cut -d'.' -f2) | |
test_name=$(echo $line | cut -d'.' -f3) | |
if [[ -z "${EXCLUDE_TESTS["$test_binary"]}" ]]; then | |
EXCLUDE_TESTS["$test_binary"]="-" | |
else | |
EXCLUDE_TESTS["$test_binary"]+=":" | |
fi | |
EXCLUDE_TESTS["$test_binary"]+="$test_suite.$test_name" | |
done < valgrind_exclude_test_helgrind.txt | |
for test_binary in bin/*Test; do | |
test_binary_name=$(basename $test_binary) | |
echo "Running Valgrind Helgrind on $test_binary_name" | |
if [[ -n "${EXCLUDE_TESTS[$test_binary_name]}" ]]; then | |
exclude_pattern="${EXCLUDE_TESTS[$test_binary_name]}" | |
valgrind --tool=helgrind --log-file="valgrind_logs/$test_binary_name_helgrind.log" ./$test_binary --gtest_filter="$exclude_pattern" || true | |
else | |
valgrind --tool=helgrind --log-file="valgrind_logs/$test_binary_name_helgrind.log" ./$test_binary || true | |
fi | |
cat "valgrind_logs/$test_binary_name_helgrind.log" >> valgrind_logs/valgrind_complete_helgrind_log.log | |
if grep -q "ERROR SUMMARY: [^0]" "valgrind_logs/$test_binary_name_helgrind.log"; then | |
echo "Valgrind Helgrind errors found in $test_binary_name:" | |
grep -A1 "ERROR SUMMARY:" "valgrind_logs/$test_binary_name_helgrind.log" >> valgrind_logs/valgrind_helgrind_summary.log | |
echo "Valgrind Helgrind log for $test_binary_name:" | |
cat "valgrind_logs/$test_binary_name_helgrind.log" | |
echo "------------------------" | |
fi | |
done | |
echo "Valgrind Helgrind Summary:" | |
cat valgrind_logs/valgrind_helgrind_summary.log | |
- name: Upload Valgrind Helgrind logs | |
uses: actions/upload-artifact@v4 | |
if: success() || failure() | |
with: | |
name: valgrind-helgrind-log | |
path: up-cpp/build/Release/valgrind_logs/valgrind_complete_helgrind_log.log | |
dhat: | |
name: Run Valgrind DHAT | |
runs-on: ubuntu-latest | |
needs: build | |
steps: | |
- name: Get build artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
name: build-artifacts | |
path: up-cpp/build/Release | |
- name: Install Valgrind | |
run: | | |
sudo apt-get update | |
sudo apt-get install -y valgrind | |
- name: Run Valgrind DHAT | |
continue-on-error: true | |
run: | | |
cd up-cpp/build/Release | |
chmod +x bin/* | |
mkdir -p valgrind_logs | |
: > valgrind_logs/valgrind_dhat_summary.log | |
: > valgrind_logs/valgrind_complete_dhat_log.log | |
declare -A EXCLUDE_TESTS | |
while IFS= read -r line; do | |
test_binary=$(echo $line | cut -d'.' -f1) | |
test_suite=$(echo $line | cut -d'.' -f2) | |
test_name=$(echo $line | cut -d'.' -f3) | |
if [[ -z "${EXCLUDE_TESTS["$test_binary"]}" ]]; then | |
EXCLUDE_TESTS["$test_binary"]="-" | |
else | |
EXCLUDE_TESTS["$test_binary"]+=":" | |
fi | |
EXCLUDE_TESTS["$test_binary"]+="$test_suite.$test_name" | |
done < valgrind_exclude_test_dhat.txt | |
for test_binary in bin/*Test; do | |
test_binary_name=$(basename $test_binary) | |
echo "Running Valgrind DHAT on $test_binary_name" | |
if [[ -n "${EXCLUDE_TESTS[$test_binary_name]}" ]]; then | |
exclude_pattern="${EXCLUDE_TESTS[$test_binary_name]}" | |
valgrind --tool=dhat --log-file="valgrind_logs/$test_binary_name_dhat.log" ./$test_binary --gtest_filter="$exclude_pattern" || true | |
else | |
valgrind --tool=dhat --log-file="valgrind_logs/$test_binary_name_dhat.log" ./$test_binary || true | |
fi | |
cat "valgrind_logs/$test_binary_name_dhat.log" >> valgrind_logs/valgrind_complete_dhat_log.log | |
if grep -q "ERROR SUMMARY: [^0]" "valgrind_logs/$test_binary_name_dhat.log"; then | |
echo "Valgrind DHAT errors found in $test_binary_name:" | |
grep -A1 "ERROR SUMMARY:" "valgrind_logs/$test_binary_name_dhat.log" >> valgrind_logs/valgrind_dhat_summary.log | |
echo "Valgrind DHAT log for $test_binary_name:" | |
cat "valgrind_logs/$test_binary_name_dhat.log" | |
echo "------------------------" | |
fi | |
done | |
echo "Valgrind DHAT Summary:" | |
cat valgrind_logs/valgrind_dhat_summary.log | |
- name: Upload Valgrind DHAT logs | |
uses: actions/upload-artifact@v4 | |
if: success() || failure() | |
with: | |
name: valgrind-dhat-log | |
path: up-cpp/build/Release/valgrind_logs/valgrind_complete_dhat_log.log | |
lint: | |
name: Lint C++ sources | |
runs-on: ubuntu-latest | |
needs: build | |
permissions: | |
contents: write | |
pull-requests: read | |
steps: | |
- name: Get build commands | |
uses: actions/download-artifact@v4 | |
with: | |
name: compile-commands | |
- name: Install Conan | |
id: conan | |
uses: turtlebrowser/get-conan@main | |
with: | |
version: 2.3.2 | |
- name: Create default Conan profile | |
run: conan profile detect | |
- name: Get conan cache | |
uses: actions/download-artifact@v4 | |
with: | |
name: conan-cache | |
- name: Restore conan cache from archive | |
shell: bash | |
run: | | |
conan cache restore conan-cache.tgz | |
- name: Fetch up-cpp | |
uses: actions/checkout@v4 | |
with: | |
path: up-cpp | |
- name: Get build artifacts | |
uses: actions/download-artifact@v4 | |
with: | |
name: build-artifacts | |
path: up-cpp/build/Release | |
- name: Run linters on source | |
continue-on-error: true | |
id: source-linter | |
uses: cpp-linter/cpp-linter-action@v2 | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
with: | |
repo-root: up-cpp | |
ignore: 'test' | |
style: 'file' # read .clang-format for configuration | |
tidy-checks: '' # Read .clang-tidy for configuration | |
database: build/Release/compile_commands.json | |
- name: Run linters on tests | |
continue-on-error: true | |
id: test-linter | |
uses: cpp-linter/cpp-linter-action@v2 | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
with: | |
repo-root: up-cpp | |
ignore: 'src|include' | |
style: 'file' # read .clang-format for configuration | |
tidy-checks: '' # Read .clang-tidy for configuration | |
database: build/Release/compile_commands.json | |
- name: Report lint failure | |
if: steps.source-linter.outputs.checks-failed > 0 || steps.test-linter.outputs.checks-failed > 0 | |
run: | | |
exit 1 | |
# NOTE: In GitHub repository settings, the "Require status checks to pass | |
# before merging" branch protection rule ensures that commits are only merged | |
# from branches where specific status checks have passed. These checks are | |
# specified manually as a list of workflow job names. Thus we use this extra | |
# job to signal whether all CI checks have passed. | |
ci: | |
name: CI status checks | |
runs-on: ubuntu-latest | |
needs: [build, test, memcheck, threadcheck, helgrind, dhat] | |
if: always() | |
steps: | |
- name: Check whether all jobs pass | |
run: echo '${{ toJson(needs) }}' | jq -e 'all(.result == "success")' |