diff --git a/.github/workflows/build-src.yml b/.github/workflows/build-src.yml index 1383c4e219597..67a363975a45d 100644 --- a/.github/workflows/build-src.yml +++ b/.github/workflows/build-src.yml @@ -15,11 +15,17 @@ on: description: "Key needed to access cached depends" required: true type: string + outputs: + key: + description: "Key needed for restoring artifacts bundle" + value: ${{ jobs.build-src.outputs.key }} jobs: build-src: name: Build source runs-on: ubuntu-24.04 + outputs: + key: ${{ steps.bundle.outputs.key }} container: image: ${{ inputs.container-path }} options: --user root @@ -89,9 +95,20 @@ jobs: ./ci/dash/test_unittests.sh shell: bash - - name: Upload build artifacts + - name: Bundle artifacts + id: bundle + run: | + export BUILD_TARGET="${{ inputs.build-target }}" + export BUNDLE_KEY="build-${BUILD_TARGET}-$(git rev-parse --short=8 HEAD)" + ./ci/dash/bundle-artifacts.sh create + echo "key=${BUNDLE_KEY}" >> "${GITHUB_OUTPUT}" + + - name: Upload artifacts uses: actions/upload-artifact@v4 with: - name: build-artifacts-${{ inputs.build-target }} + name: ${{ steps.bundle.outputs.key }} path: | - /output + ${{ steps.bundle.outputs.key }}.tar.zst + compression-level: 0 + overwrite: true + retention-days: 3 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 6b14bf2dfa1ee..8b3ba89217800 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -154,3 +154,39 @@ jobs: build-target: win64 container-path: ${{ needs.container.outputs.path }} depends-key: ${{ needs.depends-win64.outputs.key }} + + test-linux64: + name: linux64-test + uses: ./.github/workflows/test-src.yml + needs: [container, depends-linux64, src-linux64] + with: + bundle-key: ${{ needs.src-linux64.outputs.key }} + build-target: linux64 + container-path: ${{ needs.container.outputs.path }} + + test-linux64_nowallet: + name: linux64_nowallet-test + uses: ./.github/workflows/test-src.yml + needs: [container, depends-linux64_nowallet, src-linux64_nowallet] + with: + bundle-key: ${{ needs.src-linux64_nowallet.outputs.key }} + build-target: linux64_nowallet + container-path: ${{ needs.container.outputs.path }} + + test-linux64_sqlite: + name: linux64_sqlite-test + uses: ./.github/workflows/test-src.yml + needs: [container, depends-linux64, src-linux64_sqlite] + with: + bundle-key: ${{ needs.src-linux64_sqlite.outputs.key }} + build-target: linux64_sqlite + container-path: ${{ needs.container.outputs.path }} + + test-linux64_ubsan: + name: linux64_ubsan-test + uses: ./.github/workflows/test-src.yml + needs: [container, depends-linux64, src-linux64_ubsan] + with: + bundle-key: ${{ needs.src-linux64_ubsan.outputs.key }} + build-target: linux64_ubsan + container-path: ${{ needs.container.outputs.path }} diff --git a/.github/workflows/test-src.yml b/.github/workflows/test-src.yml new file mode 100644 index 0000000000000..62e47d0152eee --- /dev/null +++ b/.github/workflows/test-src.yml @@ -0,0 +1,83 @@ +name: Test source + +on: + workflow_call: + inputs: + bundle-key: + description: "Key needed to access bundle of artifacts" + required: true + type: string + build-target: + description: "Target name as defined by inputs.sh" + required: true + type: string + container-path: + description: "Path to built container at registry" + required: true + type: string + +env: + INTEGRATION_TESTS_ARGS: "--extended --exclude feature_pruning,feature_dbcrash" + +jobs: + test-src: + name: Test source + runs-on: ubuntu-24.04 + container: + image: ${{ inputs.container-path }} + options: --user root + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + fetch-depth: 1 + + - name: Download build artifacts + uses: actions/download-artifact@v4 + with: + name: ${{ inputs.bundle-key }} + + - name: Manage releases cache + uses: actions/cache@v4 + if: inputs.build-target == 'linux64' + with: + path: | + releases + key: releases-${{ hashFiles('ci/test/00_setup_env_native_qt5.sh', 'test/get_previous_releases.py') }} + + - name: Run functional tests + id: test + run: | + git config --global --add safe.directory "$PWD" + export BUILD_TARGET="${{ inputs.build-target }}" + export BUNDLE_KEY="${{ inputs.bundle-key }}" + ./ci/dash/bundle-artifacts.sh extract + ./ci/dash/slim-workspace.sh + source ./ci/dash/matrix.sh + ./ci/dash/test_integrationtests.sh ${INTEGRATION_TESTS_ARGS} + shell: bash + + - name: Bundle test logs + id: bundle + if: success() || (failure() && steps.test.outcome == 'failure') + run: | + export BUILD_TARGET="${{ inputs.build-target }}" + echo "short-sha=$(git rev-parse --short=8 HEAD)" >> "${GITHUB_OUTPUT}" + ( [ -d "testlogs" ] && echo "upload-logs=true" >> "${GITHUB_OUTPUT}" && ./ci/dash/bundle-logs.sh ) \ + || echo "upload-logs=false" >> "${GITHUB_OUTPUT}" + shell: bash + + - name: Upload test logs + uses: actions/upload-artifact@v4 + if: | + success() || (failure() && steps.test.outcome == 'failure') + && steps.bundle.outputs.upload-logs == 'true' + with: + name: test_logs-${{ inputs.build-target }}-${{ steps.bundle.outputs.short-sha }} + path: | + test_logs-${{ inputs.build-target }}.tar.zst + test_logs-${{ inputs.build-target }}.tar.zst.sha256 + compression-level: 0 + overwrite: true + retention-days: 1 diff --git a/ci/dash/bundle-artifacts.sh b/ci/dash/bundle-artifacts.sh new file mode 100755 index 0000000000000..4dee647179334 --- /dev/null +++ b/ci/dash/bundle-artifacts.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +# Copyright (c) 2024-2025 The Dash 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 -eo pipefail + +SH_NAME="$(basename "${0}")" +VERB="${1}" + +if [ -z "${BUILD_TARGET}" ]; then + echo "${SH_NAME}: BUILD_TARGET not defined, cannot continue!"; + exit 1; +elif [ -z "${BUNDLE_KEY}" ]; then + echo "${SH_NAME}: BUNDLE_KEY not defined, cannot continue!"; + exit 1; +elif [ ! "$(command -v zstd)" ]; then + echo "${SH_NAME}: zstd not found, cannot continue!"; + exit 1; +elif [ -z "${VERB}" ]; then + echo "${SH_NAME}: Verb missing, acceptable values 'create' or 'extract'"; + exit 1; +elif [ "${VERB}" != "create" ] && [ "${VERB}" != "extract" ]; then + echo "${SH_NAME}: Invalid verb '${VERB}', expected 'create' or 'extract'"; + exit 1; +fi + +OUTPUT_ARCHIVE="${BUNDLE_KEY}.tar.zst" +if [ -f "${OUTPUT_ARCHIVE}" ] && [ "${VERB}" = "create" ]; then + echo "${SH_NAME}: ${OUTPUT_ARCHIVE} already exists, cannot continue!"; + exit 1; +elif [ ! -f "${OUTPUT_ARCHIVE}" ] && [ "${VERB}" = "extract" ]; then + echo "${SH_NAME}: ${OUTPUT_ARCHIVE} missing, cannot continue!"; + exit 1; +fi + +if [ "${VERB}" = "create" ]; then + EXCLUSIONS=( + "*.a" + "*.o" + ".deps" + ".libs" + ) + EXCLUSIONS_ARG="" + for excl in "${EXCLUSIONS[@]}" + do + EXCLUSIONS_ARG+=" --exclude=${excl}"; + done + + # shellcheck disable=SC2086 + tar ${EXCLUSIONS_ARG} --use-compress-program="zstd -T0 -5" -cf "${OUTPUT_ARCHIVE}" "build-ci"; +elif [ "${VERB}" = "extract" ]; then + tar --use-compress-program="unzstd" -xf "${OUTPUT_ARCHIVE}"; +else + echo "${SH_NAME}: Generic error"; + exit 1; +fi diff --git a/ci/dash/bundle-logs.sh b/ci/dash/bundle-logs.sh new file mode 100755 index 0000000000000..f2c022a7a9290 --- /dev/null +++ b/ci/dash/bundle-logs.sh @@ -0,0 +1,28 @@ +#!/usr/bin/env bash +# Copyright (c) 2025 The Dash 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 -eo pipefail + +SH_NAME="$(basename "${0}")" +LOG_DIRECTORY="testlogs" + +if [ ! -d "${LOG_DIRECTORY}" ]; then + echo "${SH_NAME}: '${LOG_DIRECTORY}' directory missing, will skip!"; + exit 0; +elif [ -z "${BUILD_TARGET}" ]; then + echo "${SH_NAME}: BUILD_TARGET not defined, cannot continue!"; + exit 1; +fi + +LOG_ARCHIVE="test_logs-${BUILD_TARGET}.tar.zst" +if [ -f "${LOG_ARCHIVE}" ]; then + echo "${SH_NAME}: ${LOG_ARCHIVE} already exists, cannot continue!"; + exit 1; +fi + +tar --use-compress-program="zstd -T0 -5" -cf "${LOG_ARCHIVE}" "${LOG_DIRECTORY}" +sha256sum "${LOG_ARCHIVE}" > "${LOG_ARCHIVE}.sha256"; diff --git a/ci/dash/slim-workspace.sh b/ci/dash/slim-workspace.sh new file mode 100755 index 0000000000000..1a3aa3a601896 --- /dev/null +++ b/ci/dash/slim-workspace.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# Copyright (c) 2025 The Dash 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 -eo pipefail + +SH_NAME="$(basename "${0}")" + +if [ -z "${BUILD_TARGET}" ]; then + echo "${SH_NAME}: BUILD_TARGET not defined, cannot continue!"; + exit 1; +elif [ -z "${BUNDLE_KEY}" ]; then + echo "${SH_NAME}: BUNDLE_KEY not defined, cannot continue!"; + exit 1; +fi + +TARGETS=( + # Bundle restored from artifact + "${BUNDLE_KEY}.tar.zst" + # Binaries not needed by functional tests + "build-ci/dashcore-${BUILD_TARGET}/src/dash-tx" + "build-ci/dashcore-${BUILD_TARGET}/src/bench/bench_dash" + "build-ci/dashcore-${BUILD_TARGET}/src/qt/dash-qt" + "build-ci/dashcore-${BUILD_TARGET}/src/qt/test/test_dash-qt" + "build-ci/dashcore-${BUILD_TARGET}/src/test/test_dash" + "build-ci/dashcore-${BUILD_TARGET}/src/test/fuzz/fuzz" + # Misc. files that can be heavy + "build-ci/dashcore-${BUILD_TARGET}/src/qt/qrc_bitcoin.cpp" + "build-ci/dashcore-${BUILD_TARGET}/src/qt/qrc_dash_locale.cpp" +) + +# Delete directories we don't need +for target in "${TARGETS[@]}" +do + if [[ -d "${target}" ]] || [[ -f "${target}" ]]; then + rm -rf "${target}"; + fi +done diff --git a/contrib/containers/ci/Dockerfile b/contrib/containers/ci/Dockerfile index d642ffc3984d9..cdce794c5731a 100644 --- a/contrib/containers/ci/Dockerfile +++ b/contrib/containers/ci/Dockerfile @@ -184,6 +184,7 @@ RUN apt-get update && apt-get install $APT_ARGS \ wine-stable \ wine64 \ zip \ + zstd \ && rm -rf /var/lib/apt/lists/* # Make sure std::thread and friends is available