From 9a6daa50ee1cca7e3c582f8271e28a32131ea839 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Tue, 9 Dec 2025 17:53:46 +0100 Subject: [PATCH 1/5] CI: consolidate GLOBAL_PYTEST_OPTS into PYTEST_OPTS_BASE. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces GLOBAL_PYTEST_OPTS with PYTEST_OPTS_BASE that includes all common pytest options: --reruns=10, -vvv, --junit-xml=report.xml, --timeout=1800, and --durations=10. Removes redundant option specifications from individual jobs and simplifies pytest command invocations by removing direct references to GLOBAL_PYTEST_OPTS (now inherited via PYTEST_OPTS). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 Changelog-None --- .github/workflows/ci.yaml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 535afd2b8e92..5f13f7edd82d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -16,7 +16,7 @@ env: RUST_PROFILE: release SLOW_MACHINE: 1 CI_SERVER_URL: "http://35.239.136.52:3170" - GLOBAL_PYTEST_OPTS: "--reruns=10 -vvv" + PYTEST_OPTS_BASE: "--reruns=10 -vvv --junit-xml=report.xml --timeout=1800 --durations=10" jobs: prebuild: @@ -90,7 +90,7 @@ jobs: - name: Check source env: VALGRIND: 0 - PYTEST_OPTS: --timeout=1200 --durations=10 + PYTEST_OPTS: ${{ env.PYTEST_OPTS_BASE }} run: | uv run make check-source BASE_REF="origin/${{ github.base_ref }}" - name: Check Generated Files have been updated @@ -314,7 +314,7 @@ jobs: run: | env cat config.vars - uv run eatmydata pytest tests/test_downgrade.py ${GLOBAL_PYTEST_OPTS} -n ${PYTEST_PAR} ${PYTEST_OPTS} + uv run eatmydata pytest tests/test_downgrade.py -n ${PYTEST_PAR} ${PYTEST_OPTS} integration: name: Test CLN ${{ matrix.name }} @@ -322,7 +322,7 @@ jobs: timeout-minutes: 120 env: RUST_PROFILE: release # Has to match the one in the compile step - PYTEST_OPTS: --timeout=1200 --durations=10 + PYTEST_OPTS: ${{ env.PYTEST_OPTS_BASE }} needs: - compile strategy: @@ -422,7 +422,7 @@ jobs: run: | env cat config.vars - VALGRIND=0 uv run eatmydata pytest tests/ -vvv ${GLOBAL_PYTEST_OPTS} -n ${PYTEST_PAR} ${PYTEST_OPTS} + VALGRIND=0 uv run eatmydata pytest tests/ -n ${PYTEST_PAR} ${PYTEST_OPTS} integration-valgrind: name: Valgrind Test CLN ${{ matrix.name }} @@ -431,7 +431,7 @@ jobs: env: RUST_PROFILE: release # Has to match the one in the compile step CFG: compile-gcc - PYTEST_OPTS: --test-group-random-seed=42 --timeout=1800 --durations=10 --reruns=10 + PYTEST_OPTS: ${{ env.PYTEST_OPTS_BASE }} --test-group-random-seed=42 needs: - compile strategy: @@ -492,7 +492,7 @@ jobs: SLOW_MACHINE: 1 TEST_DEBUG: 1 run: | - VALGRIND=1 uv run eatmydata pytest tests/ ${GLOBAL_PYTEST_OPTS} -n 3 ${PYTEST_OPTS} ${{ matrix.PYTEST_OPTS }} + VALGRIND=1 uv run eatmydata pytest tests/ -n 3 ${PYTEST_OPTS} ${{ matrix.PYTEST_OPTS }} integration-sanitizers: name: Sanitizers Test CLN @@ -502,7 +502,7 @@ jobs: RUST_PROFILE: release SLOW_MACHINE: 1 TEST_DEBUG: 1 - PYTEST_OPTS: --test-group-random-seed=42 --timeout=1800 --durations=10 --reruns=10 + PYTEST_OPTS: ${{ env.PYTEST_OPTS_BASE }} --test-group-random-seed=42 needs: - compile strategy: @@ -562,7 +562,7 @@ jobs: - name: Test run: | - uv run eatmydata pytest tests/ ${GLOBAL_PYTEST_OPTS} -n 2 ${PYTEST_OPTS} ${{ matrix.PYTEST_OPTS }} + uv run eatmydata pytest tests/ -n 2 ${PYTEST_OPTS} ${{ matrix.PYTEST_OPTS }} update-docs-examples: name: Update examples in doc schemas (disabled temporarily!) @@ -574,7 +574,7 @@ jobs: env: VALGRIND: 0 GENERATE_EXAMPLES: 1 - PYTEST_OPTS: --timeout=1200 --durations=10 + PYTEST_OPTS: ${{ env.PYTEST_OPTS_BASE }} TEST_NETWORK: regtest needs: - compile @@ -613,7 +613,7 @@ jobs: timeout-minutes: 120 env: RUST_PROFILE: release # Has to match the one in the compile step - PYTEST_OPTS: --timeout=1200 --durations=10 + PYTEST_OPTS: ${{ env.PYTEST_OPTS_BASE }} needs: - compile strategy: @@ -679,7 +679,7 @@ jobs: run: | env cat config.vars - VALGRIND=0 uv run eatmydata pytest tests/ ${GLOBAL_PYTEST_OPTS} -n ${PYTEST_PAR} ${PYTEST_OPTS} + VALGRIND=0 uv run eatmydata pytest tests/ -n ${PYTEST_PAR} ${PYTEST_OPTS} gather: From e879770ed3e72e0517710df251c1415f6430a999 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Tue, 9 Dec 2025 18:00:14 +0100 Subject: [PATCH 2/5] CI: add artifact upload for pytest JUnit XML reports. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds upload-artifact steps after each test run to preserve test results as GitHub artifacts. Each job uploads its report.xml with a unique name based on the job and matrix configuration. Artifacts are uploaded even when tests fail (if: always()) to ensure test results are available for debugging. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- .github/workflows/ci.yaml | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 5f13f7edd82d..3bd67893a106 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -93,6 +93,13 @@ jobs: PYTEST_OPTS: ${{ env.PYTEST_OPTS_BASE }} run: | uv run make check-source BASE_REF="origin/${{ github.base_ref }}" + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: pytest-results-prebuild + path: report.xml + if-no-files-found: ignore - name: Check Generated Files have been updated run: uv run make check-gen-updated - name: Check docs @@ -315,6 +322,13 @@ jobs: env cat config.vars uv run eatmydata pytest tests/test_downgrade.py -n ${PYTEST_PAR} ${PYTEST_OPTS} + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: pytest-results-check-downgrade-${{ matrix.TEST_DB_PROVIDER }}-${{ matrix.TEST_NETWORK }} + path: report.xml + if-no-files-found: ignore integration: name: Test CLN ${{ matrix.name }} @@ -423,6 +437,13 @@ jobs: env cat config.vars VALGRIND=0 uv run eatmydata pytest tests/ -n ${PYTEST_PAR} ${PYTEST_OPTS} + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: pytest-results-integration-${{ matrix.name }} + path: report.xml + if-no-files-found: ignore integration-valgrind: name: Valgrind Test CLN ${{ matrix.name }} @@ -493,6 +514,13 @@ jobs: TEST_DEBUG: 1 run: | VALGRIND=1 uv run eatmydata pytest tests/ -n 3 ${PYTEST_OPTS} ${{ matrix.PYTEST_OPTS }} + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: pytest-results-integration-valgrind-${{ matrix.NAME }} + path: report.xml + if-no-files-found: ignore integration-sanitizers: name: Sanitizers Test CLN @@ -563,6 +591,13 @@ jobs: - name: Test run: | uv run eatmydata pytest tests/ -n 2 ${PYTEST_OPTS} ${{ matrix.PYTEST_OPTS }} + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: pytest-results-integration-sanitizers-${{ matrix.NAME }} + path: report.xml + if-no-files-found: ignore update-docs-examples: name: Update examples in doc schemas (disabled temporarily!) @@ -606,6 +641,13 @@ jobs: - name: Test run: | uv run eatmydata make -j $(nproc) check-doc-examples + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: pytest-results-update-docs-examples + path: report.xml + if-no-files-found: ignore min-btc-support: name: Test minimum supported BTC v${{ matrix.MIN_BTC_VERSION }} with ${{ matrix.NAME }} @@ -680,6 +722,13 @@ jobs: env cat config.vars VALGRIND=0 uv run eatmydata pytest tests/ -n ${PYTEST_PAR} ${PYTEST_OPTS} + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: pytest-results-min-btc-support-${{ matrix.NAME }} + path: report.xml + if-no-files-found: ignore gather: From b28df79cc40303410a5f48bb680d5218ef6df6c5 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Tue, 9 Dec 2025 18:06:44 +0100 Subject: [PATCH 3/5] CI: fix env context reference in job-level env sections. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GitHub Actions doesn't allow referencing workflow-level env variables from job-level env sections. Fixed by: - Replacing ${{ env.PYTEST_OPTS_BASE }} with full values in job-level env - Keeping ${{ env.PYTEST_OPTS_BASE }} in step-level env (which is valid) This resolves the "Unrecognized named-value: 'env'" errors. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 --- .github/workflows/ci.yaml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 3bd67893a106..7ccc73612c89 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -318,6 +318,7 @@ jobs: LIGHTNINGD_POSTGRES_NO_VACUUM: 1 VALGRIND: ${{ matrix.VALGRIND }} PREV_LIGHTNINGD: /tmp/old-cln/usr/bin/lightningd + PYTEST_OPTS: ${{ env.PYTEST_OPTS_BASE }} run: | env cat config.vars @@ -336,7 +337,7 @@ jobs: timeout-minutes: 120 env: RUST_PROFILE: release # Has to match the one in the compile step - PYTEST_OPTS: ${{ env.PYTEST_OPTS_BASE }} + PYTEST_OPTS: --reruns=10 -vvv --junit-xml=report.xml --timeout=1800 --durations=10 needs: - compile strategy: @@ -452,7 +453,7 @@ jobs: env: RUST_PROFILE: release # Has to match the one in the compile step CFG: compile-gcc - PYTEST_OPTS: ${{ env.PYTEST_OPTS_BASE }} --test-group-random-seed=42 + PYTEST_OPTS: --reruns=10 -vvv --junit-xml=report.xml --timeout=1800 --durations=10 --test-group-random-seed=42 needs: - compile strategy: @@ -530,7 +531,7 @@ jobs: RUST_PROFILE: release SLOW_MACHINE: 1 TEST_DEBUG: 1 - PYTEST_OPTS: ${{ env.PYTEST_OPTS_BASE }} --test-group-random-seed=42 + PYTEST_OPTS: --reruns=10 -vvv --junit-xml=report.xml --timeout=1800 --durations=10 --test-group-random-seed=42 needs: - compile strategy: @@ -609,7 +610,7 @@ jobs: env: VALGRIND: 0 GENERATE_EXAMPLES: 1 - PYTEST_OPTS: ${{ env.PYTEST_OPTS_BASE }} + PYTEST_OPTS: --reruns=10 -vvv --junit-xml=report.xml --timeout=1800 --durations=10 TEST_NETWORK: regtest needs: - compile @@ -655,7 +656,7 @@ jobs: timeout-minutes: 120 env: RUST_PROFILE: release # Has to match the one in the compile step - PYTEST_OPTS: ${{ env.PYTEST_OPTS_BASE }} + PYTEST_OPTS: --reruns=10 -vvv --junit-xml=report.xml --timeout=1800 --durations=10 needs: - compile strategy: From 414c24bc5e39b07af135a99e5fbb789377a5eda5 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Mon, 15 Dec 2025 15:50:27 +0100 Subject: [PATCH 4/5] fix: sanitize artifact names to handle special characters in matrix vars MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The valgrind and sanitizer test matrix names contain parentheses and slashes (e.g., 'Valgrind (01/10)', 'ASan/UBSan (01/12)') which are invalid in artifact filenames. Replace these characters with hyphens to ensure reliable artifact uploads. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Haiku 4.5 --- .github/workflows/ci.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7ccc73612c89..64ac88d7c1ae 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -519,7 +519,7 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: pytest-results-integration-valgrind-${{ matrix.NAME }} + name: pytest-results-integration-valgrind-${{ replace(replace(replace(matrix.NAME, '/', '-'), '(', '-'), ')', '') }} path: report.xml if-no-files-found: ignore @@ -596,7 +596,7 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: pytest-results-integration-sanitizers-${{ matrix.NAME }} + name: pytest-results-integration-sanitizers-${{ replace(replace(replace(matrix.NAME, '/', '-'), '(', '-'), ')', '') }} path: report.xml if-no-files-found: ignore From f9029ab290a671ef26961e4f7e8acc45f84af3df Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Mon, 15 Dec 2025 15:55:17 +0100 Subject: [PATCH 5/5] refactor: use GROUP variable for artifact names instead of sanitizing NAME MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a GROUP matrix variable to valgrind and sanitizer test configurations with simple numeric values. Use matrix.GROUP in artifact names instead of sanitizing the descriptive NAME, which contains special characters. This is cleaner and more maintainable than string replacement logic. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Haiku 4.5 --- .github/workflows/ci.yaml | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 64ac88d7c1ae..53d45a71a384 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -461,24 +461,34 @@ jobs: matrix: include: - NAME: Valgrind (01/10) + GROUP: 1 PYTEST_OPTS: --test-group=1 --test-group-count=10 - NAME: Valgrind (02/10) + GROUP: 2 PYTEST_OPTS: --test-group=2 --test-group-count=10 - NAME: Valgrind (03/10) + GROUP: 3 PYTEST_OPTS: --test-group=3 --test-group-count=10 - NAME: Valgrind (04/10) + GROUP: 4 PYTEST_OPTS: --test-group=4 --test-group-count=10 - NAME: Valgrind (05/10) + GROUP: 5 PYTEST_OPTS: --test-group=5 --test-group-count=10 - NAME: Valgrind (06/10) + GROUP: 6 PYTEST_OPTS: --test-group=6 --test-group-count=10 - NAME: Valgrind (07/10) + GROUP: 7 PYTEST_OPTS: --test-group=7 --test-group-count=10 - NAME: Valgrind (08/10) + GROUP: 8 PYTEST_OPTS: --test-group=8 --test-group-count=10 - NAME: Valgrind (09/10) + GROUP: 9 PYTEST_OPTS: --test-group=9 --test-group-count=10 - NAME: Valgrind (10/10) + GROUP: 10 PYTEST_OPTS: --test-group=10 --test-group-count=10 steps: - name: Checkout @@ -519,7 +529,7 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: pytest-results-integration-valgrind-${{ replace(replace(replace(matrix.NAME, '/', '-'), '(', '-'), ')', '') }} + name: pytest-results-integration-valgrind-${{ matrix.GROUP }} path: report.xml if-no-files-found: ignore @@ -539,28 +549,40 @@ jobs: matrix: include: - NAME: ASan/UBSan (01/12) + GROUP: 1 PYTEST_OPTS: --test-group=1 --test-group-count=12 - NAME: ASan/UBSan (02/12) + GROUP: 2 PYTEST_OPTS: --test-group=2 --test-group-count=12 -n 1 - NAME: ASan/UBSan (03/12) + GROUP: 3 PYTEST_OPTS: --test-group=3 --test-group-count=12 - NAME: ASan/UBSan (04/12) + GROUP: 4 PYTEST_OPTS: --test-group=4 --test-group-count=12 - NAME: ASan/UBSan (05/12) + GROUP: 5 PYTEST_OPTS: --test-group=5 --test-group-count=12 - NAME: ASan/UBSan (06/12) + GROUP: 6 PYTEST_OPTS: --test-group=6 --test-group-count=12 - NAME: ASan/UBSan (07/12) + GROUP: 7 PYTEST_OPTS: --test-group=7 --test-group-count=12 - NAME: ASan/UBSan (08/12) + GROUP: 8 PYTEST_OPTS: --test-group=8 --test-group-count=12 - NAME: ASan/UBSan (09/12) + GROUP: 9 PYTEST_OPTS: --test-group=9 --test-group-count=12 - NAME: ASan/UBSan (10/12) + GROUP: 10 PYTEST_OPTS: --test-group=10 --test-group-count=12 - NAME: ASan/UBSan (11/12) + GROUP: 11 PYTEST_OPTS: --test-group=11 --test-group-count=12 - NAME: ASan/UBSan (12/12) + GROUP: 12 PYTEST_OPTS: --test-group=12 --test-group-count=12 steps: - name: Checkout @@ -596,7 +618,7 @@ jobs: if: always() uses: actions/upload-artifact@v4 with: - name: pytest-results-integration-sanitizers-${{ replace(replace(replace(matrix.NAME, '/', '-'), '(', '-'), ')', '') }} + name: pytest-results-integration-sanitizers-${{ matrix.GROUP }} path: report.xml if-no-files-found: ignore