mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-02-28 18:19:31 +01:00
fa13b13239ci: [refactor] Use pathlib over os.path (MarcoFalke)fa2719ab1bci: [refactor] Move run_unit_tests to ci-windows-cross.py (MarcoFalke)fa99ba5f14ci: Set PREVIOUS_RELEASES_DIR env var in ci-windows-cross.py (MarcoFalke)fa4a1cab6cci: Move run_functional_tests into ci-windows-cross.py (MarcoFalke)1111108685ci: [refactor] Move pyzmq install and get_previous_releases into ci-windows-cross.py (MarcoFalke)fac9c7bd66ci: [refactor] Move config.ini rewrite to ci-windows-cross.py (MarcoFalke)faf7389466ci: Move check_manifests step to ci-windows-cross.py (MarcoFalke)fa674d55dfci: [refactor] Move print_version step into ci-windows-cross.py helper (MarcoFalke) Pull request description: Currently the ci yaml has a mix of Bash and Pwsh snippets, which is problematic: * The `shellcheck` tool does not review the Bash * The ci yaml is not merged with master on re-runs, but the code is, leading to possibly confusing CI errors on re-runs * The Pwsh isn't reviewed at all by any tool * It is tedious to run the CI commands locally on Windows Fix all issues by extracting them into a step-based Python script. ACKs for top commit: janb84: re ACKfa13b13239hebasto: ACKfa13b13239, I have reviewed the code and it looks OK. Tree-SHA512: 23d21d3bfb07e102fe1cc15ba5749d553d9766ae6c4a7648bd77df0705469bd138c76a9a2fdeb4d91d3f889a425b7caf25878ecb2e68b604faf9665f8df4eb6d
207 lines
5.5 KiB
Python
Executable File
207 lines
5.5 KiB
Python
Executable File
#!/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 argparse
|
|
import os
|
|
import shlex
|
|
import subprocess
|
|
import sys
|
|
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))
|
|
|
|
|
|
GENERATE_OPTIONS = {
|
|
"standard": [
|
|
"-DBUILD_BENCH=ON",
|
|
"-DBUILD_KERNEL_LIB=ON",
|
|
"-DBUILD_UTIL_CHAINSTATE=ON",
|
|
"-DCMAKE_COMPILE_WARNING_AS_ERROR=ON",
|
|
],
|
|
"fuzz": [
|
|
"-DVCPKG_MANIFEST_NO_DEFAULT_FEATURES=ON",
|
|
"-DVCPKG_MANIFEST_FEATURES=wallet",
|
|
"-DBUILD_GUI=OFF",
|
|
"-DWITH_ZMQ=OFF",
|
|
"-DBUILD_FOR_FUZZING=ON",
|
|
"-DCMAKE_COMPILE_WARNING_AS_ERROR=ON",
|
|
],
|
|
}
|
|
|
|
|
|
def generate(ci_type):
|
|
command = [
|
|
"cmake",
|
|
"-B",
|
|
"build",
|
|
"-Werror=dev",
|
|
"--preset",
|
|
"vs2026",
|
|
] + GENERATE_OPTIONS[ci_type]
|
|
run(command)
|
|
|
|
|
|
def build():
|
|
command = [
|
|
"cmake",
|
|
"--build",
|
|
"build",
|
|
"--config",
|
|
"Release",
|
|
]
|
|
if run(command + ["-j", str(os.process_cpu_count())], check=False).returncode != 0:
|
|
print("Build failure. Verbose build follows.")
|
|
run(command + ["-j1", "--verbose"])
|
|
|
|
|
|
def check_manifests(ci_type):
|
|
if ci_type != "standard":
|
|
print(f"Skipping manifest validation for '{ci_type}' ci type.")
|
|
return
|
|
|
|
release_dir = Path.cwd() / "build" / "bin" / "Release"
|
|
manifest_path = release_dir / "bitcoind.manifest"
|
|
cmd_bitcoind_manifest = [
|
|
"mt.exe",
|
|
"-nologo",
|
|
f"-inputresource:{release_dir / 'bitcoind.exe'}",
|
|
f"-out:{manifest_path}",
|
|
]
|
|
run(cmd_bitcoind_manifest)
|
|
print(manifest_path.read_text())
|
|
|
|
skips = { # Skip as they currently do not have manifests
|
|
"fuzz.exe",
|
|
"bench_bitcoin.exe",
|
|
"test_bitcoin-qt.exe",
|
|
"test_kernel.exe",
|
|
"bitcoin-chainstate.exe",
|
|
}
|
|
for entry in release_dir.iterdir():
|
|
if entry.suffix.lower() != ".exe":
|
|
continue
|
|
if entry.name in skips:
|
|
print(f"Skipping {entry.name} (no manifest present)")
|
|
continue
|
|
print(f"Checking {entry.name}")
|
|
cmd_check_manifest = [
|
|
"mt.exe",
|
|
"-nologo",
|
|
f"-inputresource:{entry}",
|
|
"-validate_manifest",
|
|
]
|
|
run(cmd_check_manifest)
|
|
|
|
|
|
def prepare_tests(ci_type):
|
|
if ci_type == "standard":
|
|
run([sys.executable, "-m", "pip", "install", "pyzmq"])
|
|
elif ci_type == "fuzz":
|
|
repo_dir = str(Path.cwd() / "qa-assets")
|
|
clone_cmd = [
|
|
"git",
|
|
"clone",
|
|
"--depth=1",
|
|
"https://github.com/bitcoin-core/qa-assets",
|
|
repo_dir,
|
|
]
|
|
run(clone_cmd)
|
|
print("Using qa-assets repo from commit ...")
|
|
run(["git", "-C", repo_dir, "log", "-1"])
|
|
|
|
|
|
def run_tests(ci_type):
|
|
build_dir = Path.cwd() / "build"
|
|
num_procs = str(os.process_cpu_count())
|
|
release_bin = build_dir / "bin" / "Release"
|
|
|
|
if ci_type == "standard":
|
|
test_envs = {
|
|
"BITCOIN_BIN": "bitcoin.exe",
|
|
"BITCOIND": "bitcoind.exe",
|
|
"BITCOINCLI": "bitcoin-cli.exe",
|
|
"BITCOIN_BENCH": "bench_bitcoin.exe",
|
|
"BITCOINTX": "bitcoin-tx.exe",
|
|
"BITCOINUTIL": "bitcoin-util.exe",
|
|
"BITCOINWALLET": "bitcoin-wallet.exe",
|
|
"BITCOINCHAINSTATE": "bitcoin-chainstate.exe",
|
|
}
|
|
for var, exe in test_envs.items():
|
|
os.environ[var] = str(release_bin / exe)
|
|
|
|
ctest_cmd = [
|
|
"ctest",
|
|
"--test-dir",
|
|
str(build_dir),
|
|
"--output-on-failure",
|
|
"--stop-on-failure",
|
|
"-j",
|
|
num_procs,
|
|
"--build-config",
|
|
"Release",
|
|
]
|
|
run(ctest_cmd)
|
|
|
|
test_cmd = [
|
|
sys.executable,
|
|
str(build_dir / "test" / "functional" / "test_runner.py"),
|
|
"--jobs",
|
|
num_procs,
|
|
"--quiet",
|
|
f"--tmpdirprefix={Path.cwd()}",
|
|
"--combinedlogslen=99999999",
|
|
*shlex.split(os.environ.get("TEST_RUNNER_EXTRA", "").strip()),
|
|
]
|
|
run(test_cmd)
|
|
|
|
elif ci_type == "fuzz":
|
|
os.environ["BITCOINFUZZ"] = str(release_bin / "fuzz.exe")
|
|
fuzz_cmd = [
|
|
sys.executable,
|
|
str(build_dir / "test" / "fuzz" / "test_runner.py"),
|
|
"--par",
|
|
num_procs,
|
|
"--loglevel",
|
|
"DEBUG",
|
|
str(Path.cwd() / "qa-assets" / "fuzz_corpora"),
|
|
]
|
|
run(fuzz_cmd)
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="Utility to run Windows CI steps.")
|
|
parser.add_argument("ci_type", choices=GENERATE_OPTIONS, help="CI type to run.")
|
|
steps = [
|
|
"generate",
|
|
"build",
|
|
"check_manifests",
|
|
"prepare_tests",
|
|
"run_tests",
|
|
]
|
|
parser.add_argument("step", choices=steps, help="CI step to perform.")
|
|
args = parser.parse_args()
|
|
|
|
if args.step == "generate":
|
|
generate(args.ci_type)
|
|
elif args.step == "build":
|
|
build()
|
|
elif args.step == "check_manifests":
|
|
check_manifests(args.ci_type)
|
|
elif args.step == "prepare_tests":
|
|
prepare_tests(args.ci_type)
|
|
elif args.step == "run_tests":
|
|
run_tests(args.ci_type)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|