mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-03-17 17:02:43 +00:00
fafdb8f635bc157f55e23890264d12170ecd41ae ci: Allow running iwyu ci in worktree (MarcoFalke)
fab73e213dee1057e9e759133767b17ec5b1f6ab ci: Reject unsafe execution of shell scripts (MarcoFalke)
Pull request description:
Currently, the iwyu CI fails to run in a git-worktree, or git-archive. This is due to the use of `git diff`.
Fix this by force-initializing a dummy git repo with a single dummy commit.
It may be possible to detect when `git diff` is not available in the directory, and only apply the fallback when needed, but the git history is not needed and it is easier to unconditionally apply the git init.
ACKs for top commit:
willcl-ark:
reACK fafdb8f635bc157f55e23890264d12170ecd41ae
hebasto:
ACK fafdb8f635bc157f55e23890264d12170ecd41ae, I have reviewed the code and it looks OK. Tested on Fedora 43.
sedited:
ACK fafdb8f635bc157f55e23890264d12170ecd41ae
Tree-SHA512: 572f1e2b9e215c2804095382498abb5b8636e3a49d5ba2a736b975e06afa2881d815b854a8a593d0f187c7c6b55034688e11f46d6814edfe7c29505197e80b18
242 lines
8.9 KiB
Bash
Executable File
242 lines
8.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
#
|
|
# Copyright (c) 2018-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
|
|
|
|
set -o errexit -o xtrace
|
|
|
|
if [ "${DANGER_RUN_CI_ON_HOST}" != "1" ]; then
|
|
echo "This script will make unsafe local and global modifications, so it can only be run inside a container and requires DANGER_RUN_CI_ON_HOST=1"
|
|
exit 1
|
|
fi
|
|
|
|
cd "${BASE_ROOT_DIR}"
|
|
|
|
export PATH="/path_with space:${PATH}"
|
|
export ASAN_OPTIONS="detect_leaks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1"
|
|
export LSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/lsan"
|
|
export TSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/tsan:halt_on_error=1:second_deadlock_stack=1"
|
|
export UBSAN_OPTIONS="suppressions=${BASE_ROOT_DIR}/test/sanitizer_suppressions/ubsan:print_stacktrace=1:halt_on_error=1:report_error_type=1"
|
|
|
|
echo "Number of available processing units: $(nproc)"
|
|
if [ "$CI_OS_NAME" == "macos" ]; then
|
|
top -l 1 -s 0 | awk ' /PhysMem/ {print}'
|
|
else
|
|
free -m -h
|
|
echo "System info: $(uname --kernel-name --kernel-release)"
|
|
lscpu
|
|
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
|
|
export HOST=${HOST:-$("$BASE_ROOT_DIR/depends/config.guess")}
|
|
|
|
echo "=== BEGIN env ==="
|
|
env
|
|
echo "=== END env ==="
|
|
|
|
# The CI framework should be flexible where it is run from. For example, from
|
|
# a git-archive, a git-worktree, or a normal git repo.
|
|
# The iwyu task requires a working git repo, which may not always be
|
|
# available, so initialize one with force.
|
|
if [[ "${RUN_IWYU}" == true ]]; then
|
|
mv .git .git_ci_backup || true
|
|
git init
|
|
git add ./src # the git diff command used later for iwyu only cares about ./src
|
|
git config user.email "ci@ci"
|
|
git config user.name "CI"
|
|
git commit -m "dummy CI ./src init for IWYU"
|
|
fi
|
|
|
|
if [ "$RUN_FUZZ_TESTS" = "true" ]; then
|
|
export DIR_FUZZ_IN=${DIR_QA_ASSETS}/fuzz_corpora/
|
|
if [ ! -d "$DIR_FUZZ_IN" ]; then
|
|
${CI_RETRY_EXE} git clone --depth=1 https://github.com/bitcoin-core/qa-assets "${DIR_QA_ASSETS}"
|
|
fi
|
|
(
|
|
cd "${DIR_QA_ASSETS}"
|
|
echo "Using qa-assets repo from commit ..."
|
|
git log -1
|
|
)
|
|
elif [ "$RUN_UNIT_TESTS" = "true" ]; then
|
|
export DIR_UNIT_TEST_DATA=${DIR_QA_ASSETS}/unit_test_data/
|
|
if [ ! -d "$DIR_UNIT_TEST_DATA" ]; then
|
|
mkdir -p "$DIR_UNIT_TEST_DATA"
|
|
${CI_RETRY_EXE} curl --location --fail https://github.com/bitcoin-core/qa-assets/raw/main/unit_test_data/script_assets_test.json -o "${DIR_UNIT_TEST_DATA}/script_assets_test.json"
|
|
fi
|
|
fi
|
|
|
|
# Make sure default datadir does not exist and is never read by creating a dummy file
|
|
if [ "$CI_OS_NAME" == "macos" ]; then
|
|
echo > "${HOME}/Library/Application Support/Bitcoin"
|
|
else
|
|
echo > "${HOME}/.bitcoin"
|
|
fi
|
|
|
|
if [ -z "$NO_DEPENDS" ]; then
|
|
if [[ $CI_IMAGE_NAME_TAG == *alpine* ]]; then
|
|
SHELL_OPTS="CONFIG_SHELL=/usr/bin/dash"
|
|
else
|
|
SHELL_OPTS="CONFIG_SHELL="
|
|
fi
|
|
bash -c "$SHELL_OPTS make $MAKEJOBS -C depends HOST=$HOST $DEP_OPTS LOG=1"
|
|
fi
|
|
if [ "$DOWNLOAD_PREVIOUS_RELEASES" = "true" ]; then
|
|
test/get_previous_releases.py --target-dir "$PREVIOUS_RELEASES_DIR"
|
|
fi
|
|
|
|
BITCOIN_CONFIG_ALL="-DCMAKE_COMPILE_WARNING_AS_ERROR=ON -DBUILD_BENCH=ON -DBUILD_FUZZ_BINARY=ON"
|
|
if [ -z "$NO_DEPENDS" ]; then
|
|
BITCOIN_CONFIG_ALL="${BITCOIN_CONFIG_ALL} -DCMAKE_TOOLCHAIN_FILE=$DEPENDS_DIR/$HOST/toolchain.cmake"
|
|
fi
|
|
|
|
ccache --zero-stats
|
|
|
|
# Folder where the build is done.
|
|
BASE_BUILD_DIR=${BASE_BUILD_DIR:-$BASE_SCRATCH_DIR/build-$HOST}
|
|
|
|
BITCOIN_CONFIG_ALL="$BITCOIN_CONFIG_ALL -DCMAKE_INSTALL_PREFIX=$BASE_OUTDIR -Werror=dev"
|
|
|
|
if [[ "${RUN_IWYU}" == true || "${RUN_TIDY}" == true ]]; then
|
|
BITCOIN_CONFIG_ALL="$BITCOIN_CONFIG_ALL -DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
|
|
fi
|
|
|
|
eval "CMAKE_ARGS=($BITCOIN_CONFIG_ALL $BITCOIN_CONFIG)"
|
|
cmake -S "$BASE_ROOT_DIR" -B "$BASE_BUILD_DIR" "${CMAKE_ARGS[@]}" || (
|
|
cd "${BASE_BUILD_DIR}"
|
|
# shellcheck disable=SC2046
|
|
cat $(cmake -P "${BASE_ROOT_DIR}/ci/test/GetCMakeLogFiles.cmake")
|
|
false
|
|
)
|
|
|
|
if [[ "${GOAL}" != all && "${GOAL}" != codegen ]]; then
|
|
GOAL="all ${GOAL}"
|
|
fi
|
|
|
|
# shellcheck disable=SC2086
|
|
cmake --build "${BASE_BUILD_DIR}" "$MAKEJOBS" --target $GOAL || (
|
|
echo "Build failure. Verbose build follows."
|
|
# shellcheck disable=SC2086
|
|
cmake --build "${BASE_BUILD_DIR}" -j1 --target $GOAL --verbose
|
|
false
|
|
)
|
|
|
|
ccache --version | head -n 1 && ccache --show-stats --verbose
|
|
hit_rate=$(ccache --show-stats | 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
|
|
du -sh "${DEPENDS_DIR}"/*/
|
|
du -sh "${PREVIOUS_RELEASES_DIR}"
|
|
|
|
if [ -n "${CI_LIMIT_STACK_SIZE}" ]; then
|
|
ulimit -s 512
|
|
fi
|
|
|
|
if [ -n "$USE_VALGRIND" ]; then
|
|
"${BASE_ROOT_DIR}/ci/test/wrap-valgrind.sh"
|
|
fi
|
|
|
|
if [ "$RUN_CHECK_DEPS" = "true" ]; then
|
|
"${BASE_ROOT_DIR}/contrib/devtools/check-deps.sh" "${BASE_BUILD_DIR}"
|
|
fi
|
|
|
|
if [ "$RUN_UNIT_TESTS" = "true" ]; then
|
|
DIR_UNIT_TEST_DATA="${DIR_UNIT_TEST_DATA}" \
|
|
LD_LIBRARY_PATH="${DEPENDS_DIR}/${HOST}/lib" \
|
|
CTEST_OUTPUT_ON_FAILURE=ON \
|
|
ctest --test-dir "${BASE_BUILD_DIR}" \
|
|
--stop-on-failure \
|
|
"${MAKEJOBS}" \
|
|
--timeout $(( TEST_RUNNER_TIMEOUT_FACTOR * 60 ))
|
|
fi
|
|
|
|
if [ "$RUN_FUNCTIONAL_TESTS" = "true" ]; then
|
|
# parses TEST_RUNNER_EXTRA as an array which allows for multiple arguments such as TEST_RUNNER_EXTRA='--exclude "rpc_bind.py --ipv6"'
|
|
eval "TEST_RUNNER_EXTRA=($TEST_RUNNER_EXTRA)"
|
|
LD_LIBRARY_PATH="${DEPENDS_DIR}/${HOST}/lib" \
|
|
"${BASE_BUILD_DIR}/test/functional/test_runner.py" \
|
|
"${MAKEJOBS}" \
|
|
--tmpdirprefix "${BASE_SCRATCH_DIR}/test_runner/" \
|
|
--ansi \
|
|
--combinedlogslen=99999999 \
|
|
--timeout-factor="${TEST_RUNNER_TIMEOUT_FACTOR}" \
|
|
"${TEST_RUNNER_EXTRA[@]}" \
|
|
--quiet \
|
|
--failfast
|
|
fi
|
|
|
|
if [ "${RUN_TIDY}" = "true" ]; then
|
|
cmake -B /tidy-build -DLLVM_DIR=/usr/lib/llvm-"${TIDY_LLVM_V}"/cmake -DCMAKE_BUILD_TYPE=Release -S "${BASE_ROOT_DIR}"/contrib/devtools/bitcoin-tidy
|
|
cmake --build /tidy-build "$MAKEJOBS"
|
|
cmake --build /tidy-build --target bitcoin-tidy-tests "$MAKEJOBS"
|
|
|
|
set -eo pipefail
|
|
# Filter out:
|
|
# * qt qrc and moc generated files
|
|
jq 'map(select(.file | test("src/qt/.*_autogen/.*\\.cpp$") | not))' "${BASE_BUILD_DIR}/compile_commands.json" > tmp.json
|
|
mv tmp.json "${BASE_BUILD_DIR}/compile_commands.json"
|
|
|
|
cd "${BASE_BUILD_DIR}/src/"
|
|
if ! ( run-clang-tidy-"${TIDY_LLVM_V}" -config-file="${BASE_ROOT_DIR}/src/.clang-tidy" -quiet -load="/tidy-build/libbitcoin-tidy.so" "${MAKEJOBS}" | tee tmp.tidy-out.txt ); then
|
|
grep -C5 "error: " tmp.tidy-out.txt
|
|
echo "^^^ ⚠️ Failure generated from clang-tidy"
|
|
false
|
|
fi
|
|
fi
|
|
|
|
if [[ "${RUN_IWYU}" == true ]]; then
|
|
# TODO: Consider enforcing IWYU across the entire codebase.
|
|
FILES_WITH_ENFORCED_IWYU="/src/((crypto|index|kernel|primitives|univalue/(lib|test)|zmq)/.*\\.cpp|node/blockstorage\\.cpp|node/utxo_snapshot\\.cpp|core_io\\.cpp|signet\\.cpp)"
|
|
jq --arg patterns "$FILES_WITH_ENFORCED_IWYU" 'map(select(.file | test($patterns)))' "${BASE_BUILD_DIR}/compile_commands.json" > "${BASE_BUILD_DIR}/compile_commands_iwyu_errors.json"
|
|
jq --arg patterns "$FILES_WITH_ENFORCED_IWYU" 'map(select(.file | test($patterns) | not))' "${BASE_BUILD_DIR}/compile_commands.json" > "${BASE_BUILD_DIR}/compile_commands_iwyu_warnings.json"
|
|
|
|
cd "${BASE_ROOT_DIR}"
|
|
|
|
run_iwyu() {
|
|
mv "${BASE_BUILD_DIR}/$1" "${BASE_BUILD_DIR}/compile_commands.json"
|
|
python3 "/include-what-you-use/iwyu_tool.py" \
|
|
-p "${BASE_BUILD_DIR}" "${MAKEJOBS}" \
|
|
-- -Xiwyu --cxx17ns -Xiwyu --mapping_file="${BASE_ROOT_DIR}/contrib/devtools/iwyu/bitcoin.core.imp" \
|
|
-Xiwyu --max_line_length=160 \
|
|
-Xiwyu --check_also="*/primitives/*.h" \
|
|
2>&1 | tee /tmp/iwyu_ci.out
|
|
python3 "/include-what-you-use/fix_includes.py" --nosafe_headers < /tmp/iwyu_ci.out
|
|
git diff -U1 | ./contrib/devtools/clang-format-diff.py -binary="clang-format-${TIDY_LLVM_V}" -p1 -i -v
|
|
}
|
|
|
|
run_iwyu "compile_commands_iwyu_errors.json"
|
|
if ! ( git --no-pager diff --exit-code ); then
|
|
echo "^^^ ⚠️ Failure generated from IWYU"
|
|
false
|
|
fi
|
|
|
|
run_iwyu "compile_commands_iwyu_warnings.json"
|
|
git --no-pager diff
|
|
fi
|
|
|
|
if [ "$RUN_FUZZ_TESTS" = "true" ]; then
|
|
# shellcheck disable=SC2086
|
|
LD_LIBRARY_PATH="${DEPENDS_DIR}/${HOST}/lib" \
|
|
"${BASE_BUILD_DIR}/test/fuzz/test_runner.py" \
|
|
${FUZZ_TESTS_CONFIG} \
|
|
"${MAKEJOBS}" \
|
|
-l DEBUG \
|
|
"${DIR_FUZZ_IN}" \
|
|
--empty_min_time=60
|
|
fi
|