diff --git a/.github/workflows/playwright-auto-rerun.yml b/.github/workflows/playwright-auto-rerun.yml index 0eab4a0764..43b28246f5 100644 --- a/.github/workflows/playwright-auto-rerun.yml +++ b/.github/workflows/playwright-auto-rerun.yml @@ -4,7 +4,9 @@ run-name: "Playwright Auto-Rerun - ${{ github.event.workflow_run.head_branch || on: workflow_run: - workflows: ["Playwright UI Tests"] + workflows: + - "Playwright UI Tests" + - "Playwright Regression Tests" types: - completed branches: diff --git a/.github/workflows/playwright.yml b/.github/workflows/playwright.yml index 439439e3c8..b7c2ad6036 100644 --- a/.github/workflows/playwright.yml +++ b/.github/workflows/playwright.yml @@ -1067,6 +1067,11 @@ jobs: TESTS: ${{ needs.ui_integration_tests.result }} MERGE_STATS: ${{ needs.merge_reports.outputs.stats }} MERGE_FLAKY: ${{ needs.merge_reports.outputs.flaky }} + # Branch + PR for per-test rows so the dashboard needs no cross-stream JOIN. + # head_ref is set on pull_request (the source branch); ref_name covers push + + # merge_group (gh-readonly-queue/main/pr--). PR empty on merge_group/push. + REPORT_BRANCH: ${{ github.head_ref || github.ref_name }} + REPORT_PR: ${{ github.event.pull_request.number }} run: | # This job runs only when tests actually ran (merge `if:` gates on !cancelled && # ui != skipped), so TESTS is success|failure here. @@ -1085,7 +1090,8 @@ jobs: FLAKY_FILE=$(mktemp "${TMPDIR:-/tmp}/flaky.XXXXXX") trap 'rm -f "$FLAKY_FILE"' EXIT printf '%s' "$FLAKY" | jq -c --arg run_id "$GITHUB_RUN_ID" --arg repo "$GITHUB_REPOSITORY" \ - '[.[] | {run_id:$run_id, repo:$repo, suite:"ui", workflow:"test", ingest_source:"live", status:.status, module:.module, test_title:.title, test_file:.file}]' \ + --arg branch "${REPORT_BRANCH:-}" --arg pr "${REPORT_PR:-}" \ + '[.[] | {run_id:$run_id, repo:$repo, suite:"ui", workflow:"test", ingest_source:"live", status:.status, module:.module, test_title:.title, test_file:.file, branch:(if $branch=="" then null else $branch end), pr_number:(if $pr=="" then null else ($pr|tonumber) end)}]' \ > "$FLAKY_FILE" 2>/dev/null || echo '[]' > "$FLAKY_FILE" if [ "$(jq 'length' "$FLAKY_FILE" 2>/dev/null || echo 0)" -gt 0 ]; then bash .github/scripts/o2-report.sh ci_test_results "$FLAKY_FILE" diff --git a/.github/workflows/playwright_regression.yml b/.github/workflows/playwright_regression.yml index 216c3925d6..51d66a9643 100644 --- a/.github/workflows/playwright_regression.yml +++ b/.github/workflows/playwright_regression.yml @@ -554,6 +554,9 @@ jobs: # Compact Playwright stats (expected/unexpected/flaky/skipped/duration) from the merged # report.json — consumed by the report_openobserve job to record reliability metrics. stats: ${{ steps.report_stats.outputs.stats }} + # One JSON array of flaky+failed tests (per-test rows) for the ci_test_results stream, + # so the unified UI+Regression dashboard's Latest-failures / Flakiest panels cover regression. + flaky: ${{ steps.report_flaky.outputs.flaky }} steps: - name: Clone the current repo @@ -658,6 +661,16 @@ jobs: echo "stats=$STATS" >> "$GITHUB_OUTPUT" echo "report stats: $STATS" + - name: Extract flaky/failed tests for OpenObserve + id: report_flaky + if: always() + run: | + # One JSON array of flaky+failed tests for the ci_test_results stream (per-test rows). + # Logic + schema live in extract-flaky.js; prints "[]" if the report is missing/clean. + FLAKY=$(node .github/scripts/extract-flaky.js tests/ui-testing/playwright-results/report.json) + printf 'flaky=%s\n' "$FLAKY" >> "$GITHUB_OUTPUT" + echo "report flaky count: $(printf '%s' "$FLAKY" | jq 'length' 2>/dev/null || echo '?')" + - name: Upload merged report if: always() uses: actions/upload-artifact@v4 @@ -805,6 +818,10 @@ jobs: UI_RESULT: ${{ needs.ui_integration_tests.result }} MERGE_RESULT: ${{ needs.merge_reports.result }} MERGE_STATS: ${{ needs.merge_reports.outputs.stats }} + MERGE_FLAKY: ${{ needs.merge_reports.outputs.flaky }} + # Branch + PR for per-test rows (ci_test_results), matching the UI workflow. + REPORT_BRANCH: ${{ github.head_ref || github.ref_name }} + REPORT_PR: ${{ github.event.pull_request.number }} run: | set -uo pipefail # Forks / unconfigured repos: skip entirely (no API call, no rate-limit spend). @@ -916,6 +933,10 @@ jobs: " > payload.json || { echo "::warning::payload build failed"; echo '{}' > payload.json; } bash .github/scripts/o2-report.sh ci_regression payload.json + # Also write the same run-level doc to ci_test_runs (already tagged suite=regression) so + # the unified UI+Regression dashboard drives one panel set off a `suite` variable. Additive: + # ci_regression keeps receiving the doc, so existing dashboards/crons are untouched. + bash .github/scripts/o2-report.sh ci_test_runs payload.json # Also emit one row per shard to the ci_regression_shards stream, flattened from # payload.shards (each = {name, conclusion, duration_sec}). Powers per-shard duration / @@ -927,17 +948,35 @@ jobs: # doc above (which also leaves it unset), keeping the two streams time-aligned. shards_json=$(jq -c --arg repo "$GITHUB_REPOSITORY" --arg run_id "$GITHUB_RUN_ID" \ '[.shards[]? | { - run_id: $run_id, repo: $repo, workflow: "regression", ingest_source: "live", + run_id: $run_id, repo: $repo, suite: "regression", workflow: "regression", ingest_source: "live", shard_name: .name, module: (.name | sub("^e2e / ";"") | sub("-Regression$";"") | if . == "" then "unknown" else . end), conclusion: .conclusion, duration_sec: .duration_sec }]' payload.json 2>/dev/null) && printf '%s' "$shards_json" > shards.json || echo '[]' > shards.json if [ "$(jq 'length' shards.json 2>/dev/null || echo 0)" -gt 0 ]; then bash .github/scripts/o2-report.sh ci_regression_shards shards.json + # Dual-write per-shard rows to the unified stream (now tagged suite=regression). + bash .github/scripts/o2-report.sh ci_test_runs_shards shards.json else echo "::notice::no shard rows to emit" fi + # Per-test flaky/failed rows -> ci_test_results (suite=regression), so the unified + # dashboard's Latest-failures / Flakiest panels cover regression too. Non-fatal; mirrors + # the UI workflow's block. branch + pr_number stamped so no cross-stream JOIN is needed. + FLAKY="${MERGE_FLAKY:-[]}" + if printf '%s' "$FLAKY" | jq -e 'type=="array" and length>0' >/dev/null 2>&1; then + FLAKY_FILE=$(mktemp "${TMPDIR:-/tmp}/flaky.XXXXXX") + trap 'rm -f "$FLAKY_FILE"' EXIT + printf '%s' "$FLAKY" | jq -c --arg run_id "$GITHUB_RUN_ID" --arg repo "$GITHUB_REPOSITORY" \ + --arg branch "${REPORT_BRANCH:-}" --arg pr "${REPORT_PR:-}" \ + '[.[] | {run_id:$run_id, repo:$repo, suite:"regression", workflow:"regression", ingest_source:"live", status:.status, module:.module, test_title:.title, test_file:.file, branch:(if $branch=="" then null else $branch end), pr_number:(if $pr=="" then null else ($pr|tonumber) end)}]' \ + > "$FLAKY_FILE" 2>/dev/null || echo '[]' > "$FLAKY_FILE" + if [ "$(jq 'length' "$FLAKY_FILE" 2>/dev/null || echo 0)" -gt 0 ]; then + bash .github/scripts/o2-report.sh ci_test_results "$FLAKY_FILE" + fi + fi + playwright_summary: timeout-minutes: 5 runs-on: