name: test # This reusable workflow structure was chosen for the sole purpose of working around # the 256 job per matrix limit. The initial total test job count was 290. This # approach shifts the 256 limit to be per OS rather than overall. A simpler single # regular workflow with matrixing against the OS would be preferred. on: workflow_call: inputs: os-emoji: required: true type: string matrix: required: true type: string name: required: true type: string file_name: required: true type: string concurrency-name: required: true type: string configuration: required: true type: string matrix_mode: required: true type: string runs-on: required: true type: string arch: required: true type: string arch-emoji: required: true type: string collect-junit: required: false type: boolean default: true concurrency: group: ${{ inputs.concurrency-name }}-${{ github.event_name == 'pull_request' && format('{0}-{1}', github.workflow_ref, github.event.pull_request.number) || github.run_id }} cancel-in-progress: true defaults: run: shell: bash jobs: test: name: ${{ matrix.os.emoji }} ${{ matrix.arch.emoji }} ${{ matrix.configuration.name }} - ${{ matrix.python.name }} runs-on: ${{ matrix.os.runs-on }} timeout-minutes: ${{ matrix.configuration.job_timeout }} strategy: fail-fast: false matrix: configuration: ${{ fromJson(inputs.configuration) }} os: - emoji: ${{ inputs.os-emoji }} matrix: ${{ inputs.matrix }} name: ${{ inputs.name }} file_name: ${{ inputs.file_name }} runs-on: ${{ inputs.runs-on }} arch: - matrix: ${{ inputs.arch }} emoji: ${{ inputs.arch-emoji }} python: - name: "3.10" file_name: "3.10" action: "3.10" apt: "3.10" install_sh: "3.10" matrix: "3.10" exclude_from: limited: True main: True - name: "3.11" file_name: "3.11" action: "3.11" apt: "3.11" install_sh: "3.11" matrix: "3.11" exclude_from: limited: True main: True - name: "3.12" file_name: "3.12" action: "3.12" apt: "3.12" install_sh: "3.12" matrix: "3.12" - name: "3.13" file_name: "3.13" action: "3.13" apt: "3.13" install_sh: "3.13" matrix: "3.13" exclude_from: limited: True main: True exclude: - arch: matrix: arm configuration: install_timelord: true - os: matrix: windows configuration: install_timelord: true - os: matrix: windows configuration: name: core.full_node # TODO: skipping macos-15-intel timelord cases until fixed # https://github.com/Chia-Network/chiavdf/pull/268 - os: matrix: macos-intel configuration: install_timelord: true - python: exclude_from: ${{ inputs.matrix_mode }}: True env: CHIA_ROOT: ${{ github.workspace }}/.chia/mainnet CHIA_SIMULATOR_ROOT: ${{ github.workspace }}/.chia/simulator JOB_FILE_NAME: tests_${{ matrix.os.file_name }}_python-${{ matrix.python.file_name }}_${{ matrix.configuration.module_import_path }}${{ matrix.configuration.file_name_index }} BLOCKS_AND_PLOTS_VERSION: 0.44.0 steps: - name: Configure git run: | git config --global core.autocrlf false - name: Checkout code uses: actions/checkout@v5 with: fetch-depth: 0 - name: Set Env uses: Chia-Network/actions/setjobenv@main env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Setup Python environment uses: Chia-Network/actions/setup-python@main with: python-version: ${{ matrix.python.action }} - name: Create keychain for CI use (macOS) if: matrix.os.matrix == 'macos' run: | security create-keychain -p foo chiachain security default-keychain -s chiachain security unlock-keychain -p foo chiachain security set-keychain-settings -t 7200 -u chiachain - name: Cache npm (Ubuntu) if: matrix.os.matrix == 'ubuntu' uses: actions/cache@v4 env: SEGMENT_DOWNLOAD_TIMEOUT_MIN: 1 with: path: ~/.npm key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }} restore-keys: | ${{ runner.os }}-node- - uses: chia-network/actions/cache-pip@main with: mode: poetry - name: Cache test blocks and plots if: matrix.configuration.checkout_blocks_and_plots uses: actions/cache@v4 env: SEGMENT_DOWNLOAD_TIMEOUT_MIN: 1 id: test-blocks-plots with: path: | ${{ github.workspace }}/.chia/blocks ${{ github.workspace }}/.chia/test-plots ${{ github.workspace }}/.chia/test-bundles key: ${{ env.BLOCKS_AND_PLOTS_VERSION }} - name: Checkout test blocks and plots if: matrix.configuration.checkout_blocks_and_plots && steps.test-blocks-plots.outputs.cache-hit != 'true' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh release download -R Chia-Network/test-cache ${{ env.BLOCKS_AND_PLOTS_VERSION }} --archive=tar.gz -O - | tar xzf - mkdir "${GITHUB_WORKSPACE}/.chia" mv "${GITHUB_WORKSPACE}/test-cache-${{ env.BLOCKS_AND_PLOTS_VERSION }}/"* "${GITHUB_WORKSPACE}/.chia" - uses: ./.github/actions/install with: python-version: ${{ matrix.python.install_sh }} development: true editable: false legacy_keyring: ${{ matrix.configuration.legacy_keyring_required }} - uses: chia-network/actions/activate-venv@main - name: Install timelord if: matrix.configuration.install_timelord run: | sh install-timelord.sh -n ./vdf_bench square_asm 400000 - name: Verify source and installed tests collect and match run: | echo '==== collecting source tests ====' if pytest --collect-only -qq --import-mode=prepend chia/_tests/ > source_tests_raw then cat source_tests_raw | sed -n 's;^\(chia/_tests/.*\);\1;p' | sort > source_tests else echo ' ==== source test collection failure' cat source_tests_raw exit 1 fi echo '==== collecting installed tests ====' if pytest --collect-only -qq --import-mode=append --pyargs chia._tests > installed_tests_raw then cat installed_tests_raw | sed -n 's;^\.venv/.*/\(chia/_tests/.*\);\1;p' | sort > installed_tests else echo ' ==== installed test collection failure' cat installed_tests_raw exit 1 fi echo '==== collected tests ====' for mode in source installed do echo "::group::collected ${mode} tests" cat ${mode}_tests echo '::endgroup::' done echo '==== diffing collected tests ====' echo "::group::collected tests diff" diff --unified source_tests installed_tests; DIFF_EXIT_CODE=$? echo '::endgroup::' exit $DIFF_EXIT_CODE - name: Move chia/ so we test the installed code run: | mv chia/ notchia/ - name: Test blockchain code with pytest with windows and 3.13 and reruns if: matrix.os.name == 'windows' && matrix.python.name == '3.13' run: | pytest --reruns 1 --cov=chia --cov-config=.coveragerc --cov-report= -o 'junit_suite_name=${{ env.JOB_FILE_NAME }}' --junitxml='junit-data/junit.${{ env.JOB_FILE_NAME }}.xml' --durations=10 ${{ matrix.configuration.pytest_parallel_args[matrix.os.matrix] }} -m "not benchmark" ${{ env.ENABLE_PYTEST_MONITOR }} ${{ matrix.configuration.test_files }} - name: Test blockchain code with pytest if: ${{ !(matrix.os.name == 'windows' && matrix.python.name == '3.13') }} env: ENABLE_PYTEST_MONITOR: ${{ matrix.os.matrix == 'ubuntu' && matrix.configuration.enable_pytest_monitor || '' }} run: | pytest --cov=chia --cov-config=.coveragerc --cov-report= -o 'junit_suite_name=${{ env.JOB_FILE_NAME }}' --junitxml='junit-data/junit.${{ env.JOB_FILE_NAME }}.xml' --durations=10 ${{ matrix.configuration.pytest_parallel_args[matrix.os.matrix] }} -m "not benchmark" ${{ env.ENABLE_PYTEST_MONITOR }} ${{ matrix.configuration.test_files }} - name: Move back to chia/ for coverage run: | mv notchia/ chia/ - name: Publish JUnit results if: inputs.collect-junit uses: actions/upload-artifact@v5 with: name: junit-data-${{ env.JOB_FILE_NAME }} path: junit-data/* if-no-files-found: error - name: Process coverage data run: | coverage xml --rcfile=.coveragerc -o coverage.xml mkdir coverage-data cp .coverage "coverage-data/.coverage.${{ env.JOB_FILE_NAME }}" cp coverage.xml "coverage-data/coverage.${{ env.JOB_FILE_NAME }}.xml" coverage report --rcfile=.coveragerc --show-missing - name: Publish coverage data uses: actions/upload-artifact@v5 with: name: coverage-data-${{ env.JOB_FILE_NAME }} path: coverage-data/* include-hidden-files: true if-no-files-found: error - name: Check resource usage if: matrix.os.matrix == 'ubuntu' && matrix.configuration.check_resource_usage run: | sqlite3 -readonly -separator " " .pymon "select item,cpu_usage,total_time,mem_usage from TEST_METRICS order by mem_usage desc;" >metrics.out ./chia/_tests/check_pytest_monitor_output.py