From d9958cfe3bcbfedb25472711b71d42837522199d Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Mon, 19 Oct 2026 21:09:40 +0200 Subject: [PATCH 1/2] extra: ci_generate_report: only list failed tests in summary When a board has a FAILURE test (e.g. an empty test report), the summary listed all of its tests, including the passing ones with no issues, causing an IndexError on test.issues[0]. Only list the failed tests. Also fix a missing f-string prefix in the "empty test report" message. Co-Authored-By: Claude Opus 5.5 (1M context) --- extra/ci_collect_data.py | 2 +- extra/ci_generate_report.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extra/ci_collect_data.py b/extra/ci_collect_data.py index 321eb287e..a9d2b6d2f 100755 --- a/extra/ci_collect_data.py +++ b/extra/ci_collect_data.py @@ -174,7 +174,7 @@ def log_test(artifact, board, sketch, link_mode, exceptions, status, issues, job reports = report_data.get('boards', [{}])[0].get('sketches', []) if not reports: - log_test(artifact, board, 'CI test', '', [], FAILURE, "Test report for {link_mode} is empty, check CI log.", job_link) + log_test(artifact, board, 'CI test', '', [], FAILURE, f"Test report for {link_mode} is empty, check CI log.", job_link) continue # Skip to the next board # Iterate through individual sketch reports diff --git a/extra/ci_generate_report.py b/extra/ci_generate_report.py index 0ba7f1a14..00d4990e5 100755 --- a/extra/ci_generate_report.py +++ b/extra/ci_generate_report.py @@ -111,7 +111,7 @@ def print_summary(): f_print(f"{res.status.board_icon}") if res.status == FAILURE: f_print(f"") - f_print("
".join(f"{test.issues[0]} (full log)" for test in res.tests)) + f_print("
".join(f"{test.issues[0]} (full log)" for test in res.tests if test.status == FAILURE and test.issues)) f_print("") continue From 571e4811c07c550d41afc39cde1d2470b7c01fc8 Mon Sep 17 00:00:00 2001 From: Luca Burelli Date: Mon, 19 Oct 2026 21:16:45 +0200 Subject: [PATCH 2/2] ci: overwrite artifacts on re-run attempts Each re-run attempt uploads its artifacts with the same names as the previous attempts, and all copies stay in the run. download-artifact then picks the one with the highest artifact ID, which is not always the newest: a re-run could test a stale core package (e.g. missing a variant) or merge stale test reports. Set 'overwrite: true' on all uploads in package_core and package_tool, so that each name maps to a single artifact, the one from the latest attempt that produced it. Set 'name' to match the uploaded file name for archive:false uploads. In the case of the board binaries, apply the 'failed-' prefix to the tarball itself before uploading, so that the name matches the file. Reorder all upload flags to 'archive', 'overwrite', 'retention-days'. Co-Authored-By: Claude Opus 5.5 (1M context) --- .github/workflows/package_core.yml | 45 +++++++++++++++++++++--------- .github/workflows/package_tool.yml | 2 ++ 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/.github/workflows/package_core.yml b/.github/workflows/package_core.yml index 754d67f3b..d9f1a39e7 100644 --- a/.github/workflows/package_core.yml +++ b/.github/workflows/package_core.yml @@ -141,15 +141,17 @@ jobs: with: name: test-data path: test-data/ + overwrite: true retention-days: 1 - name: Archive build environment uses: actions/upload-artifact@v7 with: - name: build-env + name: build-env.tar.zstd path: ~/build-env.tar.zstd - retention-days: 1 archive: false + overwrite: true + retention-days: 1 @@ -245,8 +247,14 @@ jobs: ls reports/* >> $GITHUB_ENV echo "EOF" >> $GITHUB_ENV - # Preprare an archive of the built binaries (and build dir on failure) - [ "${{ job.status }}" == "failure" ] && FULL_BUILD_DIR="build/${{ matrix.variant }}/" + # Preprare an archive of the built binaries (and build dir on failure). + # Prefix the name with 'failed-' if the build failed, so that it is not removed. + BINARIES_FILE=binaries-${ARTIFACT_TAG}.tar.zstd + if [ "${{ job.status }}" == "failure" ] ; then + FULL_BUILD_DIR="build/${{ matrix.variant }}/" + BINARIES_FILE=failed-${BINARIES_FILE} + fi + echo "BINARIES_FILE=${BINARIES_FILE}" >> $GITHUB_ENV sed -e '/^#/d' boards.local.txt > boards.local_${{ matrix.variant }}.txt tar chf - \ firmwares/*${{ matrix.variant }}* \ @@ -254,17 +262,17 @@ jobs: boards.local_${{ matrix.variant }}.txt \ cores/arduino/api/ \ ${FULL_BUILD_DIR} \ - | zstd > binaries-${ARTIFACT_TAG}.tar.zstd + | zstd > ${BINARIES_FILE} - name: Archive board binaries if: ${{ steps.restore-env.outcome == 'success' && !cancelled() }} uses: actions/upload-artifact@v7 with: - # prefix the name with 'failed-' if the build failed, so that it is not removed - name: ${{ format('{0}binaries-{1}', (job.status == 'failure') && 'failed-' || '', env.ARTIFACT_TAG) }} - path: binaries-${{ env.ARTIFACT_TAG }}.tar.zstd - retention-days: 7 # for failed build inspection + name: ${{ env.BINARIES_FILE }} + path: ${{ env.BINARIES_FILE }} archive: false + overwrite: true + retention-days: 7 # for failed build inspection - name: Archive build reports if: ${{ steps.restore-env.outcome == 'success' && !cancelled() }} @@ -272,6 +280,7 @@ jobs: with: name: build-report-${{ env.ARTIFACT_TAG }} path: ${{ env.REPORT_FILES }} + overwrite: true retention-days: 1 @@ -330,6 +339,7 @@ jobs: name: ${{ env.CORE_ARTIFACT }} path: distrib/${{ env.CORE_ARTIFACT }} archive: false + overwrite: true - name: Archive artifact ID run: | @@ -339,6 +349,7 @@ jobs: with: name: artifact-id-${{ matrix.artifact }} path: ${{ matrix.artifact }}.id + overwrite: true @@ -408,6 +419,7 @@ jobs: name: ${{ env.PACKAGE_INDEX_FILE }} path: ${{ env.PACKAGE_INDEX_FILE }} archive: false + overwrite: true - name: Display final URL in the summary run: | @@ -539,6 +551,7 @@ jobs: with: name: test-report-${{ env.ARTIFACT_TAG }} path: sketches-reports/* + overwrite: true retention-days: 1 @@ -614,6 +627,7 @@ jobs: with: name: build-metadata path: build_info.json + overwrite: true retention-days: 1 # upload comment request artifact (will be retrieved by leave_pr_comment.yml) @@ -623,6 +637,7 @@ jobs: with: name: comment-request path: comment-request/ + overwrite: true retention-days: 1 # upload size delta report artifact (will be retrieved by report_size_deltas.yml) @@ -632,6 +647,7 @@ jobs: with: name: sketches-reports path: sketches-reports/ + overwrite: true retention-days: 1 # upload new official test size artifact (for AWS storage) @@ -639,19 +655,21 @@ jobs: uses: actions/upload-artifact@v7 if: ${{ github.event_name == 'push' }} with: - name: size-reports + name: size-reports-${{ needs.build-env.outputs.CORE_HASH }}.tar.bz2 path: size-reports-${{ needs.build-env.outputs.CORE_HASH }}.tar.bz2 - retention-days: 1 archive: false + overwrite: true + retention-days: 1 # upload input set of build reports artifact (for CI debugging) - name: Archive input test reports uses: actions/upload-artifact@v7 with: - name: build-reports + name: build-reports-${{ needs.build-env.outputs.CORE_HASH }}.tar.bz2 path: build-reports-${{ needs.build-env.outputs.CORE_HASH }}.tar.bz2 - retention-days: 1 archive: false + overwrite: true + retention-days: 1 # The last line makes the job fail if the 'result' file does not contain "PASSED". # No further actions are allowed in case of error. @@ -774,6 +792,7 @@ jobs: with: name: snippets-${{ env.CORE_TAG }} path: snippets/ + overwrite: true diff --git a/.github/workflows/package_tool.yml b/.github/workflows/package_tool.yml index bacd2afbd..c47683d59 100644 --- a/.github/workflows/package_tool.yml +++ b/.github/workflows/package_tool.yml @@ -127,6 +127,7 @@ jobs: path: | distrib/*.tar.gz distrib/*.zip + overwrite: true retention-days: 7 - name: Upload JSON snippet @@ -134,6 +135,7 @@ jobs: with: name: snippet-${{ matrix.tool }}-${{ matrix.version }} path: snippets/ + overwrite: true # Upload the built tool packages to the S3 bucket for public distribution.