From fa1dacaebe5d326ff8736ab9a4475f8a99ce4bc3 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Mon, 17 Nov 2025 15:12:01 +0100 Subject: [PATCH 1/4] ci: Move lint exec snippet to stand-alone py file Moving the python code out of the yaml string makes it easier to lint, format, and edit. This can be reviewed with the git options: --color-moved=dimmed-zebra --color-moved-ws=ignore-all-space --- .github/ci-lint-exec.py | 51 ++++++++++++++++++++++++++++++++++++++++ .github/workflows/ci.yml | 38 +----------------------------- 2 files changed, 52 insertions(+), 37 deletions(-) create mode 100755 .github/ci-lint-exec.py diff --git a/.github/ci-lint-exec.py b/.github/ci-lint-exec.py new file mode 100755 index 00000000000..b0f78983886 --- /dev/null +++ b/.github/ci-lint-exec.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +# Copyright (c) The Bitcoin Core developers +# Distributed under the MIT software license, see the accompanying +# file COPYING or https://opensource.org/license/mit. + +import os +import shlex +import subprocess +import sys +import time + + +def run(cmd, **kwargs): + print("+ " + shlex.join(cmd), flush=True) + kwargs.setdefault("check", True) + try: + return subprocess.run(cmd, **kwargs) + except Exception as e: + sys.exit(e) + + +def main(): + CONTAINER_NAME = os.environ["CONTAINER_NAME"] + + build_cmd = [ + "docker", "buildx", "build", + f"--tag={CONTAINER_NAME}", + *shlex.split(os.getenv("DOCKER_BUILD_CACHE_ARG", "")), + "--file=./ci/lint_imagefile", + "." + ] + + if run(build_cmd, check=False).returncode != 0: + print("Retry building image tag after failure") + time.sleep(3) + run(build_cmd) + + CIRRUS_PR_FLAG = [] + if os.environ.get("GITHUB_EVENT_NAME") == "pull_request": + CIRRUS_PR_FLAG = ["-e", "CIRRUS_PR=1"] + + run([ + "docker", "run", "--rm", + *CIRRUS_PR_FLAG, + f"--volume={os.getcwd()}:/bitcoin", + CONTAINER_NAME, + ]) + + +if __name__ == "__main__": + main() diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0265583b027..343c20b3b13 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -620,40 +620,4 @@ jobs: cache-provider: ${{ needs.runners.outputs.provider }} - name: CI script - shell: python - run: | - import os, shlex, subprocess, sys, time - - def run(cmd, **kwargs): - print("+ " + shlex.join(cmd), flush=True) - kwargs.setdefault("check", True) - try: - return subprocess.run(cmd, **kwargs) - except Exception as e: - sys.exit(e) - - CONTAINER_NAME = os.environ["CONTAINER_NAME"] - - build_cmd = [ - "docker", "buildx", "build", - f"--tag={CONTAINER_NAME}", - *shlex.split(os.getenv("DOCKER_BUILD_CACHE_ARG", "")), - "--file=./ci/lint_imagefile", - "." - ] - - if run(build_cmd, check=False).returncode != 0: - print("Retry building image tag after failure") - time.sleep(3) - run(build_cmd) - - CIRRUS_PR_FLAG = [] - if '${{ github.event_name }}' == "pull_request": - CIRRUS_PR_FLAG = ["-e", "CIRRUS_PR=1"] - - run([ - "docker", "run", "--rm", - *CIRRUS_PR_FLAG, - f"--volume={os.getcwd()}:/bitcoin", - CONTAINER_NAME, - ]) + run: python .github/ci-lint-exec.py From faa0973de2966a610e47ba4b6d6edf3c5509d52e Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Mon, 17 Nov 2025 16:55:02 +0100 Subject: [PATCH 2/4] ci: [refactor] Rename CIRRUS_PR env var to LINT_CI_IS_PR The CIRRUS_PR env var was cirrus-specific and using a provider-agnostic name makes more sense. Also, enable pipefail, while touching this file. This refactor is needed for the next commit. --- .github/ci-lint-exec.py | 12 +++++++----- ci/lint/06_script.sh | 8 ++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/.github/ci-lint-exec.py b/.github/ci-lint-exec.py index b0f78983886..f0a6adcabca 100755 --- a/.github/ci-lint-exec.py +++ b/.github/ci-lint-exec.py @@ -35,13 +35,15 @@ def main(): time.sleep(3) run(build_cmd) - CIRRUS_PR_FLAG = [] - if os.environ.get("GITHUB_EVENT_NAME") == "pull_request": - CIRRUS_PR_FLAG = ["-e", "CIRRUS_PR=1"] + extra_env = [] + if os.environ["GITHUB_EVENT_NAME"] == "pull_request": + extra_env = ["--env", "LINT_CI_IS_PR=1"] run([ - "docker", "run", "--rm", - *CIRRUS_PR_FLAG, + "docker", + "run", + "--rm", + *extra_env, f"--volume={os.getcwd()}:/bitcoin", CONTAINER_NAME, ]) diff --git a/ci/lint/06_script.sh b/ci/lint/06_script.sh index 6d637c2a438..536427f1b45 100755 --- a/ci/lint/06_script.sh +++ b/ci/lint/06_script.sh @@ -6,19 +6,19 @@ export LC_ALL=C -set -ex +set -o errexit -o pipefail -o xtrace -if [ -n "$CIRRUS_PR" ]; then +if [ -n "${LINT_CI_IS_PR}" ]; then export COMMIT_RANGE="HEAD~..HEAD" if [ "$(git rev-list -1 HEAD)" != "$(git rev-list -1 --merges HEAD)" ]; then - echo "Error: The top commit must be a merge commit, usually the remote 'pull/${PR_NUMBER}/merge' branch." + echo "Error: The top commit must be a merge commit, usually the remote 'pull//merge' branch." false fi fi RUST_BACKTRACE=1 cargo run --manifest-path "./test/lint/test_runner/Cargo.toml" -if [ "$CIRRUS_REPO_FULL_NAME" = "bitcoin/bitcoin" ] && [ "$CIRRUS_PR" = "" ] ; then +if [ "$CIRRUS_REPO_FULL_NAME" = "bitcoin/bitcoin" ] && [ "${LINT_CI_IS_PR}" = "" ] ; then # Sanity check only the last few commits to get notified of missing sigs, # missing keys, or expired keys. Usually there is only one new merge commit # per push on the master branch and a few commits on release branches, so From fa0ce4c1486bb441e6e48d0a397334cf36cc8140 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Mon, 17 Nov 2025 16:43:34 +0100 Subject: [PATCH 3/4] ci: Re-enable LINT_CI_SANITY_CHECK_COMMIT_SIG With the move from cirrus-ci to GHA, the CIRRUS_REPO_FULL_NAME env var was always unset, never triggering the sanity check. Fix this by introducing a new vendor-agnostic env var and setting it properly. --- .github/ci-lint-exec.py | 2 ++ ci/lint/06_script.sh | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/ci-lint-exec.py b/.github/ci-lint-exec.py index f0a6adcabca..73749accd6f 100755 --- a/.github/ci-lint-exec.py +++ b/.github/ci-lint-exec.py @@ -38,6 +38,8 @@ def main(): extra_env = [] if os.environ["GITHUB_EVENT_NAME"] == "pull_request": extra_env = ["--env", "LINT_CI_IS_PR=1"] + if os.environ["GITHUB_EVENT_NAME"] != "pull_request" and os.environ["GITHUB_REPOSITORY"] == "bitcoin/bitcoin": + extra_env = ["--env", "LINT_CI_SANITY_CHECK_COMMIT_SIG=1"] run([ "docker", diff --git a/ci/lint/06_script.sh b/ci/lint/06_script.sh index 536427f1b45..82e499c29ba 100755 --- a/ci/lint/06_script.sh +++ b/ci/lint/06_script.sh @@ -18,7 +18,7 @@ fi RUST_BACKTRACE=1 cargo run --manifest-path "./test/lint/test_runner/Cargo.toml" -if [ "$CIRRUS_REPO_FULL_NAME" = "bitcoin/bitcoin" ] && [ "${LINT_CI_IS_PR}" = "" ] ; then +if [ "${LINT_CI_SANITY_CHECK_COMMIT_SIG}" = "1" ] ; then # Sanity check only the last few commits to get notified of missing sigs, # missing keys, or expired keys. Usually there is only one new merge commit # per push on the master branch and a few commits on release branches, so From 55555db055b59dd529526915dfc59e5a13e43160 Mon Sep 17 00:00:00 2001 From: MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> Date: Mon, 17 Nov 2025 17:49:59 +0100 Subject: [PATCH 4/4] doc: Add missing --platform=linux to docker build command This is required to pick the native arch, similar to how the CI_IMAGE_PLATFORM is set to linux. --- test/lint/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/lint/README.md b/test/lint/README.md index 7c3798cdefd..1858a2c0edb 100644 --- a/test/lint/README.md +++ b/test/lint/README.md @@ -7,7 +7,7 @@ To run linters locally with the same versions as the CI environment, use the inc Dockerfile: ```sh -DOCKER_BUILDKIT=1 docker build -t bitcoin-linter --file "./ci/lint_imagefile" ./ && docker run --rm -v $(pwd):/bitcoin -it bitcoin-linter +DOCKER_BUILDKIT=1 docker build --platform=linux --tag=bitcoin-linter --file="./ci/lint_imagefile" ./ && docker run --rm -v $(pwd):/bitcoin -it bitcoin-linter ``` Building the container can be done every time, because it is fast when the