lint: upgrade lint scripts for worktrees

Add a ci/lint.py script to run the linter both locally or inside the CI
(replacing .github/ci-lint-exec.py) which supports running from a
worktree.

Determines whether we are in a worktree, and mounts the real `.git`
directory as a read-only volume if we are.
This commit is contained in:
will 2026-01-23 12:09:22 +00:00
parent 1b079becf1
commit c17a2adb8d
No known key found for this signature in database
GPG Key ID: CE6EC49945C17EA6
4 changed files with 88 additions and 63 deletions

View File

@ -1,55 +0,0 @@
#!/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)
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",
"run",
"--rm",
*extra_env,
f"--volume={os.getcwd()}:/bitcoin",
CONTAINER_NAME,
])
if __name__ == "__main__":
main()

View File

@ -681,4 +681,6 @@ jobs:
cache-provider: ${{ needs.runners.outputs.provider }}
- name: CI script
run: python .github/ci-lint-exec.py
run: |
git worktree add ../lint-worktree HEAD
../lint-worktree/ci/lint.py

81
ci/lint.py Executable file
View File

@ -0,0 +1,81 @@
#!/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
from pathlib import Path
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(str(e))
def get_worktree_mounts(repo_root):
git_path = repo_root / ".git"
if not git_path.is_file():
return []
content = git_path.read_text().strip()
if not content.startswith("gitdir: "):
return []
gitdir = (repo_root / content.removeprefix("gitdir: ")).resolve()
main_gitdir = gitdir.parent.parent
return [
f"--volume={gitdir}:{gitdir}",
f"--volume={main_gitdir}:{main_gitdir}:ro",
]
def main():
repo_root = Path(__file__).resolve().parent.parent
is_ci = os.environ.get("GITHUB_ACTIONS") == "true"
container = "bitcoin-linter"
build_cmd = [
"docker",
"buildx",
"build",
f"--tag={container}",
*shlex.split(os.environ.get("DOCKER_BUILD_CACHE_ARG", "")),
f"--file={repo_root}/ci/lint_imagefile",
str(repo_root),
]
if run(build_cmd, check=False).returncode != 0:
if is_ci:
print("Retry building image after failure")
time.sleep(3)
run(build_cmd)
extra_env = []
if is_ci:
if os.environ.get("GITHUB_EVENT_NAME") == "pull_request":
extra_env = ["--env", "LINT_CI_IS_PR=1"]
elif os.environ.get("GITHUB_REPOSITORY") == "bitcoin/bitcoin":
extra_env = ["--env", "LINT_CI_SANITY_CHECK_COMMIT_SIG=1"]
run(
[
"docker",
"run",
"--rm",
*extra_env,
f"--volume={repo_root}:/bitcoin",
*get_worktree_mounts(repo_root),
*([] if is_ci else ["-it"]),
container,
*sys.argv[1:],
]
)
if __name__ == "__main__":
main()

View File

@ -3,20 +3,17 @@ This folder contains lint scripts.
Running locally
===============
To run linters locally with the same versions as the CI environment, use the included
Dockerfile:
To run linters locally with the same versions as the CI environment use
the _lint.py_ helper script which runs checks inside the CI container:
```sh
DOCKER_BUILDKIT=1 docker build --platform=linux --tag=bitcoin-linter --file="./ci/lint_imagefile" ./ && docker run --rm -v $(pwd):/bitcoin -it bitcoin-linter
./ci/lint.py
```
Building the container can be done every time, because it is fast when the
result is cached and it prevents issues when the image changes.
test runner
===========
To run all the lint checks in the test runner outside the docker you first need
To run all the lint checks in the test runner outside the container you first need
to install the rust toolchain using your package manager of choice or
[rustup](https://www.rust-lang.org/tools/install).