ci.yml raw

   1  # Copyright (c) 2023-present The Bitcoin Core developers
   2  # Distributed under the MIT software license, see the accompanying
   3  # file COPYING or https://opensource.org/license/mit.
   4  
   5  name: CI
   6  on:
   7    # See: https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request.
   8    pull_request:
   9    # See: https://docs.github.com/en/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#push.
  10    push:
  11      branches:
  12        - '**'
  13      tags-ignore:
  14        - '**'
  15  
  16  concurrency:
  17    group: ${{ github.event_name != 'pull_request' && github.run_id || github.ref }}
  18    cancel-in-progress: true
  19  
  20  env:
  21    CI_FAILFAST_TEST_LEAVE_DANGLING: 1  # GHA does not care about dangling processes and setting this variable avoids killing the CI script itself on error
  22  
  23  defaults:
  24    run:
  25      # Enforce fail-fast behavior for all platforms.
  26      # See: https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference
  27      shell: bash
  28  
  29  jobs:
  30    test-each-commit:
  31      name: 'test ancestor commits'
  32      runs-on: ${{ github.repository == 'bitcoin/bitcoin' && 'warp-ubuntu-latest-x64-8x' || 'ubuntu-latest' }}
  33      env:
  34        TEST_RUNNER_PORT_MIN: "14000"  # Use a larger port range to avoid colliding with other CI services.
  35      if: github.event_name == 'pull_request' && github.event.pull_request.commits != 1
  36      timeout-minutes: 360  # Use maximum time, see https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idtimeout-minutes.
  37      steps:
  38        - name: Determine fetch depth
  39          run: echo "FETCH_DEPTH=$((${{ github.event.pull_request.commits }} + 2))" >> "$GITHUB_ENV"
  40        - &ANNOTATION_PR_NUMBER
  41          name: Annotate with pull request number
  42          # This annotation is machine-readable and can be used to assign a check
  43          # run to its corresponding pull request. Running in all check runs is
  44          # required, because check re-runs discard the annotations of other
  45          # tasks in the test suite.
  46          run: |
  47            if [ "${{ github.event_name }}" = "pull_request" ]; then
  48              echo "::notice title=debug_pull_request_number_str::${{ github.event.number }}"
  49            fi
  50        - uses: actions/checkout@v6
  51          with:
  52            ref: ${{ github.event.pull_request.head.sha }}
  53            fetch-depth: ${{ env.FETCH_DEPTH }}
  54        - name: Determine commit range
  55          run: |
  56            # Checkout HEAD~ and find the test base commit.
  57            # Checkout HEAD~ because it would be wasteful to rerun
  58            # tests on the PR head commit that are already run
  59            # by other jobs.
  60            git checkout HEAD~
  61            # Moreover, pull requests that contain a merge commit
  62            # are generally draft pull requests that merge in other
  63            # pull requests, so only check the relevant commits
  64            # after the last merge commit. A merge commit could
  65            # also be a subtree merge commit, which may be
  66            # worthwhile to check. However, it is rare that the
  67            # subtree merge commit is not the top commit (which
  68            # would be skipped anyway by this task, because it is
  69            # run by all other tasks). Also, `git rebase --exec`
  70            # does not work on merge commits, so if this was
  71            # important to check, the logic would have to be
  72            # rewritten.
  73            #
  74            # Figure out test base commit by listing ancestors of
  75            # HEAD, excluding ancestors of the most recent merge
  76            # commit, ordering them from oldest to newest, and
  77            # taking the first one.
  78            #
  79            # In the command below, the ^@ suffix is used to refer
  80            # to all parents of the merge commit as described in:
  81            # https://git-scm.com/docs/git-rev-parse#_other_rev_parent_shorthand_notations
  82            # and the ^ prefix is used to exclude these parents
  83            # and all their ancestors from the rev-list output
  84            # as described in:
  85            # https://git-scm.com/docs/git-rev-list
  86            MERGE_BASE=$(git rev-list -n1 --merges HEAD)
  87            EXCLUDE_MERGE_BASE_ANCESTORS=
  88            # MERGE_BASE can be empty due to limited fetch-depth
  89            if test -n "$MERGE_BASE"; then
  90              EXCLUDE_MERGE_BASE_ANCESTORS=^${MERGE_BASE}^@
  91            fi
  92            echo "TEST_BASE=$(git rev-list -n${{ github.event.pull_request.commits }} --reverse HEAD $EXCLUDE_MERGE_BASE_ANCESTORS | head -1)" >> "$GITHUB_ENV"
  93        - run: |
  94            git fetch origin "${GITHUB_BASE_REF}"
  95            git config user.email "ci@example.com"
  96            git config user.name "CI"
  97        - run: |
  98            sudo apt-get update
  99            sudo apt-get install clang mold ccache build-essential cmake ninja-build pkgconf python3-zmq libboost-dev libsqlite3-dev systemtap-sdt-dev libzmq3-dev qt6-base-dev qt6-tools-dev qt6-l10n-tools libqrencode-dev capnproto libcapnp-dev -y
 100            sudo pip3 install --break-system-packages pycapnp
 101        - name: Compile and run tests
 102          run: |
 103            # Run tests on commits after the last merge commit and before the PR head commit
 104            git rebase --exec "git merge --no-commit origin/${GITHUB_BASE_REF} && python3 ./.github/ci-test-each-commit-exec.py && git reset --hard" ${{ env.TEST_BASE }}
 105  
 106    macos-native-arm64:
 107      name: ${{ matrix.job-name }}
 108      # Use any image to support the xcode-select below, but hardcode version to avoid silent upgrades (and breaks).
 109      # See: https://github.com/actions/runner-images#available-images.
 110      runs-on: macos-15
 111  
 112      # When a contributor maintains a fork of the repo, any pull request they make
 113      # to their own fork, or to the main repository, will trigger two CI runs:
 114      # one for the branch push and one for the pull request.
 115      # This can be avoided by setting SKIP_BRANCH_PUSH=true as a custom env variable
 116      # in Github repository settings.
 117      if: ${{ vars.SKIP_BRANCH_PUSH != 'true' || github.event_name == 'pull_request' }}
 118  
 119      timeout-minutes: 120
 120  
 121      strategy:
 122        fail-fast: false
 123        matrix:
 124          job-type: [standard, fuzz]
 125          include:
 126            - job-type: standard
 127              file-env: './ci/test/00_setup_env_mac_native.sh'
 128              job-name: 'macOS native'
 129            - job-type: fuzz
 130              file-env: './ci/test/00_setup_env_mac_native_fuzz.sh'
 131              job-name: 'macOS native, fuzz'
 132  
 133      env:
 134        DANGER_RUN_CI_ON_HOST: 1
 135        BASE_ROOT_DIR: ${{ github.workspace }}/repo_archive
 136  
 137      steps:
 138        - *ANNOTATION_PR_NUMBER
 139  
 140        - &CHECKOUT
 141          name: Checkout
 142          uses: actions/checkout@v6
 143          with:
 144            # Ensure the latest merged pull request state is used, even on re-runs.
 145            ref: &CHECKOUT_REF_TMPL ${{ github.event_name == 'pull_request' && github.ref || '' }}
 146  
 147        - name: Clang version
 148          run: |
 149            # Use the latest Xcode supported by the version of macOS denoted in
 150            # doc/release-notes-empty-template.md and providing at least the
 151            # minimum clang version denoted in doc/dependencies.md.
 152            # See: https://developer.apple.com/documentation/xcode-release-notes/xcode-16_2-release-notes
 153            sudo xcode-select --switch /Applications/Xcode_16.2.app
 154            clang --version
 155  
 156        - name: Install Homebrew packages
 157          env:
 158            HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
 159          run: |
 160            # A workaround for "The `brew link` step did not complete successfully" error.
 161            brew install --quiet python@3 || brew link --overwrite python@3
 162            brew install --quiet coreutils ninja pkgconf ccache boost zeromq qt@6 qrencode capnp
 163  
 164        - name: Set Ccache directory
 165          run: echo "CCACHE_DIR=${RUNNER_TEMP}/ccache_dir" >> "$GITHUB_ENV"
 166  
 167        - name: Restore Ccache cache
 168          id: ccache-cache
 169          uses: actions/cache/restore@v5
 170          with:
 171            path: ${{ env.CCACHE_DIR }}
 172            key: ${{ github.job }}-${{ matrix.job-type }}-ccache-${{ github.run_id }}
 173            restore-keys: ${{ github.job }}-${{ matrix.job-type }}-ccache-
 174  
 175        - name: Create git archive
 176          run: |
 177            git log -1
 178            git archive --format=tar --prefix=repo_archive/ --output=repo.tar HEAD
 179            tar -xf repo.tar
 180  
 181        - name: CI script
 182          run: |
 183            cd repo_archive
 184            ./ci/test_run_all.sh
 185          env:
 186            FILE_ENV: ${{ matrix.file-env }}
 187  
 188        - name: Save Ccache cache
 189          uses: actions/cache/save@v5
 190          if: github.event_name != 'pull_request' && github.ref_name == github.event.repository.default_branch && steps.ccache-cache.outputs.cache-hit != 'true'
 191          with:
 192            path: ${{ env.CCACHE_DIR }}
 193            # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#update-a-cache
 194            key: ${{ steps.ccache-cache.outputs.cache-primary-key }}
 195  
 196    windows-native-dll:
 197      name: ${{ matrix.job-name }}
 198      runs-on: windows-2025-vs2026
 199  
 200      if: ${{ vars.SKIP_BRANCH_PUSH != 'true' || github.event_name == 'pull_request' }}
 201  
 202      env:
 203        PYTHONUTF8: 1
 204        TEST_RUNNER_TIMEOUT_FACTOR: 40
 205  
 206      strategy:
 207        fail-fast: false
 208        matrix:
 209          job-type: [standard, fuzz]
 210          include:
 211            - job-type: standard
 212              job-name: 'Windows native, VS'
 213            - job-type: fuzz
 214              job-name: 'Windows native, fuzz, VS'
 215  
 216      steps:
 217        - *ANNOTATION_PR_NUMBER
 218  
 219        - *CHECKOUT
 220  
 221        - &IMPORT_VS_ENV
 222          name: Import Visual Studio env vars
 223          run: py -3 .github/ci-windows.py "standard" github_import_vs_env
 224  
 225        - name: Get tool information
 226          run: |
 227            set -o errexit -o pipefail -o xtrace -o nounset
 228  
 229            cmake -version | tee cmake_version
 230            echo '---'
 231            msbuild.exe -version | tee msbuild_version
 232            echo "${VCToolsVersion-}" | tee toolset_version
 233            py -3 --version
 234            bash --version
 235  
 236        - name: Restore vcpkg downloads cache
 237          id: vcpkg-downloads-cache
 238          uses: actions/cache/restore@v5
 239          with:
 240            path: |
 241              ~/AppData/Local/vcpkg/downloads/*
 242              !~/AppData/Local/vcpkg/downloads/tools
 243            key: ${{ github.job }}-vcpkg-downloads-${{ hashFiles('vcpkg.json') }}
 244  
 245        - name: Restore vcpkg binary cache
 246          uses: actions/cache/restore@v5
 247          id: vcpkg-binary-cache
 248          with:
 249            path: ~/AppData/Local/vcpkg/archives
 250            key: ${{ github.job }}-vcpkg-binary-release-${{ hashFiles('cmake_version', 'msbuild_version', 'toolset_version', 'vcpkg.json') }}
 251  
 252        - name: Generate build system
 253          run: |
 254            py -3 .github/ci-windows.py ${{ matrix.job-type }} generate
 255  
 256        - name: Save vcpkg binary cache
 257          uses: actions/cache/save@v5
 258          if: github.event_name != 'pull_request' && github.ref_name == github.event.repository.default_branch && steps.vcpkg-binary-cache.outputs.cache-hit != 'true' && matrix.job-type == 'standard'
 259          with:
 260            path: ~/AppData/Local/vcpkg/archives
 261            key: ${{ steps.vcpkg-binary-cache.outputs.cache-primary-key }}
 262  
 263        - name: Save vcpkg downloads cache
 264          uses: actions/cache/save@v5
 265          # Only save cache from the 'standard' job, as it includes the necessary downloads for other jobs in the matrix. If the matrix is modified, this may need amending.
 266          if: github.event_name != 'pull_request' && github.ref_name == github.event.repository.default_branch && steps.vcpkg-binary-cache.outputs.cache-hit != 'true' && steps.vcpkg-downloads-cache.outputs.cache-hit != 'true' && matrix.job-type == 'standard'
 267          with:
 268            # Cache the tools once as archives, but not redundantly in extracted form.
 269            path: |
 270              ~/AppData/Local/vcpkg/downloads/*
 271              !~/AppData/Local/vcpkg/downloads/tools
 272            key: ${{ steps.vcpkg-downloads-cache.outputs.cache-primary-key }}
 273  
 274        - name: Build
 275          run: |
 276            py -3 .github/ci-windows.py ${{ matrix.job-type }} build
 277  
 278        - name: Check executable manifests
 279          run: |
 280            py -3 .github/ci-windows.py ${{ matrix.job-type }} check_manifests
 281  
 282        - name: Prepare tests
 283          run: |
 284            py -3 .github/ci-windows.py ${{ matrix.job-type }} prepare_tests
 285  
 286        - name: Run tests
 287          env:
 288            TEST_RUNNER_EXTRA: "--timeout-factor=${{ env.TEST_RUNNER_TIMEOUT_FACTOR }} ${{ case(github.event_name == 'pull_request', '', '--extended') }}"
 289          run: |
 290            py -3 .github/ci-windows.py ${{ matrix.job-type }} run_tests
 291  
 292    record-frozen-commit:
 293      # Record frozen commit, so that the native tests on cross-builds can run on
 294      # the exact same commit id of the build.
 295      name: '[meta] record frozen commit'
 296      runs-on: ubuntu-slim
 297      outputs:
 298        commit: ${{ steps.record-commit.outputs.commit }}
 299      steps:
 300        - *ANNOTATION_PR_NUMBER
 301        - *CHECKOUT
 302        - name: Record commit
 303          id: record-commit
 304          run: echo "commit=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
 305  
 306    windows-cross:
 307      name: 'Windows-cross to x86_64, ${{ matrix.crt }}'
 308      needs: record-frozen-commit
 309      runs-on: ${{ github.repository == 'bitcoin/bitcoin' && 'warp-ubuntu-latest-x64-4x' || 'ubuntu-latest' }}
 310      if: ${{ vars.SKIP_BRANCH_PUSH != 'true' || github.event_name == 'pull_request' }}
 311  
 312      strategy:
 313        fail-fast: false
 314        matrix:
 315          crt: [msvcrt, ucrt]
 316          include:
 317            - crt: msvcrt
 318              file-env: './ci/test/00_setup_env_win64_msvcrt.sh'
 319              artifact-name: 'x86_64-w64-mingw32-executables'
 320            - crt: ucrt
 321              file-env: './ci/test/00_setup_env_win64.sh'
 322              artifact-name: 'x86_64-w64-mingw32ucrt-executables'
 323  
 324      env:
 325        FILE_ENV: ${{ matrix.file-env }}
 326        DANGER_CI_ON_HOST_FOLDERS: 1
 327  
 328      steps:
 329        - *ANNOTATION_PR_NUMBER
 330  
 331        - name: Checkout
 332          uses: actions/checkout@v6
 333          with:
 334            ref: ${{ needs.record-frozen-commit.outputs.commit }}
 335  
 336        - name: Configure environment
 337          uses: ./.github/actions/configure-environment
 338  
 339        - name: Restore caches
 340          id: restore-cache
 341          uses: ./.github/actions/cache/restore
 342          with:
 343            provider: ${{ github.repository == 'bitcoin/bitcoin' && 'warp' || 'gha' }}
 344  
 345        - name: Configure Docker
 346          uses: ./.github/actions/configure-docker
 347          with:
 348            provider: ${{ github.repository == 'bitcoin/bitcoin' && 'warp' || 'gha' }}
 349  
 350        - name: CI script
 351          run: ./ci/test_run_all.sh
 352  
 353        - name: Save caches
 354          uses: ./.github/actions/cache/save
 355          with:
 356            provider: ${{ github.repository == 'bitcoin/bitcoin' && 'warp' || 'gha' }}
 357  
 358        - name: Upload built executables
 359          uses: actions/upload-artifact@v7
 360          with:
 361            name: ${{ matrix.artifact-name }}-${{ github.run_id }}
 362            path: |
 363              ${{ env.BASE_BUILD_DIR }}/bin/*.dll
 364              ${{ env.BASE_BUILD_DIR }}/bin/*.exe
 365              ${{ env.BASE_BUILD_DIR }}/src/secp256k1/bin/*.exe
 366              ${{ env.BASE_BUILD_DIR }}/src/univalue/*.exe
 367              ${{ env.BASE_BUILD_DIR }}/test/config.ini
 368  
 369    windows-native-test:
 370      name: 'Windows, ${{ matrix.crt }}, test cross-built'
 371      runs-on: windows-2022
 372      needs: [windows-cross, record-frozen-commit]
 373  
 374      strategy:
 375        fail-fast: false
 376        matrix:
 377          crt: [msvcrt, ucrt]
 378          include:
 379            - crt: msvcrt
 380              artifact-name: 'x86_64-w64-mingw32-executables'
 381            - crt: ucrt
 382              artifact-name: 'x86_64-w64-mingw32ucrt-executables'
 383  
 384      env:
 385        PYTHONUTF8: 1
 386        TEST_RUNNER_TIMEOUT_FACTOR: 40
 387  
 388      steps:
 389        - *ANNOTATION_PR_NUMBER
 390  
 391        - name: Checkout
 392          uses: actions/checkout@v6
 393          with:
 394            ref: ${{ needs.record-frozen-commit.outputs.commit }}
 395  
 396        - name: Download built executables
 397          uses: actions/download-artifact@v8
 398          with:
 399            name: ${{ matrix.artifact-name }}-${{ github.run_id }}
 400  
 401        - name: Run bitcoind.exe
 402          run: py -3 .github/ci-windows-cross.py print_version
 403  
 404        - *IMPORT_VS_ENV
 405  
 406        - name: Check executable manifests
 407          run: py -3 .github/ci-windows-cross.py check_manifests
 408  
 409        - name: Prepare Windows test environment
 410          run: py -3 .github/ci-windows-cross.py prepare_tests
 411  
 412        - name: Run unit tests
 413          run: py -3 .github/ci-windows-cross.py run_unit_tests
 414  
 415        - name: Run functional tests
 416          env:
 417            TEST_RUNNER_EXTRA: "--timeout-factor=${{ env.TEST_RUNNER_TIMEOUT_FACTOR }} ${{ case(github.event_name == 'pull_request', '', '--extended') }}"
 418          run: |
 419            py -3 .github/ci-windows-cross.py run_functional_tests
 420  
 421    ci-matrix:
 422      name: ${{ matrix.name }}
 423      runs-on: ${{ github.repository == 'bitcoin/bitcoin' && matrix.warp-runner || matrix.fallback-runner }}
 424      if: ${{ vars.SKIP_BRANCH_PUSH != 'true' || github.event_name == 'pull_request' }}
 425      timeout-minutes: ${{ matrix.timeout-minutes }}
 426  
 427      env:
 428        DANGER_CI_ON_HOST_FOLDERS: 1
 429        FILE_ENV: ${{ matrix.file-env }}
 430  
 431      strategy:
 432        fail-fast: false
 433        matrix:
 434          include:
 435            - name: 'iwyu'
 436              warp-runner: 'warp-ubuntu-latest-x64-8x'
 437              fallback-runner: 'ubuntu-latest'
 438              timeout-minutes: 120
 439              file-env: './ci/test/00_setup_env_native_iwyu.sh'
 440  
 441            - name: '32 bit ARM'
 442              warp-runner: 'ubuntu-24.04-arm' # Warp's Arm runners don't support 32-bit mode currently
 443              fallback-runner: 'ubuntu-24.04-arm'
 444              timeout-minutes: 120
 445              file-env: './ci/test/00_setup_env_arm.sh'
 446              provider: 'gha'
 447  
 448            - name: 'ASan + LSan + UBSan + integer'
 449              warp-runner: 'warp-ubuntu-2404-x64-8x' # has to match container in ci/test/00_setup_env_native_asan.sh for tracing tools
 450              fallback-runner: 'ubuntu-24.04'
 451              timeout-minutes: 120
 452              file-env: './ci/test/00_setup_env_native_asan.sh'
 453  
 454            - name: 'macOS-cross to arm64'
 455              warp-runner: 'warp-ubuntu-latest-x64-4x'
 456              fallback-runner: 'ubuntu-latest'
 457              timeout-minutes: 120
 458              file-env: './ci/test/00_setup_env_mac_cross.sh'
 459  
 460            - name: 'macOS-cross to x86_64'
 461              warp-runner: 'warp-ubuntu-latest-x64-4x'
 462              fallback-runner: 'ubuntu-latest'
 463              timeout-minutes: 120
 464              file-env: './ci/test/00_setup_env_mac_cross_intel.sh'
 465  
 466            - name: 'NetBSD Cross'
 467              warp-runner: 'warp-ubuntu-latest-x64-8x'
 468              fallback-runner: 'ubuntu-latest'
 469              timeout-minutes: 120
 470              file-env: './ci/test/00_setup_env_netbsd_cross.sh'
 471  
 472            - name: 'FreeBSD Cross'
 473              warp-runner: 'warp-ubuntu-latest-x64-8x'
 474              fallback-runner: 'ubuntu-latest'
 475              timeout-minutes: 120
 476              file-env: './ci/test/00_setup_env_freebsd_cross.sh'
 477  
 478            - name: 'OpenBSD Cross'
 479              warp-runner: 'warp-ubuntu-latest-x64-8x'
 480              fallback-runner: 'ubuntu-latest'
 481              timeout-minutes: 120
 482              file-env: './ci/test/00_setup_env_openbsd_cross.sh'
 483  
 484            - name: 'No wallet'
 485              warp-runner: 'warp-ubuntu-latest-x64-4x'
 486              fallback-runner: 'ubuntu-latest'
 487              timeout-minutes: 120
 488              file-env: './ci/test/00_setup_env_native_nowallet.sh'
 489  
 490            - name: 'i686, no IPC'
 491              warp-runner: 'warp-ubuntu-latest-x64-8x'
 492              fallback-runner: 'ubuntu-latest'
 493              timeout-minutes: 120
 494              file-env: './ci/test/00_setup_env_i686_no_ipc.sh'
 495  
 496            - name: 'fuzzer,address,undefined,integer'
 497              warp-runner: 'warp-ubuntu-latest-x64-16x'
 498              fallback-runner: 'ubuntu-latest'
 499              timeout-minutes: 240
 500              file-env: './ci/test/00_setup_env_native_fuzz.sh'
 501  
 502            - name: 'previous releases'
 503              warp-runner: 'warp-ubuntu-latest-x64-8x'
 504              fallback-runner: 'ubuntu-latest'
 505              timeout-minutes: 120
 506              file-env: './ci/test/00_setup_env_native_previous_releases.sh'
 507  
 508            - name: 'Alpine (musl)'
 509              warp-runner: 'warp-ubuntu-latest-x64-8x'
 510              fallback-runner: 'ubuntu-latest'
 511              timeout-minutes: 120
 512              file-env: './ci/test/00_setup_env_native_alpine_musl.sh'
 513  
 514            - name: 'tidy'
 515              warp-runner: 'warp-ubuntu-latest-x64-8x'
 516              fallback-runner: 'ubuntu-latest'
 517              timeout-minutes: 120
 518              file-env: './ci/test/00_setup_env_native_tidy.sh'
 519  
 520            - name: 'TSan'
 521              warp-runner: 'warp-ubuntu-latest-x64-8x'
 522              fallback-runner: 'ubuntu-latest'
 523              timeout-minutes: 120
 524              file-env: './ci/test/00_setup_env_native_tsan.sh'
 525  
 526            - name: 'MSan, fuzz'
 527              warp-runner: 'warp-ubuntu-latest-x64-8x'
 528              fallback-runner: 'ubuntu-latest'
 529              timeout-minutes: 180
 530              file-env: './ci/test/00_setup_env_native_fuzz_with_msan.sh'
 531  
 532            - name: 'MSan'
 533              warp-runner: 'warp-ubuntu-latest-x64-16x'
 534              fallback-runner: 'ubuntu-latest'
 535              timeout-minutes: 120
 536              file-env: './ci/test/00_setup_env_native_msan.sh'
 537  
 538            - name: 'riscv32 bare metal, static libbitcoin_consensus'
 539              warp-runner: 'warp-ubuntu-latest-x64-8x'
 540              fallback-runner: 'ubuntu-latest'
 541              timeout-minutes: 120
 542              file-env: './ci/test/00_setup_env_riscv_bare_cross.sh'
 543  
 544      steps:
 545        - *ANNOTATION_PR_NUMBER
 546  
 547        - *CHECKOUT
 548  
 549        - name: Configure environment
 550          uses: ./.github/actions/configure-environment
 551  
 552        - name: Restore caches
 553          id: restore-cache
 554          uses: ./.github/actions/cache/restore
 555          with:
 556            provider: ${{ matrix.provider || (github.repository == 'bitcoin/bitcoin' && 'warp' || 'gha') }}
 557  
 558        - name: Configure Docker
 559          uses: ./.github/actions/configure-docker
 560          with:
 561            provider: ${{ matrix.provider || (github.repository == 'bitcoin/bitcoin' && 'warp' || 'gha') }}
 562  
 563        - name: Clear unnecessary files
 564          if: ${{ github.repository != 'bitcoin/bitcoin' || matrix.provider == 'gha' }} # Only needed on GHA runners
 565          uses: ./.github/actions/clear-files
 566  
 567        - name: Enable bpfcc script
 568          if: ${{ env.CONTAINER_NAME == 'ci_native_asan' }}
 569          # In the image build step, no external environment variables are available,
 570          # so any settings will need to be written to the settings env file:
 571          run: sed -i "s|\${INSTALL_BCC_TRACING_TOOLS}|true|g" ./ci/test/00_setup_env_native_asan.sh
 572  
 573        - name: Set mmap_rnd_bits
 574          if: ${{ env.CONTAINER_NAME == 'ci_native_tsan' || env.CONTAINER_NAME == 'ci_native_msan' || env.CONTAINER_NAME == 'ci_native_fuzz_msan' }}
 575          # Prevents crashes due to high ASLR entropy
 576          run: sudo sysctl -w vm.mmap_rnd_bits=28
 577  
 578        - name: CI script
 579          run: ./ci/test_run_all.sh
 580  
 581        - name: Save caches
 582          uses: ./.github/actions/cache/save
 583          with:
 584            provider: ${{ matrix.provider || (github.repository == 'bitcoin/bitcoin' && 'warp' || 'gha') }}
 585  
 586    lint:
 587      name: 'lint'
 588      runs-on: ${{ github.repository == 'bitcoin/bitcoin' && 'warp-ubuntu-latest-x64-2x' || 'ubuntu-latest' }}
 589      if: ${{ vars.SKIP_BRANCH_PUSH != 'true' || github.event_name == 'pull_request' }}
 590      timeout-minutes: 20
 591      env:
 592        CONTAINER_NAME: "bitcoin-linter"
 593      steps:
 594        - *ANNOTATION_PR_NUMBER
 595  
 596        - name: Checkout
 597          uses: actions/checkout@v6
 598          with:
 599            ref: *CHECKOUT_REF_TMPL
 600            fetch-depth: 0
 601  
 602        - name: Configure Docker
 603          uses: ./.github/actions/configure-docker
 604          with:
 605            provider: ${{ github.repository == 'bitcoin/bitcoin' && 'warp' || 'gha' }}
 606  
 607        - name: CI script
 608          run: |
 609            git worktree add ../lint-worktree HEAD
 610            ../lint-worktree/ci/lint.py
 611