From 3aac03ef8f28e78603b985eb59ed9ac5091eb3c5 Mon Sep 17 00:00:00 2001 From: jbrinkman Date: Tue, 9 Sep 2025 11:00:50 -0400 Subject: [PATCH 1/8] ci: add TRX logging and failures.json to matrix jobs; set run-name for scheduled/full-matrix; remove empty paths filters Signed-off-by: jbrinkman # Conflicts: # .github/workflows/tests.yml --- .github/workflows/tests.yml | 70 ++++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7cb38688..80d7a3d9 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -31,8 +31,8 @@ concurrency: cancel-in-progress: true run-name: - # Set custom name if job is started manually and name is given - ${{ github.event_name == 'workflow_dispatch' && (inputs.name == '' && format('{0} @ {1} {2}', github.ref_name, github.sha, toJson(inputs)) || inputs.name) || '' }} + # Use a distinct name for full-matrix or scheduled runs; otherwise keep manual-dispatch naming behavior + ${{ (github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && github.event.inputs['full-matrix'] == 'true')) && 'C# Matrix Tests' || (github.event_name == 'workflow_dispatch' && (inputs.name == '' && format('{0} @ {1} {2}', github.ref_name, github.sha, toJson(inputs)) || inputs.name)) || '' }} env: CARGO_TERM_COLOR: always @@ -98,7 +98,35 @@ jobs: key: rust-${{ matrix.host.TARGET }} - name: Test dotnet ${{ matrix.dotnet }} - run: dotnet test --configuration Debug --framework net${{ matrix.dotnet }} --logger "html;LogFileName=TestReport.html" --logger "console;verbosity=detailed" --results-directory . + run: dotnet test --configuration Debug --framework net${{ matrix.dotnet }} --logger "html;LogFileName=TestReport.html" --logger "trx;LogFileName=TestResults.trx" --logger "console;verbosity=detailed" --results-directory . + + - name: Derive failures.json (from TRX) + if: always() + shell: bash + run: | + set -euo pipefail + SUMMARY_FILE=failures.json + if command -v xmllint >/dev/null 2>&1 && command -v jq >/dev/null 2>&1; then + FAILED_COUNT=$(xmllint --xpath "string(//Counters/@failed)" TestResults.trx 2>/dev/null || echo 0) + PASSED_COUNT=$(xmllint --xpath "string(//Counters/@passed)" TestResults.trx 2>/dev/null || echo 0) + TOTAL_COUNT=$(xmllint --xpath "string(//Counters/@total)" TestResults.trx 2>/dev/null || echo 0) + SKIPPED_COUNT=$(xmllint --xpath "string(//Counters/@skipped)" TestResults.trx 2>/dev/null || echo 0) + echo "{" > "$SUMMARY_FILE" + echo " \"workflow\": \"C# tests\"," >> "$SUMMARY_FILE" + echo " \"runId\": ${GITHUB_RUN_ID}," >> "$SUMMARY_FILE" + echo " \"jobName\": \"net${{ matrix.dotnet }}, server ${{ matrix.server.version }}, ${{ matrix.host.TARGET }}\"," >> "$SUMMARY_FILE" + echo " \"matrix\": {" >> "$SUMMARY_FILE" + echo " \"dotnet\": \"${{ matrix.dotnet }}\"," >> "$SUMMARY_FILE" + echo " \"server\": { \"type\": \"${{ matrix.server.type }}\", \"version\": \"${{ matrix.server.version }}\" }," >> "$SUMMARY_FILE" + echo " \"host\": { \"OS\": \"${{ matrix.host.OS }}\", \"ARCH\": \"${{ matrix.host.ARCH }}\", \"RUNNER\": \"${{ matrix.host.RUNNER }}\" }" >> "$SUMMARY_FILE" + echo " }," >> "$SUMMARY_FILE" + echo " \"summary\": { \"total\": $TOTAL_COUNT, \"passed\": $PASSED_COUNT, \"failed\": $FAILED_COUNT, \"skipped\": $SKIPPED_COUNT }," >> "$SUMMARY_FILE" + echo " \"failed\": []," >> "$SUMMARY_FILE" + echo " \"links\": { \"runUrl\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\" }" >> "$SUMMARY_FILE" + echo "}" >> "$SUMMARY_FILE" + else + echo '{"workflow":"C# tests","summary":{"note":"Install xmllint+jq for rich failures"}}' > "$SUMMARY_FILE" + fi - name: Run benchmark if: ${{ contains(matrix.host.RUNNER, 'ubuntu') }} @@ -120,6 +148,8 @@ jobs: name: test-reports-dotnet-${{ matrix.dotnet }}-${{ matrix.server.type }}-${{ matrix.server.version }}-${{ matrix.host.OS }}-${{ matrix.host.ARCH }} path: | TestReport.html + TestResults.trx + failures.json valkey-glide/benchmarks/results/* valkey-glide/utils/clusters/** @@ -187,7 +217,37 @@ jobs: key: rust-${{ matrix.host.IMAGE }} - name: Test dotnet ${{ matrix.dotnet }} - run: dotnet test --framework net${{ matrix.dotnet }} --logger "html;LogFileName=TestReport.html" --logger "console;verbosity=detailed" --results-directory . + run: dotnet test --framework net${{ matrix.dotnet }} --logger "html;LogFileName=TestReport.html" --logger "trx;LogFileName=TestResults.trx" --logger "console;verbosity=detailed" --results-directory . + + - name: Derive failures.json (from TRX) + if: always() + shell: bash + run: | + set -euo pipefail + SUMMARY_FILE=failures.json + if command -v xmllint >/dev/null 2>&1 && command -v jq >/dev/null 2>&1; then + FAILED_COUNT=$(xmllint --xpath "string(//Counters/@failed)" TestResults.trx 2>/dev/null || echo 0) + PASSED_COUNT=$(xmllint --xpath "string(//Counters/@passed)" TestResults.trx 2>/dev/null || echo 0) + TOTAL_COUNT=$(xmllint --xpath "string(//Counters/@total)" TestResults.trx 2>/dev/null || echo 0) + SKIPPED_COUNT=$(xmllint --xpath "string(//Counters/@skipped)" TestResults.trx 2>/dev/null || echo 0) + cat > "$SUMMARY_FILE" << JSON + { + "workflow": "C# tests", + "runId": ${GITHUB_RUN_ID}, + "jobName": "net${{ matrix.dotnet }}, server ${{ matrix.server.version }}, ${{ matrix.host.TARGET }}", + "matrix": { + "dotnet": "${{ matrix.dotnet }}", + "server": { "type": "${{ matrix.server.type }}", "version": "${{ matrix.server.version }}" }, + "host": { "OS": "${{ matrix.host.OS }}", "ARCH": "${{ matrix.host.ARCH }}", "RUNNER": "${{ matrix.host.RUNNER }}" } + }, + "summary": { "total": $TOTAL_COUNT, "passed": $PASSED_COUNT, "failed": $FAILED_COUNT, "skipped": $SKIPPED_COUNT }, + "failed": [], + "links": { "runUrl": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" } + } + JSON + else + echo '{"workflow":"C# tests","summary":{"note":"Install xmllint+jq for rich failures"}}' > "$SUMMARY_FILE" + fi - name: Upload test reports if: always() @@ -197,6 +257,8 @@ jobs: name: test-reports-dotnet-${{ matrix.dotnet }}-${{ matrix.server.type }}-${{ matrix.server.version }}-${{ env.IMAGE }}-${{ matrix.host.ARCH }} path: | TestReport.html + TestResults.trx + failures.json valkey-glide/utils/clusters/** lint: From 1d520503eccaabb4610782f169511f4ccdddc383 Mon Sep 17 00:00:00 2001 From: jbrinkman Date: Tue, 9 Sep 2025 11:32:53 -0400 Subject: [PATCH 2/8] CI: add reporter workflow for nightly and manual full-matrix failures (aggregate artifacts and update rolling issue) Signed-off-by: jbrinkman --- .github/workflows/report-failures.yml | 108 ++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 .github/workflows/report-failures.yml diff --git a/.github/workflows/report-failures.yml b/.github/workflows/report-failures.yml new file mode 100644 index 00000000..84e74771 --- /dev/null +++ b/.github/workflows/report-failures.yml @@ -0,0 +1,108 @@ +name: C# failure reporter + +on: + workflow_run: + workflows: ["C# tests"] + types: [completed] + +permissions: + actions: read + contents: read + issues: write + +jobs: + report: + # Only handle scheduled runs or manual full-matrix runs ("C# Matrix Tests") that ended in failure + if: github.event.workflow_run.conclusion == 'failure' && (github.event.workflow_run.event == 'schedule' || github.event.workflow_run.display_title == 'C# Matrix Tests') + runs-on: ubuntu-latest + steps: + - name: Download artifacts from triggering run + uses: dawidd6/action-download-artifact@v6 + with: + run_id: ${{ github.event.workflow_run.id }} + path: downloaded + + - name: Aggregate failures + id: aggregate + shell: bash + run: | + set -euo pipefail + if ! command -v jq >/dev/null 2>&1; then + sudo apt-get update -y >/dev/null 2>&1 || true + sudo apt-get install -y jq >/dev/null 2>&1 || true + fi + shopt -s globstar nullglob + total_failed=0 + total_suites=0 + md='\n' + md+="# Nightly CI failures for ${{ github.repository }}\n\n" + md+="Triggered: ${{ github.event.workflow_run.run_started_at }} • [Run link](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }})\n\n" + found_any=0 + for f in downloaded/**/failures.json; do + found_any=1 + failed=$(jq -r '.summary.failed // 0' "$f" 2>/dev/null || echo 0) + total=$(jq -r '.summary.total // 0' "$f" 2>/dev/null || echo 0) + job=$(jq -r '.jobName // empty' "$f" 2>/dev/null || echo "") + [ -z "$job" ] && job=$(basename "$(dirname "$f")") + runUrl=$(jq -r '.links.runUrl // empty' "$f" 2>/dev/null || echo "") + total_failed=$((total_failed+failed)) + total_suites=$((total_suites+1)) + md+="- ${job}: ${failed}/${total} failed" + if [ -n "$runUrl" ]; then + md+=" — [run](${runUrl})" + fi + md+="\n" + done + if [ $found_any -eq 0 ]; then + md+="No failures.json artifacts were found to summarize.\n" + else + md+="\nTotal failed tests across ${total_suites} matrix jobs: ${total_failed}\n" + fi + printf "%b" "$md" > summary.md + echo "summary_path=$(pwd)/summary.md" >> "$GITHUB_OUTPUT" + echo "total_failed=${total_failed}" >> "$GITHUB_OUTPUT" + + - name: Find or create rolling failure issue + id: ensure_issue + uses: actions/github-script@v7 + env: + SUMMARY_PATH: ${{ steps.aggregate.outputs.summary_path }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const fs = require('fs'); + const body = fs.readFileSync(process.env.SUMMARY_PATH, 'utf8'); + const marker = ''; + const {owner, repo} = context.repo; + const label = 'ci-failure'; + const title = 'Nightly CI failures: C# tests'; + + // Ensure label exists? Assume it's created manually as per repo policy. + const {data: issues} = await github.rest.issues.listForRepo({ + owner, repo, state: 'open', labels: label, per_page: 100 + }); + let issue = issues.find(i => i.title === title); + + if (!issue) { + const created = await github.rest.issues.create({ + owner, repo, title, body, labels: [label] + }); + core.setOutput('issue_number', String(created.data.number)); + core.info(`Created issue #${created.data.number}`); + return; + } + + // Avoid duplicate comments for the same run using marker + const {data: comments} = await github.rest.issues.listComments({ + owner, repo, issue_number: issue.number, per_page: 100 + }); + const exists = comments.some(c => c.body && c.body.includes(marker)); + if (!exists) { + await github.rest.issues.createComment({ + owner, repo, issue_number: issue.number, body + }); + core.info(`Commented on issue #${issue.number}`); + } else { + core.info('A comment for this run already exists; skipping.'); + } + core.setOutput('issue_number', String(issue.number)); From 19f8cf8444dd6825bdf86191f2e230aff650514b Mon Sep 17 00:00:00 2001 From: jbrinkman Date: Tue, 9 Sep 2025 12:25:33 -0400 Subject: [PATCH 3/8] CI: fix container failures.json generation by replacing heredoc with echo JSON; keep TRX+artifact contract Signed-off-by: jbrinkman --- .github/workflows/tests.yml | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 80d7a3d9..7139b40e 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -230,21 +230,19 @@ jobs: PASSED_COUNT=$(xmllint --xpath "string(//Counters/@passed)" TestResults.trx 2>/dev/null || echo 0) TOTAL_COUNT=$(xmllint --xpath "string(//Counters/@total)" TestResults.trx 2>/dev/null || echo 0) SKIPPED_COUNT=$(xmllint --xpath "string(//Counters/@skipped)" TestResults.trx 2>/dev/null || echo 0) - cat > "$SUMMARY_FILE" << JSON - { - "workflow": "C# tests", - "runId": ${GITHUB_RUN_ID}, - "jobName": "net${{ matrix.dotnet }}, server ${{ matrix.server.version }}, ${{ matrix.host.TARGET }}", - "matrix": { - "dotnet": "${{ matrix.dotnet }}", - "server": { "type": "${{ matrix.server.type }}", "version": "${{ matrix.server.version }}" }, - "host": { "OS": "${{ matrix.host.OS }}", "ARCH": "${{ matrix.host.ARCH }}", "RUNNER": "${{ matrix.host.RUNNER }}" } - }, - "summary": { "total": $TOTAL_COUNT, "passed": $PASSED_COUNT, "failed": $FAILED_COUNT, "skipped": $SKIPPED_COUNT }, - "failed": [], - "links": { "runUrl": "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" } - } - JSON + echo "{" > "$SUMMARY_FILE" + echo " \"workflow\": \"C# tests\"," >> "$SUMMARY_FILE" + echo " \"runId\": ${GITHUB_RUN_ID}," >> "$SUMMARY_FILE" + echo " \"jobName\": \"net${{ matrix.dotnet }}, server ${{ matrix.server.version }}, ${{ matrix.host.TARGET }}\"," >> "$SUMMARY_FILE" + echo " \"matrix\": {" >> "$SUMMARY_FILE" + echo " \"dotnet\": \"${{ matrix.dotnet }}\"," >> "$SUMMARY_FILE" + echo " \"server\": { \"type\": \"${{ matrix.server.type }}\", \"version\": \"${{ matrix.server.version }}\" }," >> "$SUMMARY_FILE" + echo " \"host\": { \"OS\": \"${{ matrix.host.OS }}\", \"ARCH\": \"${{ matrix.host.ARCH }}\", \"RUNNER\": \"${{ matrix.host.RUNNER }}\" }" >> "$SUMMARY_FILE" + echo " }," >> "$SUMMARY_FILE" + echo " \"summary\": { \"total\": $TOTAL_COUNT, \"passed\": $PASSED_COUNT, \"failed\": $FAILED_COUNT, \"skipped\": $SKIPPED_COUNT }," >> "$SUMMARY_FILE" + echo " \"failed\": []," >> "$SUMMARY_FILE" + echo " \"links\": { \"runUrl\": \"${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}\" }" >> "$SUMMARY_FILE" + echo "}" >> "$SUMMARY_FILE" else echo '{"workflow":"C# tests","summary":{"note":"Install xmllint+jq for rich failures"}}' > "$SUMMARY_FILE" fi From e87123851fbce774f6c40a29b22ac1bc63a8e00d Mon Sep 17 00:00:00 2001 From: Joseph Brinkman Date: Tue, 9 Sep 2025 15:07:01 -0400 Subject: [PATCH 4/8] CI: add failure reporter for matrix-errors (#72) Signed-off-by: jbrinkman # Conflicts: # .github/workflows/report-failures.yml # Conflicts: # benchmarks/csharp_benchmark.csproj --- .github/workflows/report-failures.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/report-failures.yml b/.github/workflows/report-failures.yml index 84e74771..a54f72f8 100644 --- a/.github/workflows/report-failures.yml +++ b/.github/workflows/report-failures.yml @@ -4,6 +4,7 @@ on: workflow_run: workflows: ["C# tests"] types: [completed] + branches: [jbrinkman/matrix-errors] permissions: actions: read From f76d1c2667385fc5fe3a44b812567cf538822d41 Mon Sep 17 00:00:00 2001 From: jbrinkman Date: Tue, 9 Sep 2025 16:21:53 -0400 Subject: [PATCH 5/8] ci: reduce matrix for testing Signed-off-by: jbrinkman --- .github/json_matrices/server-matrix.json | 4 ---- .github/json_matrices/version-matrix.json | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/json_matrices/server-matrix.json b/.github/json_matrices/server-matrix.json index 53db4e89..ef94743d 100644 --- a/.github/json_matrices/server-matrix.json +++ b/.github/json_matrices/server-matrix.json @@ -9,10 +9,6 @@ "version": "8.1", "run": "always" }, - { - "type": "valkey", - "version": "8.0" - }, { "type": "valkey", "version": "7.2" diff --git a/.github/json_matrices/version-matrix.json b/.github/json_matrices/version-matrix.json index 6288027a..5e5e6988 100644 --- a/.github/json_matrices/version-matrix.json +++ b/.github/json_matrices/version-matrix.json @@ -1,4 +1,4 @@ { - "versions": ["8.0", "6.0"], + "versions": ["8.0"], "always-run-versions": ["8.0"] } From 7900aefa77888ecb033a46d8245e47b5e3158d84 Mon Sep 17 00:00:00 2001 From: jbrinkman Date: Tue, 9 Sep 2025 17:50:32 -0400 Subject: [PATCH 6/8] reporter: list only failing legs; parse TRX via xmlstarlet; restore job-level gating; always report even if no individual test failures (infra fail) Signed-off-by: jbrinkman --- .github/workflows/report-failures.yml | 109 +++++++++++++++++++------- 1 file changed, 80 insertions(+), 29 deletions(-) diff --git a/.github/workflows/report-failures.yml b/.github/workflows/report-failures.yml index a54f72f8..b64b0123 100644 --- a/.github/workflows/report-failures.yml +++ b/.github/workflows/report-failures.yml @@ -13,8 +13,8 @@ permissions: jobs: report: - # Only handle scheduled runs or manual full-matrix runs ("C# Matrix Tests") that ended in failure - if: github.event.workflow_run.conclusion == 'failure' && (github.event.workflow_run.event == 'schedule' || github.event.workflow_run.display_title == 'C# Matrix Tests') + # Only run this job when the triggering run failed and was schedule or workflow_dispatch + if: ${{ github.event.workflow_run.conclusion == 'failure' && (github.event.workflow_run.event == 'schedule' || github.event.workflow_run.event == 'workflow_dispatch') }} runs-on: ubuntu-latest steps: - name: Download artifacts from triggering run @@ -28,40 +28,91 @@ jobs: shell: bash run: | set -euo pipefail - if ! command -v jq >/dev/null 2>&1; then - sudo apt-get update -y >/dev/null 2>&1 || true - sudo apt-get install -y jq >/dev/null 2>&1 || true - fi - shopt -s globstar nullglob + sudo apt-get update -y >/dev/null 2>&1 || true + sudo apt-get install -y jq xmlstarlet >/dev/null 2>&1 || true + shopt -s nullglob + total_failed=0 - total_suites=0 - md='\n' - md+="# Nightly CI failures for ${{ github.repository }}\n\n" - md+="Triggered: ${{ github.event.workflow_run.run_started_at }} • [Run link](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }})\n\n" - found_any=0 - for f in downloaded/**/failures.json; do - found_any=1 - failed=$(jq -r '.summary.failed // 0' "$f" 2>/dev/null || echo 0) - total=$(jq -r '.summary.total // 0' "$f" 2>/dev/null || echo 0) - job=$(jq -r '.jobName // empty' "$f" 2>/dev/null || echo "") - [ -z "$job" ] && job=$(basename "$(dirname "$f")") - runUrl=$(jq -r '.links.runUrl // empty' "$f" 2>/dev/null || echo "") - total_failed=$((total_failed+failed)) - total_suites=$((total_suites+1)) - md+="- ${job}: ${failed}/${total} failed" - if [ -n "$runUrl" ]; then - md+=" — [run](${runUrl})" + total_legs=0 + failing_legs=0 + md=' + ' + md+="# Nightly CI failures for ${{ github.repository }} + "$'\n' + md+="Triggered: ${{ github.event.workflow_run.run_started_at }} • [Run link](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.event.workflow_run.id }}) + "$'\n\n' + md_details="" + + # Iterate each artifact folder downloaded + for dir in downloaded/*; do + [ -d "$dir" ] || continue + base="$(basename "$dir")" + case "$base" in + test-reports-*) ;; + *) continue ;; + esac + total_legs=$((total_legs+1)) + job_display="$base" + + # Prefer failures.json + fjson="$dir/failures.json" + failed=0; total=0 + if [ -f "$fjson" ]; then + failed=$(jq -r '.summary.failed // 0' "$fjson" 2>/dev/null || echo 0) + total=$(jq -r '.summary.total // 0' "$fjson" 2>/dev/null || echo 0) + fi + + # Fallback to TRX parse if counts are zero + if [ "$failed" = "0" ] && [ "$total" = "0" ]; then + trx=$(ls "$dir"/*.trx 2>/dev/null | head -n1 || true) + if [ -n "$trx" ]; then + total=$(xmlstarlet sel -T -t -v 'string(//*[local-name()="Counters"]/@total)' "$trx" 2>/dev/null || echo 0) + failed=$(xmlstarlet sel -T -t -v 'string(//*[local-name()="Counters"]/@failed)' "$trx" 2>/dev/null || echo 0) + fi + fi + + # Emit only failing legs with per-test bullets + if [ "$failed" != "0" ]; then + failing_legs=$((failing_legs+1)) + total_failed=$((total_failed+failed)) + md+="- ${job_display}: ${failed}/${total} failed\n" + # Try to get failed tests either from failures.json or directly from TRX + bullets="" + if [ -f "$fjson" ]; then + bullets=$(jq -r '.failed[]? | " - " + (.displayName // .fullyQualifiedName // .name // "(unknown)") + (if .errorMessage then " — " + .errorMessage else (if .message then " — " + .message else "" end) end)' "$fjson" 2>/dev/null || true) + fi + if [ -z "$bullets" ]; then + if [ -n "${trx:-}" ] && [ -f "$trx" ]; then + while IFS= read -r line; do + name="${line%%||*}" + msg="${line#*||}" + # Trim to first line and limit length + msg="${msg%%$'\n'*}" + if [ ${#msg} -gt 200 ]; then msg="${msg:0:197}..."; fi + echo " - ${name} — ${msg}" + done < <(xmlstarlet sel -T -t -m '//*[local-name()="UnitTestResult" and @outcome="Failed"]' -v 'concat(@testName,"||", normalize-space(.//*[local-name()="Message"]))' -n "$trx" 2>/dev/null || true) > "$dir/.bullets.txt" + bullets=$(cat "$dir/.bullets.txt" 2>/dev/null || true) + fi + fi + if [ -n "$bullets" ]; then + md_details+=$'\n' + md_details+="### ${job_display}\n\n" + md_details+="$bullets\n" + fi fi - md+="\n" done - if [ $found_any -eq 0 ]; then - md+="No failures.json artifacts were found to summarize.\n" - else - md+="\nTotal failed tests across ${total_suites} matrix jobs: ${total_failed}\n" + + if [ "$failing_legs" = "0" ]; then + md+="The pipeline failed, but no individual test failures were found. This may indicate a job or infrastructure failure.\n" fi + md+=$'\n' + md+="Total failed tests across ${failing_legs} of ${total_legs} matrix jobs: ${total_failed}\n\n" + md+="$md_details" + printf "%b" "$md" > summary.md echo "summary_path=$(pwd)/summary.md" >> "$GITHUB_OUTPUT" echo "total_failed=${total_failed}" >> "$GITHUB_OUTPUT" + echo "total_legs=${total_legs}" >> "$GITHUB_OUTPUT" - name: Find or create rolling failure issue id: ensure_issue From 6ac11b24242f579a83952af2f5e0fec5fb57ce9a Mon Sep 17 00:00:00 2001 From: jbrinkman Date: Tue, 9 Sep 2025 19:03:54 -0400 Subject: [PATCH 7/8] Revert "ci: reduce matrix for testing" This reverts commit 606a4539903bf2eab4331c8a87b125fb819f2baa. Signed-off-by: jbrinkman --- .github/json_matrices/server-matrix.json | 4 ++++ .github/json_matrices/version-matrix.json | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/json_matrices/server-matrix.json b/.github/json_matrices/server-matrix.json index ef94743d..53db4e89 100644 --- a/.github/json_matrices/server-matrix.json +++ b/.github/json_matrices/server-matrix.json @@ -9,6 +9,10 @@ "version": "8.1", "run": "always" }, + { + "type": "valkey", + "version": "8.0" + }, { "type": "valkey", "version": "7.2" diff --git a/.github/json_matrices/version-matrix.json b/.github/json_matrices/version-matrix.json index 5e5e6988..6288027a 100644 --- a/.github/json_matrices/version-matrix.json +++ b/.github/json_matrices/version-matrix.json @@ -1,4 +1,4 @@ { - "versions": ["8.0"], + "versions": ["8.0", "6.0"], "always-run-versions": ["8.0"] } From bd1c02b05daf8d4b0d1a5b4743aa916577f56ce5 Mon Sep 17 00:00:00 2001 From: jbrinkman Date: Wed, 10 Sep 2025 09:24:03 -0400 Subject: [PATCH 8/8] CI: add inputs.json artifact to tests and gate reporter on full-matrix via inputs (fallback to title) Signed-off-by: jbrinkman --- .github/workflows/report-failures.yml | 48 +++++++++++++++++++++++++++ .github/workflows/tests.yml | 29 +++++++++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/.github/workflows/report-failures.yml b/.github/workflows/report-failures.yml index b64b0123..bcec5592 100644 --- a/.github/workflows/report-failures.yml +++ b/.github/workflows/report-failures.yml @@ -17,8 +17,54 @@ jobs: if: ${{ github.event.workflow_run.conclusion == 'failure' && (github.event.workflow_run.event == 'schedule' || github.event.workflow_run.event == 'workflow_dispatch') }} runs-on: ubuntu-latest steps: + - name: Download inputs.json artifact (if present) + id: inputs + uses: dawidd6/action-download-artifact@v6 + continue-on-error: true + with: + run_id: ${{ github.event.workflow_run.id }} + name: inputs.json + path: inputs_artifact + + - name: Gate on full-matrix runs + id: gate + uses: actions/github-script@v7 + with: + github-token: ${{ github.token }} + script: | + const {owner, repo} = context.repo; + const runId = context.payload.workflow_run.id; + const event = context.payload.workflow_run.event; + const { data: run } = await github.rest.actions.getWorkflowRun({ owner, repo, run_id: runId }); + const title = run.display_title || run.name || ''; + // Prefer inputs.json when workflow_dispatch + let should = false; + if (event === 'schedule') { + should = true; + } else if (event === 'workflow_dispatch') { + try { + const fs = require('fs'); + const path = 'inputs_artifact/inputs.json'; + if (fs.existsSync(path)) { + const data = JSON.parse(fs.readFileSync(path, 'utf8')); + const fm = !!(data.inputs && data.inputs['full-matrix']); + should = fm; + core.info(`Gate via inputs.json: full-matrix=${fm}`); + } else { + core.info('inputs.json not found; falling back to title gate'); + should = title.startsWith('C# Matrix Tests'); + } + } catch (e) { + core.warning(`Failed to read inputs.json: ${e}`); + should = title.startsWith('C# Matrix Tests'); + } + } + core.info(`Trigger event: ${event}; run title: ${title}; should process: ${should}`); + return should; + - name: Download artifacts from triggering run uses: dawidd6/action-download-artifact@v6 + if: ${{ steps.gate.outputs.result == 'true' }} with: run_id: ${{ github.event.workflow_run.id }} path: downloaded @@ -26,6 +72,7 @@ jobs: - name: Aggregate failures id: aggregate shell: bash + if: ${{ steps.gate.outputs.result == 'true' }} run: | set -euo pipefail sudo apt-get update -y >/dev/null 2>&1 || true @@ -117,6 +164,7 @@ jobs: - name: Find or create rolling failure issue id: ensure_issue uses: actions/github-script@v7 + if: ${{ steps.gate.outputs.result == 'true' }} env: SUMMARY_PATH: ${{ steps.aggregate.outputs.summary_path }} with: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 7139b40e..8649d4a5 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -45,6 +45,33 @@ jobs: host-matrix-output: ${{ steps.get-matrices.outputs.os-matrix-output }} version-matrix-output: ${{ steps.get-matrices.outputs.version-matrix-output }} steps: + - name: Write inputs.json + uses: actions/github-script@v7 + with: + script: | + const fs = require('fs'); + fs.mkdirSync('.run-meta', {recursive: true}); + const event = context.eventName; + const out = {event}; + if (event === 'workflow_dispatch') { + const inputs = context.payload.inputs || {}; + const raw = inputs['full-matrix']; + const fm = (raw === true) || (String(raw).toLowerCase() === 'true'); + out.inputs = { + 'full-matrix': fm, + name: inputs.name || '' + }; + } + fs.writeFileSync('.run-meta/inputs.json', JSON.stringify(out)); + core.info(`inputs.json => ${JSON.stringify(out)}`); + + - name: Upload inputs.json + uses: actions/upload-artifact@v4 + with: + name: inputs.json + path: .run-meta/inputs.json + if-no-files-found: error + - uses: actions/checkout@v5 - id: get-matrices uses: ./.github/workflows/create-test-matrices @@ -252,7 +279,7 @@ jobs: continue-on-error: true uses: actions/upload-artifact@v4 with: - name: test-reports-dotnet-${{ matrix.dotnet }}-${{ matrix.server.type }}-${{ matrix.server.version }}-${{ env.IMAGE }}-${{ matrix.host.ARCH }} + name: test-reports-dotnet-${{ matrix.dotnet }}-${{ matrix.server.type }}-${{ matrix.server.version }}-${{ matrix.host.IMAGE }}-${{ matrix.host.ARCH }} path: | TestReport.html TestResults.trx