Trying coverage tests on self-hosted runners and coveralls #104
This file contains hidden or 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: Self-Hosted Build and Test | |
| on: | |
| pull_request: | |
| branches: [ develop ] | |
| workflow_dispatch: | |
| inputs: | |
| ref: | |
| description: "Branch, tag, or SHA to test (leave empty for current ref)" | |
| required: false | |
| default: "" | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.event.inputs.ref || github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| PYTHON_REQUIRED_VERSION: "3.12.2" | |
| FC: gfortran-13 | |
| BUILD_DIR: build-coverage | |
| ANNUAL_SIMULATION_EXCLUDE_REGEX: >- | |
| ^integration\.(GSHP-GLHE-BoreholeFieldDesign|PythonPluginSolarHeating|_5ZoneAirCooled_annual|_5ZoneAirCooled_LeapYear_annual|UnitarySystem_MultiSpeedDX_EconoStaging|UnitarySystem_VariableSpeedDX_SZVAV|_ResidentialBase|_ExternalInterface-functionalmockupunit-to-actuator|_ExternalInterface-functionalmockupunit-to-schedule|_ExternalInterface-functionalmockupunit-to-variable)$ | |
| INTEGRATION_EXCLUDE_REGEX: >- | |
| ^integration\.(UnitaryHybridAC_DedicatedOutsideAir|HospitalLowEnergy|GSHP-GLHE-CalcGFunctions|HospitalBaselineReheatReportEMS|HospitalBaseline|RefBldgOutPatientNew2004_Chicago|ASHRAE901_ApartmentHighRise_STD2019_Denver|UnitarySystem_VariableSpeedDX_SZVAV|ASHRAE901_OutPatientHealthCare_STD2019_Denver|UnitarySystem_MultiSpeedDX_EconoStaging|RefBldgSecondarySchoolNew2004_Chicago|RefrigeratedWarehouse|HeatPumpWaterHeaterStratified|ASHRAE901_OfficeLarge_STD2019_Denver_Chiller205|ASHRAE901_OfficeLarge_STD2019_Denver_Chiller205_Detailed|_5ZoneAirCooled_LeapYear_annual|_5ZoneAirCooled_annual|_SmallOffice_Dulles|EcoroofOrlando|EcoroofOrlando_NoSitePrec)$ | |
| jobs: | |
| coverage: | |
| name: Coverage | |
| runs-on: [self-hosted, linux, x64, ubuntu-24.04] | |
| permissions: | |
| contents: read | |
| statuses: write | |
| steps: | |
| - name: Checkout EnergyPlus | |
| uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ github.event.inputs.ref || github.ref }} | |
| - name: Resolve checked out SHA | |
| id: checkout-sha | |
| shell: bash | |
| run: echo "sha=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT" | |
| - name: Setup runner | |
| id: setup-runner | |
| uses: ./.github/actions/setup-runner | |
| with: | |
| python-version: ${{ env.PYTHON_REQUIRED_VERSION }} | |
| python-arch: x64 | |
| - name: Restore ccache | |
| uses: actions/cache/restore@v5 | |
| id: cacheccache-restore | |
| with: | |
| path: | | |
| ${{ steps.setup-runner.outputs.ccache-dir }} | |
| key: ccache-self-hosted-linux-${{ steps.setup-runner.outputs.compiler-id }}-coverage-${{ github.head_ref || github.event.inputs.ref || github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} | |
| restore-keys: | | |
| ccache-self-hosted-linux-${{ steps.setup-runner.outputs.compiler-id }}-coverage-${{ github.head_ref || github.event.inputs.ref || github.ref_name }}- | |
| ccache-self-hosted-linux-${{ steps.setup-runner.outputs.compiler-id }}-coverage- | |
| ccache-self-hosted-linux-${{ steps.setup-runner.outputs.compiler-id }}- | |
| ccache-self-hosted-linux- | |
| - name: Install Linux coverage tools | |
| run: | | |
| sudo apt-get -qq update | |
| sudo apt-get -qq install -y lcov | |
| - name: Show restored ccache stats | |
| shell: bash | |
| run: | | |
| ccache --show-stats -vv || ccache --show-stats | |
| ccache --zero-stats | |
| ccache -p | |
| - name: Configure coverage build | |
| run: > | |
| cmake -S . -B ${{ env.BUILD_DIR }} | |
| -G "Unix Makefiles" | |
| -DCMAKE_BUILD_TYPE=RelWithDebInfo | |
| -DLINK_WITH_PYTHON:BOOL=ON | |
| -DPYTHON_CLI:BOOL=OFF | |
| -DPython_REQUIRED_VERSION:STRING=${{ env.PYTHON_REQUIRED_VERSION }} | |
| -DPython_ROOT_DIR:PATH=${{ steps.setup-runner.outputs.python-root-dir }} | |
| -DBUILD_FORTRAN:BOOL=ON | |
| -DBUILD_TESTING=ON | |
| -DBUILD_PACKAGE=OFF | |
| -DDOCUMENTATION_BUILD=DoNotBuild | |
| -DENABLE_REGRESSION_TESTING:BOOL=OFF | |
| -DTEST_ANNUAL_SIMULATION:BOOL=OFF | |
| -DENABLE_COVERAGE:BOOL=ON | |
| -DENABLE_GTEST_DEBUG_MODE:BOOL=OFF | |
| -DENABLE_PCH:BOOL=OFF | |
| -DFORCE_DEBUG_ARITHM_GCC_OR_CLANG:BOOL=ON | |
| -DCOMMIT_SHA:STRING=${{ steps.checkout-sha.outputs.sha }} | |
| - name: Build coverage targets | |
| run: cmake --build ${{ env.BUILD_DIR }} -j "${{ steps.setup-runner.outputs.nproc }}" | |
| - name: Show post-build ccache stats | |
| shell: bash | |
| run: ccache --show-stats -vv || ccache --show-stats | |
| - name: Run unit tests | |
| run: > | |
| ctest | |
| --test-dir ${{ env.BUILD_DIR }} | |
| -E "integration.*" | |
| --output-on-failure | |
| -j "${{ steps.setup-runner.outputs.nproc }}" | |
| - name: Generate unit test coverage results | |
| working-directory: ${{ env.BUILD_DIR }} | |
| run: | | |
| set -o pipefail | |
| mkdir -p coverage/unit | |
| lcov -c -d . -o coverage/unit/lcov.output --no-external --base-directory ${{ github.workspace }} --source-directory ${{ github.workspace }} --ignore-errors source,source | |
| lcov -e coverage/unit/lcov.output "${{ github.workspace }}/src/EnergyPlus/*" "src/EnergyPlus/*" -o coverage/unit/lcov.output.filtered --ignore-errors unused,unused,empty,empty | |
| grep -q '^DA:' coverage/unit/lcov.output.filtered | |
| # Coveralls needs repo-relative SF paths to fetch source for line views. | |
| sed "s#^SF:${{ github.workspace }}/#SF:#" coverage/unit/lcov.output.filtered > coverage/unit/lcov.output.coveralls | |
| genhtml coverage/unit/lcov.output.filtered -o coverage/unit/lcov-html --source-directory ${{ github.workspace }} --demangle-cpp --function-coverage --synthesize-missing --ignore-errors source,source | tee coverage/unit/cover.txt | |
| - name: Process unit test coverage summary | |
| working-directory: ${{ env.BUILD_DIR }}/coverage/unit | |
| continue-on-error: true | |
| run: ${{ steps.setup-runner.outputs.python-root-dir }}/bin/python ${{ github.workspace }}/scripts/dev/gha_coverage_summary.py | |
| - name: Add unit test coverage summary to job summary | |
| if: ${{ always() && hashFiles(format('{0}/{1}/coverage/unit/cover.md', github.workspace, env.BUILD_DIR)) != '' }} | |
| run: cat ${{ github.workspace }}/${{ env.BUILD_DIR }}/coverage/unit/cover.md >> "$GITHUB_STEP_SUMMARY" | |
| - name: Clear coverage counters before integration tests | |
| run: ${{ steps.setup-runner.outputs.python-root-dir }}/bin/python ${{ github.workspace }}/scripts/dev/clear_coverage_results.py ${{ env.BUILD_DIR }} | |
| - name: Run integration tests excluding slowest and annual-only tests | |
| run: > | |
| ctest | |
| --test-dir ${{ env.BUILD_DIR }} | |
| -R "integration.*" | |
| -E "${{ env.INTEGRATION_EXCLUDE_REGEX }}|${{ env.ANNUAL_SIMULATION_EXCLUDE_REGEX }}" | |
| --output-on-failure | |
| -j "${{ steps.setup-runner.outputs.nproc }}" | |
| - name: Generate integration test coverage results | |
| working-directory: ${{ env.BUILD_DIR }} | |
| run: | | |
| set -o pipefail | |
| mkdir -p coverage/integration | |
| lcov -c -d . -o coverage/integration/lcov.output --no-external --base-directory ${{ github.workspace }} --source-directory ${{ github.workspace }} --ignore-errors source,source | |
| lcov -e coverage/integration/lcov.output "${{ github.workspace }}/src/EnergyPlus/*" "src/EnergyPlus/*" -o coverage/integration/lcov.output.filtered --ignore-errors unused,unused,empty,empty | |
| grep -q '^DA:' coverage/integration/lcov.output.filtered | |
| # Coveralls needs repo-relative SF paths to fetch source for line views. | |
| sed "s#^SF:${{ github.workspace }}/#SF:#" coverage/integration/lcov.output.filtered > coverage/integration/lcov.output.coveralls | |
| genhtml coverage/integration/lcov.output.filtered -o coverage/integration/lcov-html --source-directory ${{ github.workspace }} --demangle-cpp --function-coverage --synthesize-missing --ignore-errors source,source | tee coverage/integration/cover.txt | |
| - name: Process integration test coverage summary | |
| working-directory: ${{ env.BUILD_DIR }}/coverage/integration | |
| continue-on-error: true | |
| run: ${{ steps.setup-runner.outputs.python-root-dir }}/bin/python ${{ github.workspace }}/scripts/dev/gha_coverage_summary.py | |
| - name: Add integration test coverage summary to job summary | |
| if: ${{ always() && hashFiles(format('{0}/{1}/coverage/integration/cover.md', github.workspace, env.BUILD_DIR)) != '' }} | |
| run: cat ${{ github.workspace }}/${{ env.BUILD_DIR }}/coverage/integration/cover.md >> "$GITHUB_STEP_SUMMARY" | |
| - name: Upload unit test coverage to Coveralls | |
| id: coveralls-unit | |
| if: ${{ always() && hashFiles(format('{0}/{1}/coverage/unit/lcov.output.coveralls', github.workspace, env.BUILD_DIR)) != '' }} | |
| uses: coverallsapp/github-action@v2 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| file: ${{ github.workspace }}/${{ env.BUILD_DIR }}/coverage/unit/lcov.output.coveralls | |
| format: lcov | |
| base-path: ${{ github.workspace }} | |
| flag-name: unit-tests | |
| parallel: true | |
| build-number: ${{ github.run_id }} | |
| git-branch: ${{ github.head_ref || github.event.inputs.ref || github.ref_name }} | |
| git-commit: ${{ github.event.pull_request.head.sha || steps.checkout-sha.outputs.sha }} | |
| fail-on-error: true | |
| - name: Upload integration test coverage to Coveralls | |
| id: coveralls-integration | |
| if: ${{ always() && hashFiles(format('{0}/{1}/coverage/integration/lcov.output.coveralls', github.workspace, env.BUILD_DIR)) != '' }} | |
| uses: coverallsapp/github-action@v2 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| file: ${{ github.workspace }}/${{ env.BUILD_DIR }}/coverage/integration/lcov.output.coveralls | |
| format: lcov | |
| base-path: ${{ github.workspace }} | |
| flag-name: integration-tests | |
| parallel: true | |
| build-number: ${{ github.run_id }} | |
| git-branch: ${{ github.head_ref || github.event.inputs.ref || github.ref_name }} | |
| git-commit: ${{ github.event.pull_request.head.sha || steps.checkout-sha.outputs.sha }} | |
| fail-on-error: true | |
| - name: Finish Coveralls coverage build | |
| if: ${{ always() && (steps.coveralls-unit.conclusion == 'success' || steps.coveralls-integration.conclusion == 'success') }} | |
| uses: coverallsapp/github-action@v2 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| parallel-finished: true | |
| build-number: ${{ github.run_id }} | |
| git-branch: ${{ github.head_ref || github.event.inputs.ref || github.ref_name }} | |
| git-commit: ${{ github.event.pull_request.head.sha || steps.checkout-sha.outputs.sha }} | |
| fail-on-error: true | |
| - name: Upload unit test coverage artifacts | |
| if: ${{ always() && hashFiles(format('{0}/{1}/coverage/unit/lcov.output.filtered', github.workspace, env.BUILD_DIR)) != '' }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: unit_test_coverage_results | |
| path: | | |
| ${{ github.workspace }}/${{ env.BUILD_DIR }}/coverage/unit/lcov.output.filtered | |
| ${{ github.workspace }}/${{ env.BUILD_DIR }}/coverage/unit/lcov.output.coveralls | |
| ${{ github.workspace }}/${{ env.BUILD_DIR }}/coverage/unit/lcov-html | |
| - name: Upload integration test coverage artifacts | |
| if: ${{ always() && hashFiles(format('{0}/{1}/coverage/integration/lcov.output.filtered', github.workspace, env.BUILD_DIR)) != '' }} | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: integration_test_coverage_results | |
| path: | | |
| ${{ github.workspace }}/${{ env.BUILD_DIR }}/coverage/integration/lcov.output.filtered | |
| ${{ github.workspace }}/${{ env.BUILD_DIR }}/coverage/integration/lcov.output.coveralls | |
| ${{ github.workspace }}/${{ env.BUILD_DIR }}/coverage/integration/lcov-html | |
| - name: Save ccache | |
| if: always() && steps.cacheccache-restore.outputs.cache-hit != 'true' | |
| uses: actions/cache/save@v5 | |
| with: | |
| path: | | |
| ${{ steps.setup-runner.outputs.ccache-dir }} | |
| key: ${{ steps.cacheccache-restore.outputs.cache-primary-key }} |