From ca3d24f5ea289f155ad7ae8f56b268d57cf874b2 Mon Sep 17 00:00:00 2001 From: Swung0x48 Date: Tue, 11 Aug 2026 19:30:38 -0400 Subject: [PATCH] [Fix] (CI, android-plugin): keep a failed Android retrace's result artifact, and echo the logs a failed replay already wrote --- .github/workflows/apk.yml | 29 ++++++++++++++++++++++++----- android-plugin/trace-replay-ci.sh | 16 ++++++++++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/.github/workflows/apk.yml b/.github/workflows/apk.yml index fc9ffc85..e8fa3493 100644 --- a/.github/workflows/apk.yml +++ b/.github/workflows/apk.yml @@ -531,22 +531,41 @@ jobs: ) if ((${#failed_cases[@]})); then - echo "Retaining fixtures for failed retrace case(s):" + echo "Retaining fixtures and results for failed retrace case(s):" printf ' %s\n' "${!failed_cases[@]}" else - echo "All retrace jobs succeeded; no fixtures need to be retained." + echo "All retrace jobs succeeded; nothing needs to be retained." fi deleted=0 retained=0 while IFS=$'\t' read -r artifact_id artifact_name; do + keep=0 if [[ "${artifact_name}" == MobileGL-trace-fixture-* ]]; then case_name="${artifact_name#MobileGL-trace-fixture-}" if [[ -v "failed_cases[${case_name}]" ]]; then - echo "Retaining ${artifact_name} (${artifact_id}) for failed retrace." - ((retained += 1)) - continue + keep=1 fi + elif [[ "${artifact_name}" == MobileGL-android-retrace-result-* ]]; then + # The result artifact carries mobilegl.log, retrace.log, logcat, + # the emulator log and the actual/diff images - the only record of + # why a retrace failed. Its name ends in --, so a + # suffix match on the case name keeps both backends' results for a + # case that failed on either of them, which is what a comparison + # needs. The match is anchored at the end, so a case name that is a + # prefix of a longer one does not retain the longer one's results. + for case_name in "${!failed_cases[@]}"; do + if [[ "${artifact_name}" == *-"${case_name}" ]]; then + keep=1 + break + fi + done + fi + + if ((keep)); then + echo "Retaining ${artifact_name} (${artifact_id}) for failed retrace." + ((retained += 1)) + continue fi echo "Deleting ${artifact_name} (${artifact_id})" diff --git a/android-plugin/trace-replay-ci.sh b/android-plugin/trace-replay-ci.sh index a879d114..831725c3 100644 --- a/android-plugin/trace-replay-ci.sh +++ b/android-plugin/trace-replay-ci.sh @@ -344,6 +344,22 @@ run_retrace() { copy_app_artifact "${app_dir}/output/retrace.log" "${result_dir}/retrace.log" copy_app_artifact "${app_dir}/output/mobilegl.log" "${result_dir}/mobilegl.log" + # A replay that wrote result.json but did not pass used to print nothing but + # the JSON, which for a non-zero statusCode says only "retrace failed with + # status N". The logs that say why are already on disk here, so echo their + # tails the same way the missing-result.json path does; the job log is the one + # place a failure stays readable after the result artifact expires. + if ! grep -q '"passed"[[:space:]]*:[[:space:]]*true' "${result_dir}/result.json"; then + if [ -s "${result_dir}/retrace.log" ]; then + echo "trace-replay-ci.sh: tail of retrace.log:" >&2 + tail -200 "${result_dir}/retrace.log" >&2 + fi + if [ -s "${result_dir}/mobilegl.log" ]; then + echo "trace-replay-ci.sh: tail of mobilegl.log:" >&2 + tail -200 "${result_dir}/mobilegl.log" >&2 + fi + fi + "${PYTHON}" -c 'import json, sys; result = json.load(open(sys.argv[1], encoding="utf-8")); sys.exit(0 if result.get("passed") else f"trace replay failed: {result}")' "${result_dir}/result.json" }