From d8ad667f943b77b42ef28a2f316dc7831c65ccec Mon Sep 17 00:00:00 2001 From: will Date: Sat, 26 Jul 2025 09:41:10 +0100 Subject: [PATCH 01/30] ci: add configure environment action Github-Pull: #32989 Rebased-From: b8fcc9fcbcd --- .../actions/configure-environment/action.yml | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/actions/configure-environment/action.yml diff --git a/.github/actions/configure-environment/action.yml b/.github/actions/configure-environment/action.yml new file mode 100644 index 00000000000..aae5016bdce --- /dev/null +++ b/.github/actions/configure-environment/action.yml @@ -0,0 +1,27 @@ +name: 'Configure environment' +description: 'Configure CI, cache and container name environment variables' +runs: + using: 'composite' + steps: + - name: Set CI and cache directories + shell: bash + run: | + echo "BASE_ROOT_DIR=${{ runner.temp }}" >> "$GITHUB_ENV" + echo "BASE_BUILD_DIR=${{ runner.temp }}/build" >> "$GITHUB_ENV" + echo "CCACHE_DIR=${{ runner.temp }}/ccache_dir" >> $GITHUB_ENV + echo "DEPENDS_DIR=${{ runner.temp }}/depends" >> "$GITHUB_ENV" + echo "BASE_CACHE=${{ runner.temp }}/depends/built" >> $GITHUB_ENV + echo "SOURCES_PATH=${{ runner.temp }}/depends/sources" >> $GITHUB_ENV + echo "PREVIOUS_RELEASES_DIR=${{ runner.temp }}/previous_releases" >> $GITHUB_ENV + + - name: Set cache hashes + shell: bash + run: | + echo "DEPENDS_HASH=$(git ls-tree HEAD depends "ci/test/$FILE_ENV" | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV + echo "PREVIOUS_RELEASES_HASH=$(git ls-tree HEAD test/get_previous_releases.py | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV + + - name: Get container name + shell: bash + run: | + source $FILE_ENV + echo "CONTAINER_NAME=$CONTAINER_NAME" >> "$GITHUB_ENV" From 8d6d70f5555cd9ac75b499ff031ab8b1410d59f3 Mon Sep 17 00:00:00 2001 From: will Date: Mon, 16 Jun 2025 20:02:20 +0100 Subject: [PATCH 02/30] ci: add caching actions Github-Pull: #32989 Rebased-From: b232b0fa5e9 Add "Restore" and "Save" caching actions. These actions reduce boilerplate in the main ci.yml configuration file. These actions are implemented so that caches will be saved on `push` only. When a pull request is opened it will cache hit on the caches from the lastest push, or in the case of depends will hit on any matching depends hash, falling back to partial matches. Depends caches are hashed using `$(git ls-tree HEAD depends "ci/test/$FILE_ENV" | sha256sum | cut -d' ' -f1)` and this hash is passed in as an input to the actions. This means we direct cache hit in cases where depends would not be re-built, otherwise falling back to a partial match. Previous releases cache is hashed similarly to depends, but using the test/get_previous_releases.py file. The cirruslabs cache action will fallback transparently to GitHub's cache in the case that the job is not being run on a Cirrus Runner, making these compatible with running on forks (on free GH hardware). --- .github/actions/restore-caches/action.yml | 47 +++++++++++++++++++++++ .github/actions/save-caches/action.yml | 39 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 .github/actions/restore-caches/action.yml create mode 100644 .github/actions/save-caches/action.yml diff --git a/.github/actions/restore-caches/action.yml b/.github/actions/restore-caches/action.yml new file mode 100644 index 00000000000..8dc35d4902e --- /dev/null +++ b/.github/actions/restore-caches/action.yml @@ -0,0 +1,47 @@ +name: 'Restore Caches' +description: 'Restore ccache, depends sources, and built depends caches' +runs: + using: 'composite' + steps: + - name: Restore Ccache cache + id: ccache-cache + uses: cirruslabs/cache/restore@v4 + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-${{ env.CONTAINER_NAME }}-${{ github.run_id }} + restore-keys: | + ccache-${{ env.CONTAINER_NAME }}- + + - name: Restore depends sources cache + id: depends-sources + uses: cirruslabs/cache/restore@v4 + with: + path: ${{ env.SOURCES_PATH }} + key: depends-sources-${{ env.CONTAINER_NAME }}-${{ env.DEPENDS_HASH }} + restore-keys: | + depends-sources-${{ env.CONTAINER_NAME }}- + + - name: Restore built depends cache + id: depends-built + uses: cirruslabs/cache/restore@v4 + with: + path: ${{ env.BASE_CACHE }} + key: depends-built-${{ env.CONTAINER_NAME }}-${{ env.DEPENDS_HASH }} + restore-keys: | + depends-built-${{ env.CONTAINER_NAME }}- + + - name: Restore previous releases cache + id: previous-releases + uses: cirruslabs/cache/restore@v4 + with: + path: ${{ env.PREVIOUS_RELEASES_DIR }} + key: previous-releases-${{ env.CONTAINER_NAME }}-${{ env.PREVIOUS_RELEASES_HASH }} + restore-keys: | + previous-releases-${{ env.CONTAINER_NAME }}- + + - name: export cache hits + shell: bash + run: | + echo "depends-sources-cache-hit=${{ steps.depends-sources.outputs.cache-hit }}" >> $GITHUB_ENV + echo "depends-built-cache-hit=${{ steps.depends-built.outputs.cache-hit }}" >> $GITHUB_ENV + echo "previous-releases-cache-hit=${{ steps.previous-releases.outputs.cache-hit }}" >> $GITHUB_ENV diff --git a/.github/actions/save-caches/action.yml b/.github/actions/save-caches/action.yml new file mode 100644 index 00000000000..0e3b31246c6 --- /dev/null +++ b/.github/actions/save-caches/action.yml @@ -0,0 +1,39 @@ +name: 'Save Caches' +description: 'Save ccache, depends sources, and built depends caches' +runs: + using: 'composite' + steps: + - name: debug cache hit inputs + shell: bash + run: | + echo "depends sources direct cache hit to primary key: ${{ env.depends-sources-cache-hit }}" + echo "depends built direct cache hit to primary key: ${{ env.depends-built-cache-hit }}" + echo "previous releases direct cache hit to primary key: ${{ env.previous-releases-cache-hit }}" + + - name: Save Ccache cache + uses: cirruslabs/cache/save@v4 + if: ${{ (github.event_name == 'push') && (github.ref_name == github.event.repository.default_branch) }} + with: + path: ${{ env.CCACHE_DIR }} + key: ccache-${{ env.CONTAINER_NAME }}-${{ github.run_id }} + + - name: Save depends sources cache + uses: cirruslabs/cache/save@v4 + if: ${{ (github.event_name == 'push') && (github.ref_name == github.event.repository.default_branch) && (env.depends-sources-cache-hit != 'true') }} + with: + path: ${{ env.SOURCES_PATH }} + key: depends-sources-${{ env.CONTAINER_NAME }}-${{ env.DEPENDS_HASH }} + + - name: Save built depends cache + uses: cirruslabs/cache/save@v4 + if: ${{ (github.event_name == 'push') && (github.ref_name == github.event.repository.default_branch) && (env.depends-built-cache-hit != 'true' )}} + with: + path: ${{ env.BASE_CACHE }} + key: depends-built-${{ env.CONTAINER_NAME }}-${{ env.DEPENDS_HASH }} + + - name: Save previous releases cache + uses: cirruslabs/cache/save@v4 + if: ${{ (github.event_name == 'push') && (github.ref_name == github.event.repository.default_branch) && (env.previous-releases-cache-hit != 'true' )}} + with: + path: ${{ env.PREVIOUS_RELEASES_DIR }} + key: previous-releases-${{ env.CONTAINER_NAME }}-${{ env.PREVIOUS_RELEASES_HASH }} From 270191c3c0e51cdd75d5b6eaaeeaae0b6e0ed3b9 Mon Sep 17 00:00:00 2001 From: will Date: Mon, 28 Jul 2025 16:05:32 +0100 Subject: [PATCH 03/30] ci: add REPO_USE_CIRRUS_RUNNERS Github-Pull: #32989 Rebased-From: 33ba073df7a If set, Cirrus runners will be used on pushes to, and pull requests against, this repository. Forks can set this if they have their own cirrus runners. --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7961c3c9005..ea08ea59185 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,7 @@ concurrency: env: 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 MAKEJOBS: '-j10' + REPO_USE_CIRRUS_RUNNERS: 'bitcoin/bitcoin' # Use cirrus runners and cache for this repo, instead of falling back to the slow GHA runners jobs: test-each-commit: From f8cb31d0647b824190281d1e54c75972272bd025 Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:37:26 +0100 Subject: [PATCH 04/30] ci: add configure-docker action Github-Pull: #32989 Rebased-From: fdf64e55324 Another action to reduce boilerplate in the main ci.yml file. This action will set up a docker builder compatible with caching build layers to a container registry using the `gha` build driver. It will then configure the docker build cache args. --- .github/actions/configure-docker/action.yml | 52 +++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/actions/configure-docker/action.yml diff --git a/.github/actions/configure-docker/action.yml b/.github/actions/configure-docker/action.yml new file mode 100644 index 00000000000..c78df86b6cf --- /dev/null +++ b/.github/actions/configure-docker/action.yml @@ -0,0 +1,52 @@ +name: 'Configure Docker' +description: 'Set up Docker build driver and configure build cache args' +inputs: + use-cirrus: + description: 'Use cirrus cache' + required: true +runs: + using: 'composite' + steps: + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + # Use host network to allow access to cirrus gha cache running on the host + driver-opts: | + network=host + + # This is required to allow buildkit to access the actions cache + - name: Expose actions cache variables + uses: actions/github-script@v6 + with: + script: | + core.exportVariable('ACTIONS_CACHE_URL', process.env['ACTIONS_CACHE_URL']) + core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env['ACTIONS_RUNTIME_TOKEN']) + + - name: Construct docker build cache args + shell: bash + run: | + # Configure docker build cache backend + # + # On forks the gha cache will work but will use Github's cache backend. + # Docker will check for variables $ACTIONS_CACHE_URL, $ACTIONS_RESULTS_URL and $ACTIONS_RUNTIME_TOKEN + # which are set automatically when running on GitHub infra: https://docs.docker.com/build/cache/backends/gha/#synopsis + + # Use cirrus cache host + if [[ ${{ inputs.use-cirrus }} == 'true' ]]; then + url_args="url=${CIRRUS_CACHE_HOST},url_v2=${CIRRUS_CACHE_HOST}" + else + url_args="" + fi + + # Always optimistically --cache‑from in case a cache blob exists + args=(--cache-from "type=gha${url_args:+,${url_args}},scope=${CONTAINER_NAME}") + + # If this is a push to the default branch, also add --cache‑to to save the cache + if [[ ${{ github.event_name }} == "push" && ${{ github.ref_name }} == ${{ github.event.repository.default_branch }} ]]; then + args+=(--cache-to "type=gha${url_args:+,${url_args}},mode=max,ignore-error=true,scope=${CONTAINER_NAME}") + fi + + # Always `--load` into docker images (needed when using the `docker-container` build driver). + args+=(--load) + + echo "DOCKER_BUILD_CACHE_ARG=${args[*]}" >> $GITHUB_ENV From f6ccd895df85ab6642ef2c5dcc336acc5990f4fd Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 05/30] ci: use buildx in ci Github-Pull: #32989 Rebased-From: 94a09325475 This rebase also includes part of e87429a2d0f23eb59526d335844fa5ff5b50b21f adding `$DOCKER_BUILD_CACHE_ARG \` to the `docker build` command. Using buildx is required to properly load the correct driver, for use with registry caching. Neither build, nor BUILDKIT=1 currently do this properly. Use of `docker buildx build` is compatible with podman. --- ci/test/02_run_container.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ci/test/02_run_container.sh b/ci/test/02_run_container.sh index afd447c347f..9255c27beb8 100755 --- a/ci/test/02_run_container.sh +++ b/ci/test/02_run_container.sh @@ -17,11 +17,15 @@ if [ -z "$DANGER_RUN_CI_ON_HOST" ]; then docker run --rm "${CI_IMAGE_NAME_TAG}" bash -c "env | grep --extended-regexp '^(HOME|PATH|USER)='" | tee --append "/tmp/env-$USER-$CONTAINER_NAME" echo "Creating $CI_IMAGE_NAME_TAG container to run in" - DOCKER_BUILDKIT=1 docker build \ + # Use buildx unconditionally + # Using buildx is required to properly load the correct driver, for use with registry caching. Neither build, nor BUILDKIT=1 currently do this properly + # shellcheck disable=SC2086 + docker buildx build \ --file "${BASE_READ_ONLY_DIR}/ci/test_imagefile" \ --build-arg "CI_IMAGE_NAME_TAG=${CI_IMAGE_NAME_TAG}" \ --build-arg "FILE_ENV=${FILE_ENV}" \ --label="${CI_IMAGE_LABEL}" \ + $DOCKER_BUILD_CACHE_ARG \ --tag="${CONTAINER_NAME}" \ "${BASE_READ_ONLY_DIR}" From 30efc95aecb1602cd01547b1f9dde2382358d5ca Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 06/30] ci: have base install run in right dir Github-Pull: #32989 Rebased-From: 9c2b96e0d03 This sets the build dir at build time so that Apple SDK gets installed in the correct/expected location for the runtime to find it. Co-authored-by: Max Edwards --- ci/test/02_run_container.sh | 1 + ci/test_imagefile | 3 +++ 2 files changed, 4 insertions(+) diff --git a/ci/test/02_run_container.sh b/ci/test/02_run_container.sh index 9255c27beb8..db41c96ce26 100755 --- a/ci/test/02_run_container.sh +++ b/ci/test/02_run_container.sh @@ -24,6 +24,7 @@ if [ -z "$DANGER_RUN_CI_ON_HOST" ]; then --file "${BASE_READ_ONLY_DIR}/ci/test_imagefile" \ --build-arg "CI_IMAGE_NAME_TAG=${CI_IMAGE_NAME_TAG}" \ --build-arg "FILE_ENV=${FILE_ENV}" \ + --build-arg "BASE_ROOT_DIR=${BASE_ROOT_DIR}" \ --label="${CI_IMAGE_LABEL}" \ $DOCKER_BUILD_CACHE_ARG \ --tag="${CONTAINER_NAME}" \ diff --git a/ci/test_imagefile b/ci/test_imagefile index f8b5eea1c88..224141b138f 100644 --- a/ci/test_imagefile +++ b/ci/test_imagefile @@ -10,6 +10,9 @@ FROM ${CI_IMAGE_NAME_TAG} ARG FILE_ENV ENV FILE_ENV=${FILE_ENV} +ARG BASE_ROOT_DIR +ENV BASE_ROOT_DIR=${BASE_ROOT_DIR} + COPY ./ci/retry/retry /usr/bin/retry COPY ./ci/test/00_setup_env.sh ./${FILE_ENV} ./ci/test/01_base_install.sh /ci_container_base/ci/test/ From 82cfddbc9ae710a1dc135315049b1da5c8344109 Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 07/30] ci: add Cirrus cache host Github-Pull: #32989 Rebased-From: 020069e6b71 Whilst the action cirruslabs/actions/cache will automatically set this host, the docker `gha` build cache backend will not be aware of it. Set the value here, which will later be used in the docker build args to enable docker build cache on the cirrus cache. --- .github/workflows/ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ea08ea59185..ad6b4d2c005 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,7 @@ concurrency: env: 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 + CIRRUS_CACHE_HOST: http://127.0.0.1:12321/ # When using Cirrus Runners this host can be used by the docker `gha` build cache type. MAKEJOBS: '-j10' REPO_USE_CIRRUS_RUNNERS: 'bitcoin/bitcoin' # Use cirrus runners and cache for this repo, instead of falling back to the slow GHA runners From 5538ce4f320894fbffed9dcaec574f8a01b12b3b Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 08/30] ci: add job to determine runner type Github-Pull: #32989 Rebased-From: cc1735d7771 To remove multiple occurances of the respository name, against which we compare `${{ github.repository }}` to check if we should use Cirrus Runners, introduce a helper job which can check a single environment variable and output this as an input to subsequent jobs. Forks can maintain a trivial patch of their repo name against the `REPO_USE_CIRRUS_RUNNERS` variable in ci.yml if they have Cirrus Runners of their own, which will then enable cache actions and docker build cache to use Cirrus Cache. It's not possible to use `${{ env.USE_CIRRUS_RUNNERS }}` in the `runs-on:` directive as the context is not supported by GitHub. If it was, this job would no longer be necessary. --- .github/workflows/ci.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ad6b4d2c005..a61c25ac367 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,6 +24,22 @@ env: REPO_USE_CIRRUS_RUNNERS: 'bitcoin/bitcoin' # Use cirrus runners and cache for this repo, instead of falling back to the slow GHA runners jobs: + runners: + name: 'determine runners' + runs-on: ubuntu-latest + outputs: + use-cirrus-runners: ${{ steps.runners.outputs.use-cirrus-runners }} + steps: + - id: runners + run: | + if [[ "${REPO_USE_CIRRUS_RUNNERS}" == "${{ github.repository }}" ]]; then + echo "use-cirrus-runners=true" >> "$GITHUB_OUTPUT" + echo "::notice title=Runner Selection::Using Cirrus Runners" + else + echo "use-cirrus-runners=false" >> "$GITHUB_OUTPUT" + echo "::notice title=Runner Selection::Using GitHub-hosted runners" + fi + test-each-commit: name: 'test each commit' runs-on: ubuntu-24.04 From bb455c95940e4548f418d53e0083a060df2a7b14 Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 09/30] ci: port arm job Github-Pull: #32989 Rebased-From: f253031cb8e Co-authored-by: Max Edwards --- .github/workflows/ci.yml | 43 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a61c25ac367..ad979e430b4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -371,3 +371,46 @@ jobs: path: ${{ env.CCACHE_DIR }} # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#update-a-cache key: ${{ github.job }}-ccache-${{ github.run_id }} + + ci-matrix: + name: ${{ matrix.name }} + needs: runners + runs-on: ${{ needs.runners.outputs.use-cirrus-runners == 'true' && matrix.cirrus-runner || matrix.fallback-runner }} + if: ${{ vars.SKIP_BRANCH_PUSH != 'true' || github.event_name == 'pull_request' }} + timeout-minutes: ${{ matrix.timeout-minutes }} + + env: + DANGER_CI_ON_HOST_FOLDERS: 1 + FILE_ENV: ${{ matrix.file-env }} + + strategy: + fail-fast: false + matrix: + include: + - name: 'ARM, unit tests, no functional tests' + cirrus-runner: 'ubuntu-24.04-arm' # Cirrus' Arm runners are Apple (with virtual Linux aarch64), which doesn't support 32-bit mode + fallback-runner: 'ubuntu-24.04-arm' + timeout-minutes: 120 + file-env: './ci/test/00_setup_env_arm.sh' + + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Configure environment + uses: ./.github/actions/configure-environment + + - name: Restore caches + id: restore-cache + uses: ./.github/actions/restore-caches + + - name: Configure Docker + uses: ./.github/actions/configure-docker + with: + use-cirrus: ${{ needs.runners.outputs.use-cirrus-runners }} + + - name: CI script + run: ./ci/test_run_all.sh + + - name: Save caches + uses: ./.github/actions/save-caches From 61bb5180d512cb1de993ee8bc6b93fb4481b9730 Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 10/30] ci: update asan-lsan-ubsan Github-Pull: #32989 Rebased-From: 884251441bb Co-authored-by: Max Edwards --- .github/workflows/ci.yml | 51 ++++++++++------------------------------ 1 file changed, 12 insertions(+), 39 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ad979e430b4..bb33be3af99 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -329,49 +329,10 @@ jobs: shell: cmd run: py -3 test\fuzz\test_runner.py --par %NUMBER_OF_PROCESSORS% --loglevel DEBUG %RUNNER_TEMP%\qa-assets\fuzz_seed_corpus - asan-lsan-ubsan-integer-no-depends-usdt: - name: 'ASan + LSan + UBSan + integer, no depends, USDT' - runs-on: ubuntu-24.04 # has to match container in ci/test/00_setup_env_native_asan.sh for tracing tools - # No need to run on the read-only mirror, unless it is a PR. - if: github.repository != 'bitcoin-core/gui' || github.event_name == 'pull_request' - timeout-minutes: 120 - env: - FILE_ENV: "./ci/test/00_setup_env_native_asan.sh" - DANGER_CI_ON_HOST_CACHE_FOLDERS: 1 - steps: - - name: Checkout - uses: actions/checkout@v4 - - - name: Set Ccache directory - run: echo "CCACHE_DIR=${RUNNER_TEMP}/ccache_dir" >> "$GITHUB_ENV" - - - name: Set base root directory - run: echo "BASE_ROOT_DIR=${RUNNER_TEMP}" >> "$GITHUB_ENV" - - - name: Restore Ccache cache - id: ccache-cache - uses: actions/cache/restore@v4 - with: - path: ${{ env.CCACHE_DIR }} - key: ${{ github.job }}-ccache-${{ github.run_id }} - restore-keys: ${{ github.job }}-ccache- - - - name: Enable bpfcc script - # In the image build step, no external environment variables are available, - # so any settings will need to be written to the settings env file: - run: sed -i "s|\${INSTALL_BCC_TRACING_TOOLS}|true|g" ./ci/test/00_setup_env_native_asan.sh - name: CI script run: ./ci/test_run_all.sh - - name: Save Ccache cache - uses: actions/cache/save@v4 - if: github.event_name != 'pull_request' && steps.ccache-cache.outputs.cache-hit != 'true' - with: - path: ${{ env.CCACHE_DIR }} - # https://github.com/actions/cache/blob/main/tips-and-workarounds.md#update-a-cache - key: ${{ github.job }}-ccache-${{ github.run_id }} - ci-matrix: name: ${{ matrix.name }} needs: runners @@ -393,6 +354,12 @@ jobs: timeout-minutes: 120 file-env: './ci/test/00_setup_env_arm.sh' + - name: 'ASan + LSan + UBSan + integer, no depends, USDT' + cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-lg' # has to match container in ci/test/00_setup_env_native_asan.sh for tracing tools + fallback-runner: 'ubuntu-24.04' + timeout-minutes: 120 + file-env: './ci/test/00_setup_env_native_asan.sh' + steps: - name: Checkout uses: actions/checkout@v5 @@ -409,6 +376,12 @@ jobs: with: use-cirrus: ${{ needs.runners.outputs.use-cirrus-runners }} + - name: Enable bpfcc script + if: ${{ env.CONTAINER_NAME == 'ci_native_asan' }} + # In the image build step, no external environment variables are available, + # so any settings will need to be written to the settings env file: + run: sed -i "s|\${INSTALL_BCC_TRACING_TOOLS}|true|g" ./ci/test/00_setup_env_native_asan.sh + - name: CI script run: ./ci/test_run_all.sh From 8c9048f4fccb7e48778f5b5134a9e2e18e9e3ba9 Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 11/30] ci: force reinstall of kernel headers in asan Github-Pull: #32989 Rebased-From: 2c990d84a3d When using hosted runners in combination with cached docker images, there is the possibility that the host runner image is updated, rendering the linux-headers package (stored in the cached docker image) incompatible. Fix this by doing a re-install of the headers package in 03_test_script.sh. If the underlying runner kernel has not changed thie has no effect, but prevents the job from failing if it has. --- ci/test/03_test_script.sh | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/ci/test/03_test_script.sh b/ci/test/03_test_script.sh index 1d7a9d76dbb..5920f7e9808 100755 --- a/ci/test/03_test_script.sh +++ b/ci/test/03_test_script.sh @@ -25,6 +25,14 @@ fi echo "Free disk space:" df -h +# We force an install of linux-headers again here via $PACKAGES to fix any +# kernel mismatch between a cached docker image and the underlying host. +# This can happen occasionally on hosted runners if the runner image is updated. +if [[ "$CONTAINER_NAME" == "ci_native_asan" ]]; then + $CI_RETRY_EXE apt-get update + ${CI_RETRY_EXE} bash -c "apt-get install --no-install-recommends --no-upgrade -y $PACKAGES" +fi + # What host to compile for. See also ./depends/README.md # Tests that need cross-compilation export the appropriate HOST. # Tests that run natively guess the host From 6237cd537d4ed03fbeda5c9702c87a21f6a32c17 Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 12/30] ci: port mac-cross-gui-notests Github-Pull: #32989 Rebased-From: 9c2514de534 Co-authored-by: Max Edwards --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb33be3af99..c8b5c6f9622 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -360,6 +360,12 @@ jobs: timeout-minutes: 120 file-env: './ci/test/00_setup_env_native_asan.sh' + - name: 'macOS-cross, gui, no tests' + cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-sm' + fallback-runner: 'ubuntu-24.04' + timeout-minutes: 120 + file-env: './ci/test/00_setup_env_mac_cross.sh' + steps: - name: Checkout uses: actions/checkout@v5 From f61cb6be58d7798ded7441b0076e21bfe887304c Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 13/30] ci: port nowallet-libbitcoinkernel Github-Pull: #32989 Rebased-From: 2a00b12d73b Co-authored-by: Max Edwards --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c8b5c6f9622..6371031dc3b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -366,6 +366,12 @@ jobs: timeout-minutes: 120 file-env: './ci/test/00_setup_env_mac_cross.sh' + - name: 'No wallet, libbitcoinkernel' + cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md' + fallback-runner: 'ubuntu-24.04' + timeout-minutes: 120 + file-env: './ci/test/00_setup_env_native_nowallet_libbitcoinkernel.sh' + steps: - name: Checkout uses: actions/checkout@v5 From 0fc3fd1eb5b8ee1fb07bffc9ac99a3c14187f387 Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 14/30] ci: port i686-multiprocess-DEBUG Github-Pull: #32989 Rebased-From: f2068f26c12 Co-authored-by: Max Edwards --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6371031dc3b..1b139eb0e02 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -372,6 +372,12 @@ jobs: timeout-minutes: 120 file-env: './ci/test/00_setup_env_native_nowallet_libbitcoinkernel.sh' + - name: 'i686, multiprocess, DEBUG' + cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md' + fallback-runner: 'ubuntu-24.04' + timeout-minutes: 120 + file-env: './ci/test/00_setup_env_i686_multiprocess.sh' + steps: - name: Checkout uses: actions/checkout@v5 From 96cd28f1461b461e6cf7823c1d64806ef46a40c1 Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 15/30] ci: port fuzzer-address-undefined-integer-nodepends Github-Pull: #32989 Rebased-From: 341196d75c3 Co-authored-by: Max Edwards --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1b139eb0e02..acfcb6edd6e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -378,6 +378,12 @@ jobs: timeout-minutes: 120 file-env: './ci/test/00_setup_env_i686_multiprocess.sh' + - name: 'fuzzer,address,undefined,integer, no depends' + cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-lg' + fallback-runner: 'ubuntu-24.04' + timeout-minutes: 240 + file-env: './ci/test/00_setup_env_native_fuzz.sh' + steps: - name: Checkout uses: actions/checkout@v5 From fa259b4e72071a41d0682b87aba7f43b313ce854 Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 16/30] ci: port previous-releases-depends-debug Github-Pull: #32989 Rebased-From: 58e38c3a042 Co-authored-by: Max Edwards --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index acfcb6edd6e..e299bbd17a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -384,6 +384,12 @@ jobs: timeout-minutes: 240 file-env: './ci/test/00_setup_env_native_fuzz.sh' + - name: 'previous releases, depends DEBUG' + cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md' + fallback-runner: 'ubuntu-24.04' + timeout-minutes: 120 + file-env: './ci/test/00_setup_env_native_previous_releases.sh' + steps: - name: Checkout uses: actions/checkout@v5 From c2c69cd6ec90670e290e5cc58f02d6bc3443011c Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 17/30] ci: port 32-bit-centos-dash-gui Github-Pull: #32989 Rebased-From: 549074bc643 Co-authored-by: Max Edwards --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e299bbd17a9..94b349d86c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -390,6 +390,12 @@ jobs: timeout-minutes: 120 file-env: './ci/test/00_setup_env_native_previous_releases.sh' + - name: '32bit CentOS, dash, gui' + cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-lg' + fallback-runner: 'ubuntu-24.04' + timeout-minutes: 120 + file-env: './ci/test/00_setup_env_i686_centos.sh' + steps: - name: Checkout uses: actions/checkout@v5 From 49ff9d7e6e1395755e8ecd692b6529d7f02e4b1f Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 18/30] ci: port tidy Github-Pull: #32989 Rebased-From: bf7d5364527 Co-authored-by: Max Edwards --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 94b349d86c7..f17077276fc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -396,6 +396,12 @@ jobs: timeout-minutes: 120 file-env: './ci/test/00_setup_env_i686_centos.sh' + - name: 'tidy' + cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md' + fallback-runner: 'ubuntu-24.04' + timeout-minutes: 120 + file-env: './ci/test/00_setup_env_native_tidy.sh' + steps: - name: Checkout uses: actions/checkout@v5 From cf18a500d7742c65f5c45bd5e4504ce03feceb30 Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 19/30] ci: port tsan-depends-gui Github-Pull: #32989 Rebased-From: 9bbae61e3b4 Co-authored-by: Max Edwards --- .github/workflows/ci.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f17077276fc..20ca56a5f10 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -402,6 +402,12 @@ jobs: timeout-minutes: 120 file-env: './ci/test/00_setup_env_native_tidy.sh' + - name: 'TSan, depends, gui' + cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md' + fallback-runner: 'ubuntu-24.04' + timeout-minutes: 120 + file-env: './ci/test/00_setup_env_native_tsan.sh' + steps: - name: Checkout uses: actions/checkout@v5 @@ -424,6 +430,11 @@ jobs: # so any settings will need to be written to the settings env file: run: sed -i "s|\${INSTALL_BCC_TRACING_TOOLS}|true|g" ./ci/test/00_setup_env_native_asan.sh + - name: Set mmap_rnd_bits + if: ${{ env.CONTAINER_NAME == 'ci_native_tsan' }} + # Prevents crashes due to high ASLR entropy + run: sudo sysctl -w vm.mmap_rnd_bits=28 + - name: CI script run: ./ci/test_run_all.sh From 4b3468389be4762aadbd37f97a949ba20a9444ff Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 20/30] ci: port msan-depends Github-Pull: #32989 Rebased-From: d290a8e6eab Co-authored-by: Max Edwards --- .github/workflows/ci.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 20ca56a5f10..b4a0ec7e3d6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -408,6 +408,12 @@ jobs: timeout-minutes: 120 file-env: './ci/test/00_setup_env_native_tsan.sh' + - name: 'MSan, depends' + cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-lg' + fallback-runner: 'ubuntu-24.04' + timeout-minutes: 120 + file-env: './ci/test/00_setup_env_native_msan.sh' + steps: - name: Checkout uses: actions/checkout@v5 @@ -431,7 +437,7 @@ jobs: run: sed -i "s|\${INSTALL_BCC_TRACING_TOOLS}|true|g" ./ci/test/00_setup_env_native_asan.sh - name: Set mmap_rnd_bits - if: ${{ env.CONTAINER_NAME == 'ci_native_tsan' }} + if: ${{ env.CONTAINER_NAME == 'ci_native_tsan' || env.CONTAINER_NAME == 'ci_native_msan' }} # Prevents crashes due to high ASLR entropy run: sudo sysctl -w vm.mmap_rnd_bits=28 From 99411458b4be92bb2107b9a1b73c5530d79fe9d6 Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 21/30] ci: port lint Github-Pull: #32989 Rebased-From: bc41848d00f Co-authored-by: Max Edwards --- .github/workflows/ci.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b4a0ec7e3d6..effdff565f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -446,3 +446,32 @@ jobs: - name: Save caches uses: ./.github/actions/save-caches + + lint: + name: 'lint' + needs: runners + runs-on: ${{ needs.runners.outputs.use-cirrus-runners == 'true' && 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-sm' || 'ubuntu-24.04' }} + if: ${{ vars.SKIP_BRANCH_PUSH != 'true' || github.event_name == 'pull_request' }} + timeout-minutes: 20 + env: + CONTAINER_NAME: "bitcoin-linter" + steps: + - name: Checkout + uses: actions/checkout@v5 + with: + fetch-depth: 0 + + - name: Configure Docker + uses: ./.github/actions/configure-docker + with: + use-cirrus: ${{ needs.runners.outputs.use-cirrus-runners }} + + - name: CI script + run: | + set -o xtrace + docker buildx build -t "$CONTAINER_NAME" $DOCKER_BUILD_CACHE_ARG --file "./ci/lint_imagefile" . + CIRRUS_PR_FLAG="" + if [ "${{ github.event_name }}" = "pull_request" ]; then + CIRRUS_PR_FLAG="-e CIRRUS_PR=1" + fi + docker run --rm $CIRRUS_PR_FLAG -v "$(pwd)":/bitcoin "$CONTAINER_NAME" From 8ab684eeb72590090393be5ebbbb79a421603577 Mon Sep 17 00:00:00 2001 From: will Date: Tue, 16 Sep 2025 14:10:07 +0100 Subject: [PATCH 22/30] ci: port win64-no_gui job --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index effdff565f1..aae5ed74723 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -354,6 +354,12 @@ jobs: timeout-minutes: 120 file-env: './ci/test/00_setup_env_arm.sh' + - name: 'Win64, unit tests, no gui tests, no functional tests' + cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md' + fallback-runner: 'ubuntu-24.04' + timeout-minutes: 120 + file-env: './ci/test/00_setup_env_win64.sh' + - name: 'ASan + LSan + UBSan + integer, no depends, USDT' cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-lg' # has to match container in ci/test/00_setup_env_native_asan.sh for tracing tools fallback-runner: 'ubuntu-24.04' From abaa128095e68178c0a1fb213a973f966fbf16cb Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 23/30] ci: remove .cirrus.yml Github-Pull: #32989 Rebased-From: 4393ffdd837 Removed as unused. --- .cirrus.yml | 217 ---------------------------------------------------- 1 file changed, 217 deletions(-) delete mode 100644 .cirrus.yml diff --git a/.cirrus.yml b/.cirrus.yml deleted file mode 100644 index f5874744b52..00000000000 --- a/.cirrus.yml +++ /dev/null @@ -1,217 +0,0 @@ -env: # Global defaults - CIRRUS_CLONE_DEPTH: 1 - PACKAGE_MANAGER_INSTALL: "apt-get update && apt-get install -y" - MAKEJOBS: "-j10" - TEST_RUNNER_PORT_MIN: "14000" # Must be larger than 12321, which is used for the http cache. See https://cirrus-ci.org/guide/writing-tasks/#http-cache - CI_FAILFAST_TEST_LEAVE_DANGLING: "1" # Cirrus CI does not care about dangling processes and setting this variable avoids killing the CI script itself on error - CCACHE_MAXSIZE: "200M" - CCACHE_DIR: "/tmp/ccache_dir" - CCACHE_NOHASHDIR: "1" # Debug info might contain a stale path if the build dir changes, but this is fine - -# A self-hosted machine(s) can be used via Cirrus CI. It can be configured with -# multiple users to run tasks in parallel. No sudo permission is required. -# -# https://cirrus-ci.org/guide/persistent-workers/ -# -# Generally, a persistent worker must run Ubuntu 23.04+ or Debian 12+. -# -# The following specific types should exist, with the following requirements: -# - small: For an x86_64 machine, recommended to have 2 CPUs and 8 GB of memory. -# - medium: For an x86_64 machine, recommended to have 4 CPUs and 16 GB of memory. -# - arm64: For an aarch64 machine, recommended to have 2 CPUs and 8 GB of memory. -# -# CI jobs for the latter configuration can be run on x86_64 hardware -# by installing qemu-user-static, which works out of the box with -# podman or docker. Background: https://stackoverflow.com/a/72890225/313633 -# -# The above machine types are matched to each task by their label. Refer to the -# Cirrus CI docs for more details. -# -# When a contributor maintains a fork of the repo, any pull request they make -# to their own fork, or to the main repository, will trigger two CI runs: -# one for the branch push and one for the pull request. -# This can be avoided by setting SKIP_BRANCH_PUSH=true as a custom env variable -# in Cirrus repository settings, accessible from -# https://cirrus-ci.com/github/my-organization/my-repository -# -# On machines that are persisted between CI jobs, RESTART_CI_DOCKER_BEFORE_RUN=1 -# ensures that previous containers and artifacts are cleared before each run. -# This requires installing Podman instead of Docker. -# -# Futhermore: -# - apt-get is required due to PACKAGE_MANAGER_INSTALL -# - podman-docker-4.1+ is required due to the bugfix in 4.1 -# (https://github.com/bitcoin/bitcoin/pull/21652#issuecomment-1657098200) -# - The ./ci/ dependencies (with cirrus-cli) should be installed. One-liner example -# for a single user setup with sudo permission: -# -# ``` -# apt update && apt install git screen python3 bash podman-docker curl -y && curl -L -o cirrus "https://github.com/cirruslabs/cirrus-cli/releases/latest/download/cirrus-linux-$(dpkg --print-architecture)" && mv cirrus /usr/local/bin/cirrus && chmod +x /usr/local/bin/cirrus -# ``` -# -# - There are no strict requirements on the hardware. Having fewer CPU threads -# than recommended merely causes the CI script to run slower. -# To avoid rare and intermittent OOM due to short memory usage spikes, -# it is recommended to add (and persist) swap: -# -# ``` -# fallocate -l 16G /swapfile_ci && chmod 600 /swapfile_ci && mkswap /swapfile_ci && swapon /swapfile_ci && ( echo '/swapfile_ci none swap sw 0 0' | tee -a /etc/fstab ) -# ``` -# -# - To register the persistent worker, open a `screen` session and run: -# -# ``` -# RESTART_CI_DOCKER_BEFORE_RUN=1 screen cirrus worker run --labels type=todo_fill_in_type --token todo_fill_in_token -# ``` - -# https://cirrus-ci.org/guide/tips-and-tricks/#sharing-configuration-between-tasks -filter_template: &FILTER_TEMPLATE - # Allow forks to specify SKIP_BRANCH_PUSH=true and skip CI runs when a branch is pushed, - # but still run CI when a PR is created. - # https://cirrus-ci.org/guide/writing-tasks/#conditional-task-execution - skip: $SKIP_BRANCH_PUSH == "true" && $CIRRUS_PR == "" - stateful: false # https://cirrus-ci.org/guide/writing-tasks/#stateful-tasks - -base_template: &BASE_TEMPLATE - << : *FILTER_TEMPLATE - merge_base_script: - # Unconditionally install git (used in fingerprint_script). - - git --version || bash -c "$PACKAGE_MANAGER_INSTALL git" - - if [ "$CIRRUS_PR" = "" ]; then exit 0; fi - - git fetch --depth=1 $CIRRUS_REPO_CLONE_URL "pull/${CIRRUS_PR}/merge" - - git checkout FETCH_HEAD # Use merged changes to detect silent merge conflicts - # Also, the merge commit is used to lint COMMIT_RANGE="HEAD~..HEAD" - -main_template: &MAIN_TEMPLATE - timeout_in: 120m # https://cirrus-ci.org/faq/#instance-timed-out - ci_script: - - ./ci/test_run_all.sh - -global_task_template: &GLOBAL_TASK_TEMPLATE - << : *BASE_TEMPLATE - << : *MAIN_TEMPLATE - -compute_credits_template: &CREDITS_TEMPLATE - # https://cirrus-ci.org/pricing/#compute-credits - # Only use credits for pull requests to the main repo - use_compute_credits: $CIRRUS_REPO_FULL_NAME == 'bitcoin/bitcoin' && $CIRRUS_PR != "" - -task: - name: 'lint' - << : *BASE_TEMPLATE - container: - image: debian:bookworm - cpu: 1 - memory: 1G - # For faster CI feedback, immediately schedule the linters - << : *CREDITS_TEMPLATE - test_runner_cache: - folder: "/lint_test_runner" - fingerprint_script: echo $CIRRUS_TASK_NAME $(git rev-parse HEAD:test/lint/test_runner) - python_cache: - folder: "/python_build" - fingerprint_script: cat .python-version /etc/os-release - unshallow_script: - - git fetch --unshallow --no-tags - lint_script: - - ./ci/lint_run_all.sh - -task: - name: 'tidy' - << : *GLOBAL_TASK_TEMPLATE - persistent_worker: - labels: - type: medium - env: - FILE_ENV: "./ci/test/00_setup_env_native_tidy.sh" - -task: - name: 'ARM, unit tests, no functional tests' - << : *GLOBAL_TASK_TEMPLATE - persistent_worker: - labels: - type: arm64 # Use arm64 worker to sidestep qemu and avoid a slow CI: https://github.com/bitcoin/bitcoin/pull/28087#issuecomment-1649399453 - env: - FILE_ENV: "./ci/test/00_setup_env_arm.sh" - -task: - name: 'Win64, unit tests, no gui tests, no functional tests' - << : *GLOBAL_TASK_TEMPLATE - persistent_worker: - labels: - type: small - env: - FILE_ENV: "./ci/test/00_setup_env_win64.sh" - -task: - name: '32-bit CentOS, dash, gui' - << : *GLOBAL_TASK_TEMPLATE - persistent_worker: - labels: - type: small - env: - FILE_ENV: "./ci/test/00_setup_env_i686_centos.sh" - -task: - name: 'previous releases, depends DEBUG' - << : *GLOBAL_TASK_TEMPLATE - persistent_worker: - labels: - type: small - env: - FILE_ENV: "./ci/test/00_setup_env_native_previous_releases.sh" - -task: - name: 'TSan, depends, gui' - << : *GLOBAL_TASK_TEMPLATE - persistent_worker: - labels: - type: medium - env: - FILE_ENV: "./ci/test/00_setup_env_native_tsan.sh" - -task: - name: 'MSan, depends' - << : *GLOBAL_TASK_TEMPLATE - persistent_worker: - labels: - type: small - timeout_in: 300m # Use longer timeout for the *rare* case where a full build (llvm + msan + depends + ...) needs to be done. - env: - FILE_ENV: "./ci/test/00_setup_env_native_msan.sh" - -task: - name: 'fuzzer,address,undefined,integer, no depends' - << : *GLOBAL_TASK_TEMPLATE - persistent_worker: - labels: - type: medium - env: - FILE_ENV: "./ci/test/00_setup_env_native_fuzz.sh" - -task: - name: 'multiprocess, i686, DEBUG' - << : *GLOBAL_TASK_TEMPLATE - persistent_worker: - labels: - type: medium - env: - FILE_ENV: "./ci/test/00_setup_env_i686_multiprocess.sh" - -task: - name: 'no wallet, libbitcoinkernel' - << : *GLOBAL_TASK_TEMPLATE - persistent_worker: - labels: - type: small - env: - FILE_ENV: "./ci/test/00_setup_env_native_nowallet_libbitcoinkernel.sh" - -task: - name: 'macOS-cross, gui, no tests' - << : *GLOBAL_TASK_TEMPLATE - persistent_worker: - labels: - type: small - env: - FILE_ENV: "./ci/test/00_setup_env_mac_cross.sh" From 1bfe9f56c3213e7c9c38fa065e04fce841779cdd Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 24/30] ci: dynamically match makejobs with cores Github-Pull: #32989 Rebased-From: 3f339e99e00 Previously jobs were running on a large multi-core server where 10 jobs as default made sense (or may even have been on the low side). Using hosted runners with fixed (and lower) numbers of vCPUs we should adapt compilation to match the number of cpus we have dynamically. This is cross-platform compatible with macos and linux only. --- .github/workflows/ci.yml | 1 - ci/test/00_setup_env.sh | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index aae5ed74723..a49d3d25afc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,6 @@ concurrency: env: 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 CIRRUS_CACHE_HOST: http://127.0.0.1:12321/ # When using Cirrus Runners this host can be used by the docker `gha` build cache type. - MAKEJOBS: '-j10' REPO_USE_CIRRUS_RUNNERS: 'bitcoin/bitcoin' # Use cirrus runners and cache for this repo, instead of falling back to the slow GHA runners jobs: diff --git a/ci/test/00_setup_env.sh b/ci/test/00_setup_env.sh index b9e6818afbc..1466e37b906 100755 --- a/ci/test/00_setup_env.sh +++ b/ci/test/00_setup_env.sh @@ -35,7 +35,7 @@ fi echo "Fallback to default values in env (if not yet set)" # The number of parallel jobs to pass down to make and test_runner.py -export MAKEJOBS=${MAKEJOBS:--j4} +export MAKEJOBS=${MAKEJOBS:--j$(if command -v nproc > /dev/null 2>&1; then nproc; else sysctl -n hw.logicalcpu; fi)} # Whether to prefer BusyBox over GNU utilities export USE_BUSY_BOX=${USE_BUSY_BOX:-false} From a0b6e2ae6b5c6fd7ca2be164f020cf6385c7f820 Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 25/30] doc: Detail configuration of hosted CI runners Github-Pull: #32989 Rebased-From: f4272844833dd660c2b9db587856baa408889302 --- ci/README.md | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/ci/README.md b/ci/README.md index b4edd4b1917..628954d3383 100644 --- a/ci/README.md +++ b/ci/README.md @@ -1,8 +1,8 @@ -## CI Scripts +# CI Scripts This directory contains scripts for each build step in each build stage. -### Running a Stage Locally +## Running a Stage Locally Be aware that the tests will be built and run in-place, so please run at your own risk. If the repository is not a fresh git clone, you might have to clean files from previous builds or test runs first. @@ -27,7 +27,7 @@ with a specific configuration, env -i HOME="$HOME" PATH="$PATH" USER="$USER" bash -c 'FILE_ENV="./ci/test/00_setup_env_arm.sh" ./ci/test_run_all.sh' ``` -### Configurations +## Configurations The test files (`FILE_ENV`) are constructed to test a wide range of configurations, rather than a single pass/fail. This helps to catch build @@ -49,8 +49,32 @@ env -i HOME="$HOME" PATH="$PATH" USER="$USER" bash -c 'MAKEJOBS="-j1" FILE_ENV=" The files starting with `0n` (`n` greater than 0) are the scripts that are run in order. -### Cache +## Cache In order to avoid rebuilding all dependencies for each build, the binaries are cached and reused when possible. Changes in the dependency-generator will trigger cache-invalidation and rebuilds as necessary. + +## Configuring a repository for CI + +### Primary repository + +To configure the primary repository, follow these steps: + +1. Register with [Cirrus Runners](https://cirrus-runners.app/) and purchase runners. +2. Install the Cirrus Runners GitHub app against the GitHub organization. +3. Enable organisation-level runners to be used in public repositories: + 1. `Org settings -> Actions -> Runner Groups -> Default -> Allow public repos` +4. Permit the following actions to run: + 1. cirruslabs/cache/restore@\* + 1. cirruslabs/cache/save@\* + 1. docker/setup-buildx-action@\* + 1. actions/github-script@\* + +### Forked repositories + +When used in a fork the CI will run on GitHub's free hosted runners by default. +In this case, due to GitHub's 10GB-per-repo cache size limitations caches will be frequently evicted and missed, but the workflows will run (slowly). + +It is also possible to use your own Cirrus Runners in your own fork with an appropriate patch to the `REPO_USE_CIRRUS_RUNNERS` variable in ../.github/workflows/ci.yml +NB that Cirrus Runners only work at an organisation level, therefore in order to use your own Cirrus Runners, *the fork must be within your own organisation*. From e4493b15dfa2267b9d83b67e2e205cc40a742fef Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 26/30] ci: add ccache hit-rate warning when < 75% Github-Pull: #32989 Rebased-From: dd1c5903e8d Print the ccache hit-rate for the job using a GitHub annotation if it was below 75%. --- ci/test/00_setup_env_mac_native.sh | 1 + ci/test/03_test_script.sh | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/ci/test/00_setup_env_mac_native.sh b/ci/test/00_setup_env_mac_native.sh index c47f13f96ed..ae21b72aa84 100755 --- a/ci/test/00_setup_env_mac_native.sh +++ b/ci/test/00_setup_env_mac_native.sh @@ -9,6 +9,7 @@ export LC_ALL=C.UTF-8 export HOST=x86_64-apple-darwin # Homebrew's python@3.12 is marked as externally managed (PEP 668). # Therefore, `--break-system-packages` is needed. +export CONTAINER_NAME="ci_mac_native" # macos does not use a container, but the env var is needed for logging export PIP_PACKAGES="--break-system-packages zmq" export GOAL="install" export BITCOIN_CONFIG="--with-gui --with-miniupnpc --with-natpmp --enable-reduce-exports" diff --git a/ci/test/03_test_script.sh b/ci/test/03_test_script.sh index 5920f7e9808..a3c57c014e7 100755 --- a/ci/test/03_test_script.sh +++ b/ci/test/03_test_script.sh @@ -145,6 +145,12 @@ fi bash -c "${MAYBE_BEAR} ${MAYBE_TOKEN} make $MAKEJOBS $GOAL" || ( echo "Build failure. Verbose build follows." && make "$GOAL" V=1 ; false ) bash -c "${PRINT_CCACHE_STATISTICS}" +if [ "$CI" = "true" ]; then + hit_rate=$(ccache -s | grep "Hits:" | head -1 | sed 's/.*(\(.*\)%).*/\1/') + if [ "${hit_rate%.*}" -lt 75 ]; then + echo "::notice title=low ccache hitrate::Ccache hit-rate in $CONTAINER_NAME was $hit_rate%" + fi +fi du -sh "${DEPENDS_DIR}"/*/ du -sh "${PREVIOUS_RELEASES_DIR}" From 189bb3992228240468195abaa1040f2528707f89 Mon Sep 17 00:00:00 2001 From: will Date: Tue, 5 Aug 2025 14:41:09 +0100 Subject: [PATCH 27/30] ci: fix annoying docker warning Github-Pull: #32989 Rebased-From: 2aa288efdda Docker currently warns that we are missing a default value. Set this to scratch which will error if an appropriate image tag is not passed in to silence the warning. --- ci/test_imagefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ci/test_imagefile b/ci/test_imagefile index 224141b138f..f9cf3187a25 100644 --- a/ci/test_imagefile +++ b/ci/test_imagefile @@ -4,7 +4,8 @@ # See ci/README.md for usage. -ARG CI_IMAGE_NAME_TAG +# We never want scratch, but default arg silences a Warning +ARG CI_IMAGE_NAME_TAG=scratch FROM ${CI_IMAGE_NAME_TAG} ARG FILE_ENV From 12eada012b56e6d4018b878c5663f57aeae91d89 Mon Sep 17 00:00:00 2001 From: willcl-ark Date: Fri, 8 Aug 2025 10:31:56 +0200 Subject: [PATCH 28/30] ci: remove un-needed lint_run*.sh files Github-Pull: #32989 Rebased-From: 3c5da69a232 ci/lint_run_all.sh: Only used in .cirrus.yml. Refer to test/lint/README.md on how to run locally. --- ci/lint_run_all.sh | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100755 ci/lint_run_all.sh diff --git a/ci/lint_run_all.sh b/ci/lint_run_all.sh deleted file mode 100755 index c57261d21a6..00000000000 --- a/ci/lint_run_all.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env bash -# -# Copyright (c) 2019-present The Bitcoin Core developers -# Distributed under the MIT software license, see the accompanying -# file COPYING or http://www.opensource.org/licenses/mit-license.php. - -export LC_ALL=C.UTF-8 - -# Only used in .cirrus.yml. Refer to test/lint/README.md on how to run locally. - -cp "./ci/retry/retry" "/ci_retry" -cp "./.python-version" "/.python-version" -mkdir --parents "/test/lint" -cp --recursive "./test/lint/test_runner" "/test/lint/" -set -o errexit; source ./ci/lint/04_install.sh -set -o errexit -./ci/lint/06_script.sh From 48761444e24350c2b74396aa6643fa58cdc05493 Mon Sep 17 00:00:00 2001 From: will Date: Thu, 4 Sep 2025 19:53:45 +0100 Subject: [PATCH 29/30] ci: reduce runner sizes on various jobs Github Pull: #33319 Rebased-From: 5eeb2facbbbbf68a2c30ef9e6747e39c85d7b116 These jobs can use reduced runner size to avoid wasting CPU, as much of the long-running part of the job is single-threaded. Suggested in: https://github.com/bitcoin/bitcoin/pull/32989#discussion_r2321775620 Co-authored-by: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> --- .github/workflows/ci.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a49d3d25afc..10f99f3cdae 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -328,7 +328,6 @@ jobs: shell: cmd run: py -3 test\fuzz\test_runner.py --par %NUMBER_OF_PROCESSORS% --loglevel DEBUG %RUNNER_TEMP%\qa-assets\fuzz_seed_corpus - - name: CI script run: ./ci/test_run_all.sh @@ -360,7 +359,7 @@ jobs: file-env: './ci/test/00_setup_env_win64.sh' - name: 'ASan + LSan + UBSan + integer, no depends, USDT' - cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-lg' # has to match container in ci/test/00_setup_env_native_asan.sh for tracing tools + cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md' # has to match container in ci/test/00_setup_env_native_asan.sh for tracing tools fallback-runner: 'ubuntu-24.04' timeout-minutes: 120 file-env: './ci/test/00_setup_env_native_asan.sh' @@ -372,7 +371,7 @@ jobs: file-env: './ci/test/00_setup_env_mac_cross.sh' - name: 'No wallet, libbitcoinkernel' - cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-md' + cirrus-runner: 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-sm' fallback-runner: 'ubuntu-24.04' timeout-minutes: 120 file-env: './ci/test/00_setup_env_native_nowallet_libbitcoinkernel.sh' @@ -455,7 +454,7 @@ jobs: lint: name: 'lint' needs: runners - runs-on: ${{ needs.runners.outputs.use-cirrus-runners == 'true' && 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-sm' || 'ubuntu-24.04' }} + runs-on: ${{ needs.runners.outputs.use-cirrus-runners == 'true' && 'ghcr.io/cirruslabs/ubuntu-runner-amd64:24.04-xs' || 'ubuntu-24.04' }} if: ${{ vars.SKIP_BRANCH_PUSH != 'true' || github.event_name == 'pull_request' }} timeout-minutes: 20 env: From ea4e0aa8c4b0e4eed92b81e6e8b84a3b92232939 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Thu, 4 Sep 2025 11:21:45 +0200 Subject: [PATCH 30/30] ci: Checkout latest merged pulls Github-Pull: #33303 Rebased-From: fa8f081af31 --- .github/workflows/ci.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10f99f3cdae..5b5860228ac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -108,8 +108,12 @@ jobs: BASE_ROOT_DIR: ${{ github.workspace }} steps: - - name: Checkout - uses: actions/checkout@v4 + - &CHECKOUT + name: Checkout + uses: actions/checkout@v5 + with: + # Ensure the latest merged pull request state is used, even on re-runs. + ref: &CHECKOUT_REF_TMPL ${{ github.event_name == 'pull_request' && github.ref || '' }} - name: Clang version run: | @@ -165,8 +169,7 @@ jobs: TEST_RUNNER_TIMEOUT_FACTOR: 40 steps: - - name: Checkout - uses: actions/checkout@v4 + - *CHECKOUT - name: Configure Developer Command Prompt for Microsoft Visual C++ # Using microsoft/setup-msbuild is not enough. @@ -419,8 +422,7 @@ jobs: file-env: './ci/test/00_setup_env_native_msan.sh' steps: - - name: Checkout - uses: actions/checkout@v5 + - *CHECKOUT - name: Configure environment uses: ./.github/actions/configure-environment @@ -463,6 +465,7 @@ jobs: - name: Checkout uses: actions/checkout@v5 with: + ref: *CHECKOUT_REF_TMPL fetch-depth: 0 - name: Configure Docker