diff --git a/.github/workflows/analysis_workflow.yml b/.github/workflows/analysis_workflow.yml new file mode 100644 index 0000000000..2bc98adfed --- /dev/null +++ b/.github/workflows/analysis_workflow.yml @@ -0,0 +1,202 @@ +name: Build with analysis tools +on: + workflow_dispatch: + inputs: + run: + type: boolean + + schedule: # Schdeule the job to run at 12 a.m. daily + - cron: '0 0 * * *' +jobs: + cibw_docker_image: + uses: ./.github/workflows/cibw_docker_image.yml + permissions: {packages: write} + with: + cibuildwheel_ver: "2.12.1" + force_update: false + + code_coverage: + needs: [cibw_docker_image] + runs-on: "ubuntu-latest" + container: + image: ${{needs.cibw_docker_image.outputs.tag}} + services: + mongodb: + image: mongo:4.4 + ports: + - 27017:27017 + env: + SCCACHE_GHA_VERSION: ${{vars.SCCACHE_GHA_VERSION || 1}} # Setting this env var enables the caching + VCPKG_NUGET_USER: ${{secrets.VCPKG_NUGET_USER || github.repository_owner}} + VCPKG_NUGET_TOKEN: ${{secrets.VCPKG_NUGET_TOKEN || secrets.GITHUB_TOKEN}} + VCPKG_MAN_NUGET_USER: ${{secrets.VCPKG_MAN_NUGET_USER}} # For forks to download pre-compiled dependencies from the Man repo + VCPKG_MAN_NUGET_TOKEN: ${{secrets.VCPKG_MAN_NUGET_TOKEN}} + CMAKE_C_COMPILER_LAUNCHER: sccache + CMAKE_CXX_COMPILER_LAUNCHER: sccache + ARCTIC_CMAKE_PRESET: linux-debug + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + + - name: Get number of CPU cores + uses: SimenB/github-actions-cpu-cores@v1 + id: cpu-cores + + - name: Extra envs + run: | + . build_tooling/vcpkg_caching.sh # Linux follower needs another call in CIBW + echo -e "VCPKG_BINARY_SOURCES=$VCPKG_BINARY_SOURCES + VCPKG_ROOT=$PLATFORM_VCPKG_ROOT" | tee -a $GITHUB_ENV + cmake -P cpp/CMake/CpuCount.cmake | sed 's/^-- //' | tee -a $GITHUB_ENV + env: + CMAKE_BUILD_PARALLEL_LEVEL: ${{vars.CMAKE_BUILD_PARALLEL_LEVEL}} + + - name: Prepare C++ compilation env + run: . build_tooling/prep_cpp_build.sh + + - name: CMake compile + uses: lukka/run-cmake@v10 + with: + cmakeListsTxtPath: ${{github.workspace}}/cpp/CMakeLists.txt + configurePreset: ${{env.ARCTIC_CMAKE_PRESET}} + buildPreset: ${{env.ARCTIC_CMAKE_PRESET}} + env: + ARCTICDB_CODE_COVERAGE_BUILD: 1 + ARCTICDB_DEBUG_FIND_PYTHON: ${{vars.ARCTICDB_DEBUG_FIND_PYTHON}} + python_impl_name: 'cp311' + + - name: Run C++ Tests + shell: bash -l {0} + run: | + cd cpp/out/linux-debug-build/ + ls arcticdb + make -j ${{ steps.cpu-cores.outputs.count }} arcticdb_rapidcheck_tests + make -j ${{ steps.cpu-cores.outputs.count }} test_unit_arcticdb + ctest + + # We are chainging the python here because we want to use the default python to build (it is devel version) + # and this python for the rest of the testing + - name: Select Python (Linux) + run: echo /opt/python/cp36-cp36m/bin >> $GITHUB_PATH + + - name: Test with pytest + shell: bash -l {0} + run: | + yum install nodejs npm -y + npm config set strict-ssl false + npm install -g azurite + python -m pip install --upgrade pip + + python >build_tooling/requirements-analysis-workflow.txt <> $GITHUB_ENV + + - name: Run Gcovr manually post-pytest + shell: bash -l {0} + run: | + cd cpp/out/linux-debug-build/ + python -m pip install gcovr + mkdir coverage + python -m gcovr --txt --html-details coverage/index.html -e vcpkg_installed/ -e proto/ -e ../../third_party -e ../../arcticdb/util/test/ -r ../.. --exclude-throw-branches --exclude-unreachable-branches -u --exclude-function-lines | tee output.txt + zip -r coverage.zip coverage/ + + echo "CPP_COV_PERCENT=$(cat output.txt | grep 'TOTAL' | awk '{print $NF}' | tr -d '%')" >> $GITHUB_ENV + + - name: Upload Coverage + uses: actions/upload-artifact@v3 + with: + name: cpp-coverage-artifact + path: cpp/out/linux-debug-build/coverage.zip + + - name: Upload Python Coverage + uses: actions/upload-artifact@v3 + with: + name: python-coverage-artifact + path: python/python_cov.zip + + - name: Restore cached CPP Coverage Percentage from the previous run + id: cache-cov-restore + uses: actions/cache/restore@v3 + with: + path: prev_coverage.txt + key: coverage + + - name: Get and compare coverage if cache was restored + run: | + # if cache was restored, compare coverage + if [ -f coverage.txt ]; then + PREV_COVERAGE=$(cat prev_coverage.txt | cut -d' ' -f2) + echo "Previous coverage: $PREV_COVERAGE" + CURR_COVERAGE=${{env.CPP_COV_PERCENT}} + echo "CPP_COV_PREV_PERCENT=$PREV_COVERAGE" >> $GITHUB_ENV + echo "Current coverage: $CURR_COVERAGE" + if [ $CURR_COVERAGE -gt $PREV_COVERAGE ]; then + echo "Coverage increased" + elif [ $CURR_COVERAGE -lt $PREV_COVERAGE ]; then + echo "Coverage decreased" + else + echo "Coverage unchanged" + fi + fi + + - name: Save CPP Coverage Percentage to file + run: | + echo "Coverage: ${{ env.CPP_COV_PERCENT }}" > current_coverage.txt + + - name: Save the current CPP Coverage Percentage to the cache + id: cache-cov-save + uses: actions/cache/save@v3 + with: + path: current_coverage.txt + key: coverage + + - name: Check percentage and send Slack notification + if: ${{ env.CPP_COV_PREV_PERCENT && env.CPP_COV_PERCENT && env.CPP_COV_PERCENT < env.CPP_COV_PREV_PERCENT }} + uses: slackapi/slack-github-action@v1.24.0 + with: + # For posting a rich message using Block Kit + payload: | + { + "text": "The CPP Code Coverage has been reduced", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "The CPP Code Coverage from the current run(${{ env.CPP_COV_PERCENT }}%) is lower the previous one(${{ env.CPP_COV_PREV_PERCENT }}%)." + } + } + ] + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.ARCTICDB_DEV_WEBHOOK_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK diff --git a/cpp/CMakeLists.txt b/cpp/CMakeLists.txt index 41d36b962c..7c05e1c6c9 100755 --- a/cpp/CMakeLists.txt +++ b/cpp/CMakeLists.txt @@ -35,6 +35,9 @@ else() set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") endif() set(CMAKE_CXX_FLAGS_DEBUG "-ggdb") + if(DEFINED ENV{ARCTICDB_CODE_COVERAGE_BUILD}) + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} --coverage -g -O0") + endif() set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -ggdb") endif() diff --git a/python/tests/stress/arcticdb/version_store/test_stress_version_map_compact.py b/python/tests/stress/arcticdb/version_store/test_stress_version_map_compact.py index 72f6780e2f..01e7c0dd99 100644 --- a/python/tests/stress/arcticdb/version_store/test_stress_version_map_compact.py +++ b/python/tests/stress/arcticdb/version_store/test_stress_version_map_compact.py @@ -7,6 +7,8 @@ """ import random import time +import os +import pytest from multiprocessing import Process, Value @@ -56,6 +58,13 @@ def read_data(lib, sym, done): assert vs[idx]["version"] == vs[idx + 1]["version"] + 1 +@pytest.mark.skipif( + os.environ.get("ARCTICDB_CODE_COVERAGE_BUILD", "0") == "1", + reason=( + "When we build for code coverage, we make a DEBUG binary, which is much slower and causes this test to take" + " around ~4 hours which is breaking the build" + ), +) def test_stress_version_map_compact(object_version_store, sym, capsys): done = Value("b", 0) error = Value("b", 0) diff --git a/setup.cfg b/setup.cfg index c955646810..c180c7ce4a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -128,6 +128,7 @@ Testing = pymongo azure-storage-blob azure-identity + coverage [options.entry_points] console_scripts =