Repository navigation
Fix crashes in ensemble fracture statistics and camera zoom all #25843
Workflow file for this run
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: ResInsight Build With Cache | |
| on: | |
| push: | |
| pull_request: | |
| schedule: | |
| # Every day at 1am to make sure we have a build cache for the current date | |
| # build cache is | |
| - cron: '0 1 * * *' | |
| # Allows manually re-running the full pipeline (e.g. to re-verify the | |
| # publish-dev-build job) without needing a new commit. | |
| workflow_dispatch: | |
| concurrency: | |
| group: build-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| build: | |
| runs-on: ${{ matrix.config.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| build_type: [Release] | |
| config: | |
| - { | |
| name: "Windows_2022_qt_610", | |
| # Published to the dev-builds distribution repo as | |
| # <dist-name>.zip (see the publish-dev-build job below). Left | |
| # empty for configs that should not be published there. | |
| dist-name: "ResInsight-Windows", | |
| os: windows-2022, | |
| cc: "cl", | |
| cxx: "cl", | |
| build-python-module: true, | |
| execute-unit-tests: true, | |
| execute-pytests: true, | |
| publish-to-pypi: false, | |
| enable-asserts: false, | |
| vcpkg-bootstrap: bootstrap-vcpkg.bat, | |
| vcpkg-triplet: x64-windows-release, | |
| buildcache-max-size: 1610612736, | |
| qt-version: 6.10.1, | |
| ri-unit-test-path: "ApplicationLibCode/UnitTests/ResInsight-tests", | |
| } | |
| - { | |
| name: "Ubuntu 24.04 gcc", | |
| dist-name: "ResInsight-Ubuntu", | |
| os: ubuntu-24.04, | |
| cc: "gcc-14", | |
| cxx: "g++-14", | |
| build-python-module: true, | |
| execute-unit-tests: true, | |
| execute-pytests: true, | |
| publish-to-pypi: true, | |
| enable-asserts: false, | |
| vcpkg-bootstrap: bootstrap-vcpkg.sh, | |
| vcpkg-triplet: x64-linux-release, | |
| buildcache-max-size: 524288000, | |
| qt-version: 6.7.0, | |
| ri-unit-test-path: "ApplicationLibCode/UnitTests/ResInsight-tests", | |
| } | |
| - { | |
| name: "Ubuntu 24.04 clang-19", | |
| dist-name: "", | |
| os: ubuntu-24.04, | |
| cc: "clang-19", | |
| cxx: "clang++-19", | |
| build-python-module: true, | |
| execute-unit-tests: true, | |
| execute-pytests: false, | |
| publish-to-pypi: false, | |
| enable-asserts: true, | |
| vcpkg-bootstrap: bootstrap-vcpkg.sh, | |
| vcpkg-triplet: x64-linux-release, | |
| buildcache-max-size: 524288000, | |
| qt-version: 6.7.0, | |
| ri-unit-test-path: "ApplicationLibCode/UnitTests/ResInsight-tests", | |
| } | |
| env: | |
| BUILD_TYPE: Release | |
| BUILDCACHE_DIR: ${{ github.workspace }}/buildcache_dir | |
| BUILDCACHE_ACCURACY: SLOPPY | |
| # Per-configuration size limit, in bytes. The cache must hold a full | |
| # build with room to spare; at the limit buildcache evicts entries the | |
| # same build still needs and the hit ratio collapses. MSVC objects are | |
| # roughly twice the size of the gcc/clang ones, so Windows gets 1.5 GiB | |
| # while Linux stays at 500 MB. | |
| BUILDCACHE_MAX_CACHE_SIZE: ${{ matrix.config.buildcache-max-size }} | |
| VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite" | |
| # Supply-chain hardening: never install Python packages published within | |
| # the last week, to avoid pulling freshly published (potentially | |
| # compromised) releases. Honored by all `uv pip install` invocations below. | |
| UV_EXCLUDE_NEWER: "1 week" | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v7 | |
| with: | |
| submodules: true | |
| - name: Set up Python | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: "3.12" | |
| - name: Display Python version | |
| run: python -c "import sys; print(sys.version)" | |
| - name: Set up uv | |
| uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0 | |
| - name: Get Python executable path | |
| shell: bash | |
| id: python-path | |
| run: echo "PYTHON_EXECUTABLE=$(python -c 'import sys; import pathlib; print (pathlib.PurePath(sys.executable).as_posix())')" >> $GITHUB_OUTPUT | |
| - name: Print Python path | |
| run: echo "${{ steps.python-path.outputs.PYTHON_EXECUTABLE }}" | |
| - name: Install dependencies | |
| run: | | |
| # rips/_version.py is normally generated by CMake; create a dev | |
| # fallback so the editable install below can resolve the version. | |
| echo '__version__ = "0.0.0.dev"' > GrpcInterface/Python/rips/_version.py | |
| uv pip install --system -e "GrpcInterface/Python[dev]" | |
| - name: Use MSVC (Windows) | |
| if: contains(matrix.config.os, 'windows') | |
| uses: TheMrMilchmann/setup-msvc-dev@v4 | |
| with: | |
| arch: x64 | |
| - name: Setup buildcache | |
| uses: CeetronSolutions/setup-buildcache-action@v1.1 | |
| - name: Get current date | |
| id: current-time | |
| shell: bash | |
| run: echo "formattedTime=$(date -u +%Y-%m-%d)" >> $GITHUB_OUTPUT | |
| - name: Print time stamp | |
| run: echo "timestamp ${{ steps.current-time.outputs.formattedTime }}" | |
| - name: Restore Buildcache | |
| id: cache-buildcache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: ${{ env.BUILDCACHE_DIR }} | |
| key: ${{ matrix.config.os }}-${{ matrix.config.cc }}-${{ matrix.config.qt-version }}-cache-v03-${{ steps.current-time.outputs.formattedTime }} | |
| # Fall back to the most recent cache for this configuration if no | |
| # cache exists for the current date | |
| restore-keys: ${{ matrix.config.os }}-${{ matrix.config.cc }}-${{ matrix.config.qt-version }}-cache-v03- | |
| - name: Create Folder for buildcache | |
| run: New-Item ${{ env.BUILDCACHE_DIR }} -ItemType "directory" -Force | |
| shell: pwsh | |
| - name: Set apt mirror | |
| # see https://github.com/actions/runner-images/issues/7048 | |
| if: contains( matrix.config.os, 'ubuntu') | |
| run: | | |
| # make sure there is a `\t` between URL and `priority:*` attributes | |
| printf 'http://azure.archive.ubuntu.com/ubuntu priority:1\n' | sudo tee /etc/apt/mirrors.txt | |
| curl http://mirrors.ubuntu.com/mirrors.txt | sudo tee --append /etc/apt/mirrors.txt | |
| sudo sed -i 's/http:\/\/azure.archive.ubuntu.com\/ubuntu\//mirror+file:\/etc\/apt\/mirrors.txt/' /etc/apt/sources.list | |
| - name: Install Linux dependencies | |
| if: contains( matrix.config.os, 'ubuntu') | |
| run: | | |
| sudo apt-get update --option="APT::Acquire::Retries=3" | |
| sudo apt-get install --option="APT::Acquire::Retries=3" libxkbcommon-x11-0 libgl1-mesa-dev mesa-common-dev libglfw3-dev libglu1-mesa-dev libhdf5-dev | |
| - name: Install clang-19 | |
| if: contains( matrix.config.cc, 'clang') | |
| run: | | |
| set -e | |
| # Add LLVM repository | |
| wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - | |
| echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main" | sudo tee /etc/apt/sources.list.d/llvm-19.list | |
| echo "deb-src http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main" | sudo tee -a /etc/apt/sources.list.d/llvm-19.list | |
| # Update package list and install clang-19 | |
| sudo apt-get update --option="APT::Acquire::Retries=3" | |
| sudo apt-get install --option="APT::Acquire::Retries=3" -y \ | |
| clang-19 \ | |
| lldb-19 \ | |
| lld-19 \ | |
| clangd-19 \ | |
| clang-tidy-19 \ | |
| clang-format-19 \ | |
| clang-tools-19 \ | |
| libc++-19-dev \ | |
| libc++abi-19-dev \ | |
| libomp-19-dev | |
| # Verify installation | |
| clang-19 --version | |
| clang++-19 --version | |
| echo "clang-19 installation completed successfully" | |
| - name: Install gcc-14 | |
| if: contains( matrix.config.cc, 'gcc-14') | |
| run: | | |
| sudo apt-get install --option="APT::Acquire::Retries=3" gcc-14 g++-14 | |
| - name: Install Qt | |
| uses: CeetronSolutions/install-qt-action@bump-node24 | |
| with: | |
| version: ${{ matrix.config.qt-version }} | |
| dir: "${{ github.workspace }}/Qt/" | |
| cache: true | |
| setup-python: false | |
| modules: "qtnetworkauth" | |
| - name: vcpkg bootstrap | |
| run: | | |
| ThirdParty/vcpkg/${{ matrix.config.vcpkg-bootstrap }} | |
| - name: Get vcpkg submodule SHA | |
| id: vcpkg-sha | |
| shell: bash | |
| run: echo "sha=$(git rev-parse HEAD:ThirdParty/vcpkg)" >> $GITHUB_OUTPUT | |
| - name: Get MSVC compiler hash (Windows) | |
| # vcpkg keys each binary's ABI on a SHA-1 of the actual cl.exe binary | |
| # content (see ThirdParty/vcpkg/scripts/detect_compiler/CMakeLists.txt), | |
| # not on the VCToolsVersion folder name. GitHub ships rebuilt cl.exe | |
| # binaries under the same VCToolsVersion across runner image releases, so | |
| # vcpkg's ABI hash changes while VCToolsVersion stays fixed; the restored | |
| # binaries are then rejected and vcpkg rebuilds everything. Because the | |
| # cache key did not change, the action skips saving the freshly built | |
| # binaries, so the stale entry never refreshes and the rebuild loop | |
| # persists across runs. Hash cl.exe directly so the cache key tracks | |
| # exactly what vcpkg tracks: a cl.exe change yields a new key, one cold | |
| # rebuild, then a successful save under the new key. cl.exe is on PATH | |
| # via the "Use MSVC (Windows)" step above. | |
| id: compiler-hash | |
| if: contains(matrix.config.os, 'windows') | |
| shell: bash | |
| run: | | |
| cl_path=$(cygpath -u "$(where.exe cl.exe | head -n 1 | tr -d '\r')") | |
| echo "Using compiler: $cl_path" | |
| echo "hash=$(sha1sum "$cl_path" | cut -d' ' -f1)" >> $GITHUB_OUTPUT | |
| - name: Get runner image version | |
| # vcpkg's ABI hash covers more of the runner image than cl.exe alone: on | |
| # Windows every port's ABI includes the PowerShell version, and other | |
| # image-provided tools feed it as well. A PowerShell 7.6.3 -> 7.6.4 bump | |
| # in image 20260728 changed all 102 ABIs while cl.exe, the vcpkg | |
| # submodule and vcpkg.json stayed fixed, so the cache restored but vcpkg | |
| # rejected every archive ("Restored 0 package(s)"). Since the key was | |
| # unchanged the action then skipped saving, leaving the stale entry in | |
| # place for good. Track the image version so any image bump gives one | |
| # cold rebuild followed by a save under the new key. | |
| id: image-version | |
| shell: bash | |
| run: echo "version=${ImageVersion:-unknown}" >> $GITHUB_OUTPUT | |
| - name: Restore vcpkg cache | |
| id: vcpkg-cache | |
| # Restore only. The cache is saved by the "Save vcpkg cache" step after a | |
| # successful Configure, so failed or cancelled jobs never write partial | |
| # caches. | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: ${{ github.workspace }}/.vcpkg-cache | |
| key: vcpkg-${{ runner.os }}-${{ matrix.config.cxx }}-${{ steps.image-version.outputs.version }}-${{ steps.compiler-hash.outputs.hash }}-${{ matrix.config.vcpkg-triplet }}-${{ steps.vcpkg-sha.outputs.sha }}-${{ hashFiles('vcpkg.json', 'vcpkg-configuration.json') }} | |
| - name: Print CMake version | |
| shell: bash | |
| run: | | |
| if [ "$RUNNER_OS" = "Windows" ]; then | |
| EXEC_PATH=$(where.exe cmake | head -n 1) | |
| else | |
| EXEC_PATH=$(which cmake) | |
| fi | |
| echo "Executable path: $EXEC_PATH" | |
| "$EXEC_PATH" --version | |
| - name: Configure | |
| shell: bash | |
| env: | |
| VCPKG_FEATURE_FLAGS: "binarycaching" # Possibly redundant, but explicitly sets the binary caching feature flag | |
| VCPKG_BINARY_SOURCES: "clear;files,${{ github.workspace }}/.vcpkg-cache,readwrite" | |
| CC: ${{ matrix.config.cc }} | |
| CXX: ${{ matrix.config.cxx }} | |
| run: > | |
| cmake -S . -B cmakebuild | |
| -DVCPKG_TARGET_TRIPLET=${{ matrix.config.vcpkg-triplet }} | |
| -DVCPKG_HOST_TRIPLET=${{ matrix.config.vcpkg-triplet }} | |
| -DCMAKE_INSTALL_PREFIX=cmakebuild/install | |
| -DCMAKE_BUILD_TYPE=${{ matrix.build_type }} | |
| -DRESINSIGHT_INCLUDE_APPLICATION_UNIT_TESTS=true | |
| -DRESINSIGHT_TREAT_WARNINGS_AS_ERRORS=true | |
| -DRESINSIGHT_ENABLE_PRECOMPILED_HEADERS=false | |
| -DRESINSIGHT_ENABLE_UNITY_BUILD=false | |
| -DRESINSIGHT_ENABLE_ASSERTS_IN_RELEASE=${{ matrix.config.enable-asserts }} | |
| -DRESINSIGHT_ENABLE_GRPC=${{ matrix.config.build-python-module }} | |
| -DRESINSIGHT_GRPC_PYTHON_EXECUTABLE=${{ steps.python-path.outputs.PYTHON_EXECUTABLE }} | |
| -DRESINSIGHT_GRPC_DOWNLOAD_PYTHON_MODULE=true | |
| -DRESINSIGHT_ENABLE_HDF5=false | |
| -DCMAKE_TOOLCHAIN_FILE=ThirdParty/vcpkg/scripts/buildsystems/vcpkg.cmake | |
| -G Ninja | |
| - name: Save vcpkg cache | |
| # Only after a fully successful Configure (all ports built) | |
| if: success() && steps.vcpkg-cache.outputs.cache-hit != 'true' | |
| uses: actions/cache/save@v6 | |
| with: | |
| path: ${{ github.workspace }}/.vcpkg-cache | |
| key: ${{ steps.vcpkg-cache.outputs.cache-primary-key }} | |
| - name: Build | |
| run: | | |
| cmake --build cmakebuild --target install | |
| - name: Stats for buildcache | |
| run: buildcache -s | |
| - name: Save Buildcache | |
| # Save the cache with the current date, unless a cache for the current | |
| # date was already restored (cache keys are immutable and cannot be | |
| # overwritten) | |
| # | |
| # Only save from the default branch. GitHub scopes cache writes to the | |
| # current ref, and a branch can only read its own scope plus the default | |
| # branch, so a cache saved from a feature branch or PR is invisible to | |
| # every other branch. Those copies bring no reuse, but they do count | |
| # against the 10 GB per-repository quota and evict the shared caches on | |
| # the default branch. | |
| if: >- | |
| steps.cache-buildcache.outputs.cache-hit != 'true' && | |
| github.ref == format('refs/heads/{0}', github.event.repository.default_branch) | |
| uses: actions/cache/save@v6 | |
| with: | |
| path: ${{ env.BUILDCACHE_DIR }} | |
| key: ${{ matrix.config.os }}-${{ matrix.config.cc }}-${{ matrix.config.qt-version }}-cache-v03-${{ steps.current-time.outputs.formattedTime }} | |
| - name: Run Unit Tests | |
| if: matrix.config.execute-unit-tests | |
| shell: bash | |
| run: | | |
| echo "Content of unit test folder " | |
| ls cmakebuild/${{ matrix.config.ri-unit-test-path }} | |
| cmakebuild/${{ matrix.config.ri-unit-test-path }} | |
| - name: (Python) Verify protobuf gencode compatibility | |
| if: matrix.config.build-python-module | |
| shell: bash | |
| run: | | |
| cd GrpcInterface/Python | |
| ${{ steps.python-path.outputs.PYTHON_EXECUTABLE }} check_gencode_compatibility.py | |
| - name: (Python) Build Python module | |
| if: matrix.config.build-python-module | |
| shell: bash | |
| run: | | |
| uv pip install --system build wheel | |
| cd GrpcInterface/Python | |
| ${{ steps.python-path.outputs.PYTHON_EXECUTABLE }} -m build | |
| - name: (Python) Check types using mypy | |
| if: matrix.config.build-python-module | |
| shell: bash | |
| run: | | |
| uv pip install --system mypy types-protobuf | |
| cd GrpcInterface/Python | |
| ${{ steps.python-path.outputs.PYTHON_EXECUTABLE }} -m mypy rips/*.py rips/generated/generated_classes.py | |
| - name: Run pytest | |
| if: matrix.config.execute-pytests | |
| env: | |
| RESINSIGHT_EXECUTABLE: ${{ runner.workspace }}/ResInsight/cmakebuild/ResInsight${{ runner.os == 'Windows' && '.exe' || '' }} | |
| run: | | |
| cd GrpcInterface/Python/rips | |
| ${{ steps.python-path.outputs.PYTHON_EXECUTABLE }} -m pytest --console | |
| - name: Upload python distribution folder | |
| if: matrix.config.publish-to-pypi | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: dist-python | |
| path: GrpcInterface/Python/dist | |
| retention-days: 5 | |
| - name: Upload artifacts | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| # Configs with a non-empty matrix.config.dist-name are uploaded | |
| # under a dist-<dist-name> artifact name, which the publish-dev-build | |
| # job below uses directly as the published asset name. Configs | |
| # without a dist-name (e.g. the clang-19 CI-only build) keep the | |
| # old descriptive name and are not published. | |
| name: ${{ matrix.config.dist-name != '' && format('dist-{0}', matrix.config.dist-name) || format('ResInsight-{0}', matrix.config.name) }} | |
| path: ${{ runner.workspace }}/ResInsight/cmakebuild/install | |
| retention-days: 5 | |
| pypi-publish: | |
| name: Upload release to PyPI | |
| needs: build | |
| runs-on: ubuntu-24.04 | |
| environment: | |
| name: pypi | |
| url: https://pypi.org/p/rips | |
| permissions: | |
| id-token: write # IMPORTANT: this permission is mandatory for trusted publishing | |
| # If this is a tagged release | |
| if: startsWith(github.ref, 'refs/tags') | |
| steps: | |
| - name: Download python distribution folder | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: dist-python | |
| path: dist | |
| - name: Display structure of downloaded files | |
| run: ls -R | |
| - name: Publish Python package to pypi | |
| # https://docs.pypi.org/trusted-publishers/adding-a-publisher/ | |
| uses: pypa/gh-action-pypi-publish@release/v1 | |
| publish-dev-build: | |
| name: Publish dev build to distribution repo | |
| needs: build | |
| runs-on: ubuntu-24.04 | |
| # Publishes a rolling `dev` pre-release to CeetronSolutions/resinsight-builds | |
| # (see magnesj/ResInsight#1093). Restricted to OPM/ResInsight and to | |
| # schedule/workflow_dispatch to limit how often it runs. | |
| if: >- | |
| github.repository == 'OPM/ResInsight' && | |
| (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && | |
| github.ref == 'refs/heads/dev' | |
| concurrency: | |
| group: publish-dev-build | |
| cancel-in-progress: true | |
| steps: | |
| - name: Download artifacts | |
| uses: actions/download-artifact@v8 | |
| with: | |
| path: artifacts | |
| - name: Package assets | |
| # Only matrix configs with a dist-name are published (dist-<dist-name>); | |
| # the zip name matches the dist-name directly. The dist-python | |
| # artifact (wheel/sdist built for pypi) is also published as-is. | |
| shell: bash | |
| run: | | |
| set -e | |
| mkdir dist | |
| shopt -s nullglob | |
| dirs=(artifacts/dist-*/) | |
| # dist-python holds raw wheel/sdist files, not an install tree; | |
| # publish it as-is instead of zipping it with the other dist-* dirs. | |
| filtered_dirs=() | |
| for d in "${dirs[@]}"; do | |
| [ "$d" = "artifacts/dist-python/" ] || filtered_dirs+=("$d") | |
| done | |
| dirs=("${filtered_dirs[@]}") | |
| if [ ${#dirs[@]} -eq 0 ]; then | |
| echo "::error::No dist-* artifact directories found" | |
| exit 1 | |
| fi | |
| for d in "${dirs[@]}"; do | |
| dest_name=$(basename "$d") | |
| dest_name=${dest_name#dist-} | |
| # upload-artifact drops file permissions; restore the exec bit on | |
| # ELF binaries and scripts so they run directly after unzip. | |
| while IFS= read -r -d '' f; do | |
| case "$(head -c 4 "$f" | od -An -tx1 | tr -d ' \n')" in | |
| 7f454c46|2321*) chmod +x "$f" ;; | |
| esac | |
| done < <(find "$d" -type f -print0) | |
| (cd "$d" && zip -qr "$GITHUB_WORKSPACE/dist/${dest_name}.zip" .) | |
| done | |
| # Publish the python wheel/sdist built for pypi alongside the zips, | |
| # renamed to drop the version number so the rolling release always | |
| # exposes a stable, predictable asset name. | |
| if [ -d artifacts/dist-python ]; then | |
| for f in artifacts/dist-python/*; do | |
| case "$f" in | |
| *.tar.gz) cp "$f" dist/rips.tar.gz ;; | |
| *.whl) cp "$f" dist/rips.whl ;; | |
| *) cp "$f" dist/ ;; | |
| esac | |
| done | |
| fi | |
| ls -l dist | |
| - name: Update rolling release in builds repo | |
| env: | |
| GH_TOKEN: ${{ secrets.DEV_BUILDS_TOKEN }} | |
| GH_REPO: CeetronSolutions/resinsight-builds | |
| TAG: dev-latest | |
| run: | | |
| set -e | |
| if ! gh release view "$TAG" >/dev/null 2>&1; then | |
| gh release create "$TAG" --prerelease --title "ResInsight dev build" --notes "Rolling build" | |
| fi | |
| run_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| asset_list=$(cd dist && for f in *; do echo "- $f"; done) | |
| notes=$(cat <<EOF | |
| Built from OPM/ResInsight@${GITHUB_SHA::8} on $(date -u +%Y-%m-%dT%H:%MZ) | |
| Source build job: $run_url | |
| Published assets: | |
| $asset_list | |
| EOF | |
| ) | |
| gh release edit "$TAG" --notes "$notes" | |
| gh release upload "$TAG" dist/* --clobber |