Skip to content
Open

Up #76

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
81 commits
Select commit Hold shift + click to select a range
5c8a9c4
[Fix, Test] (MG_Impl, MG_State): GL entry points record errors instea…
Swung0x48 Aug 11, 2026
ed29e63
[Fix, Test] (MG_Impl): glGetProgramResourceiv reports a written lengt…
Swung0x48 Aug 11, 2026
7c5fc03
[Fix, Test] (MG_Backend/DirectVulkan): never bind or cache a null pip…
Swung0x48 Aug 11, 2026
921504e
[Fix, Test] (MG_Backend/DirectVulkan, MG_Util): clamp Vulkan-derived …
Swung0x48 Aug 11, 2026
a6c362c
[Fix, Test] (MG_Backend/DirectVulkan): convert every default-framebuf…
Swung0x48 Aug 11, 2026
fa0f669
[Fix, Test] (MG_State, MG_Impl): reflection-backed glGetProgramiv que…
Swung0x48 Aug 11, 2026
ef562ee
[Fix, Test] (MG_Backend/DirectGLES): backend framebuffer, renderbuffe…
Swung0x48 Aug 11, 2026
543c29b
[Fix, Test] (MG_Backend/DirectVulkan): gl_FragCoord on the default fr…
Swung0x48 Aug 11, 2026
5b6dec2
[Revert] (MG_Backend/DirectVulkan): back out the gl_FragCoord default…
Swung0x48 Aug 11, 2026
21a43bf
[Fix, Test] (MG_Backend/DirectVulkan): re-land the gl_FragCoord defau…
Swung0x48 Aug 11, 2026
5a7bd99
[Fix] (MG_Backend/DirectVulkan): print VkShaderModule as a 64-bit val…
Swung0x48 Aug 11, 2026
964a7fc
[Fix, Test] (MG_State, MG_Backend/DirectVulkan): resolve transform-fe…
Swung0x48 Aug 11, 2026
d83b4db
[Fix, Test] (MG_State, MG_Impl): ARB_vertex_attrib_binding state mode…
Swung0x48 Aug 11, 2026
7b593e3
[Fix, Test] (MG_Impl, MG_State): negative-path GL errors for multi_bi…
Swung0x48 Aug 11, 2026
5d47698
[Fix, Test] (MG_Backend/DirectVulkan): materialize the default frameb…
Swung0x48 Aug 11, 2026
6f64ec0
[Fix, Test] (MG_Impl): validate indirect-dispatch and indirect-count …
Swung0x48 Aug 11, 2026
16c0109
[Fix, Test] (MG_Impl): multi-bind name rejection is per element, and …
Swung0x48 Aug 11, 2026
18c17ae
[Fix, Test] (MG_Backend/DirectVulkan): a blit into the default frameb…
Swung0x48 Aug 11, 2026
b1fdffd
[Fix, Test] (MG_Backend/DirectVulkan): read the default framebuffer's…
Swung0x48 Aug 11, 2026
7ba012a
[Test] (MG_IntegrationTest): SSBO runtime-array length across preambl…
Swung0x48 Aug 11, 2026
994ae37
[Fix, Test] (MG_Backend/DirectVulkan): an SSBO block instance array i…
Swung0x48 Aug 11, 2026
fa5ff5d
[Test] (MG_IntegrationTest): every texture access routine must read t…
Swung0x48 Aug 11, 2026
dbae4ed
[Fix, Test] (MG_Backend/DirectVulkan): depth blits to or from the def…
Swung0x48 Aug 11, 2026
757b315
[Fix, Test] (MG_Backend/DirectVulkan): a multisample resolve that mus…
Swung0x48 Aug 11, 2026
cc34d34
[Fix, Test] (MG_Backend/DirectGLES): hand every compiled shader's lif…
Swung0x48 Aug 11, 2026
ca3d24f
[Fix] (CI, android-plugin): keep a failed Android retrace's result ar…
Swung0x48 Aug 11, 2026
6cf5a77
[Test] (MG_IntegrationTest): separable programs drawn through a progr…
Swung0x48 Aug 11, 2026
f7d63f8
[Fix, Test] (MG_State, MG_Impl): a reserved program-pipeline name tak…
Swung0x48 Aug 11, 2026
ba9af18
[Test] (MG_IntegrationTest): park the two program-pipeline cases whos…
Swung0x48 Aug 11, 2026
2ce0595
[Fix, Test] (MG_State, MG_Impl, MG_Backend): a program pipeline's com…
Swung0x48 Aug 11, 2026
43bcd03
[Fix] (MG_Backend/DirectVulkan, MG_Impl): a malformed graphics pipeli…
Swung0x48 Aug 11, 2026
94e75fe
[Fix, Test] (MG_State, MG_Impl): glIsProgramPipeline answers for the …
Swung0x48 Aug 12, 2026
05bef71
[Fix, Test] (MG_State): a pipeline draw uses the block bindings its s…
Swung0x48 Aug 12, 2026
6dd0201
[Fix, Test] (MG_Impl/GLImpl): an indexed buffer SIZE query reports th…
Swung0x48 Aug 12, 2026
3068cda
[Test] (CI): keep the emulator log of the attempt that lost the emula…
Swung0x48 Aug 12, 2026
33c2715
[Fix] (MG_State, MG_Util): a default-block uniform starts at its decl…
Swung0x48 Aug 12, 2026
5267243
[Test] (MG_IntegrationTest): pin declared uniform initializers end to…
Swung0x48 Aug 12, 2026
577cd8c
[Fix] (3rdparty/glslang): bump the fork to the uniform-initializer pr…
Swung0x48 Aug 12, 2026
8af6ebc
[Fix] (MG_State): seed uniform initializers through the phase-A gate,…
Swung0x48 Aug 12, 2026
09459ed
[Fix] (CI, android-plugin): an ANGLE window surface lost before init …
Swung0x48 Aug 12, 2026
a4bd4e0
Merge branch 'fix/ssbo-rc13' into dev
Swung0x48 Aug 12, 2026
7aa958f
[Docs] (tools/trace_replay): reproduce the Android DirectGLES lane on…
Swung0x48 Aug 12, 2026
22859b0
[Docs] (tools/trace_replay): localise the improved-transparency ANGLE…
Swung0x48 Aug 12, 2026
1c5744f
[Fix] (MobileGL, Build): drop the __ANDROID_API__ source pin; hold AP…
Swung0x48 Aug 12, 2026
4c5afec
Merge branch 'fix/drop-android-api-pin' into dev
Swung0x48 Aug 12, 2026
2292e99
Merge remote-tracking branch 'origin/dev' into dev
Swung0x48 Aug 12, 2026
99ebf67
[Fix] (CMake): the Android API guard holds a floor of 26, not an exac…
Swung0x48 Aug 12, 2026
38eb958
[Test] (tools/trace_replay): dump every live framebuffer attachment a…
Swung0x48 Aug 12, 2026
f6cf04d
[Docs] (tools/trace_replay): name the two generated-ESSL defects that…
Swung0x48 Aug 12, 2026
ab62f81
[Docs] (tools/trace_replay): the local farm ANGLE is not the CI ANGLE…
Swung0x48 Aug 12, 2026
5705e05
[Docs] (tools/trace_replay): sundial-lite kills the emulator via a ho…
Swung0x48 Aug 12, 2026
7994ca3
[Docs] (tools/trace_replay): sundial-lite has no output-array indexin…
Swung0x48 Aug 12, 2026
90dd9be
[Docs] (tools/trace_replay): sundial-lite crashes in llvmpipe's JIT o…
Swung0x48 Aug 12, 2026
2839066
[Docs] (tools/trace_replay): sundial-lite's sampler state is identica…
Swung0x48 Aug 12, 2026
794c10e
[Fix] (3rdparty/glslang): bump the fork to the invariant-placement an…
Swung0x48 Aug 12, 2026
bcb0e89
[Fix, Test] (MG_State, MG_Backend/DirectGLES, MG_Util, MG_Integration…
Swung0x48 Aug 12, 2026
19fc734
[Fix] (MG_Backend/DirectVulkan): a re-entrant cache lookup dangled th…
Swung0x48 Aug 12, 2026
ef4c6db
Merge branch 'feat/cts-420pack-wave' into dev
Swung0x48 Aug 12, 2026
ff32405
[Fix, Perf, Test] (MG_State, MG_Impl/GLImpl, MG_Test, MG_IntegrationT…
Swung0x48 Aug 12, 2026
b4e07ce
[Fix, Test] (MG_State, MG_Backend/DirectGLES, MG_Test): close three h…
Swung0x48 Aug 12, 2026
c4e6ea1
[Docs] (tools/trace_replay): strip investigation logs from the README…
Swung0x48 Aug 12, 2026
cef81df
[Fix, Test] (ShaderTranspiler, DirectGLES): fold or lower dynamically…
Swung0x48 Aug 12, 2026
4d1d4f6
[Fix] (DirectGLES): report a rejected shader and a failed link at MGL…
Swung0x48 Aug 12, 2026
f6849fc
[Fix, Test] (MG_Backend/DirectVulkan, MG_IntegrationTest): an image u…
Swung0x48 Aug 12, 2026
faa7b17
[Test] (tools/trace_replay): drop the minecraft-26.2-in-world fixture
Swung0x48 Aug 12, 2026
21ec744
[Refactor] (MG_Util, MG_Test): retire FastSTL for ska::flat_hash_map,…
Swung0x48 Aug 12, 2026
8f3ce5f
[Fix] (MG_Backend/DirectGLES, MG_State, Docs): CopyImageSubData held …
Swung0x48 Aug 12, 2026
7b946fd
[Fix] (MG_Backend/DirectVulkan, MG_Util): RenderPassEntry needs move …
Swung0x48 Aug 12, 2026
e71d715
[Fix, Test] (MG_Backend/DirectVulkan, MG_Util, MG_Test): VkProgramObj…
Swung0x48 Aug 12, 2026
574634a
[Fix, Test] (MG_Backend/DirectVulkan, MG_IntegrationTest): let the bi…
Swung0x48 Aug 12, 2026
a020de7
Merge remote-tracking branch 'origin/dev' into feat/sampler-array-des…
Swung0x48 Aug 12, 2026
d2a36d6
[Fix, Test] (MG_Backend/DirectVulkan, MG_IntegrationTest): a sampler …
Swung0x48 Aug 12, 2026
8e7cc62
[Test] (MG_Benchmark): a standing UnorderedMap observatory - the cont…
Swung0x48 Aug 12, 2026
068786e
[Fix, Test] (MG_Backend/DirectVulkan, MG_IntegrationTest): a declined…
Swung0x48 Aug 12, 2026
f3a0d9e
[Refactor] (CI): move the trace fixture LFS pointer and verification …
Swung0x48 Aug 12, 2026
64c3411
[Perf] (CI): restore unchanged trace fixtures from the Actions cache …
Swung0x48 Aug 12, 2026
5cfbb71
Merge remote-tracking branch 'origin/dev' into feat/sampler-array-des…
Swung0x48 Aug 12, 2026
97facf7
[Fix] (MG_Backend/DirectVulkan): act on a failed binding remap, bound…
Swung0x48 Aug 12, 2026
a0bf4a8
[Fix, Test] (MG_Util, MG_Backend/DirectGLES, MG_Test, MG_IntegrationT…
Swung0x48 Aug 12, 2026
e310e3e
[Fix, Test] (MG_Util, MG_Backend/DirectGLES, MG_Test): resolve buffer…
Swung0x48 Aug 12, 2026
b5e9339
[Fix] (MG_Util): the unsupported-buffer-textures log tells a too-old …
Swung0x48 Aug 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 4 additions & 51 deletions .github/scripts/fetch-trace-fixture-lfs.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail

script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=trace-fixture-lib.sh
. "${script_dir}/trace-fixture-lib.sh"

if [ "$#" -lt 1 ] || [ "$#" -gt 2 ]; then
echo "usage: $0 <trace-case> [fixture-dir]" >&2
exit 2
Expand Down Expand Up @@ -62,57 +66,6 @@ if [ "${case_name}" = "OpenRA" ]; then
exit 0
fi

get_lfs_metadata() {
local file="$1"
local pointer
local expected_oid
local expected_size

if ! pointer="$(git show "HEAD:${file}" 2>/dev/null)"; then
echo "failed to read tracked fixture metadata: ${file}" >&2
return 1
fi
if ! grep -q '^version https://git-lfs.github.com/spec/v1$' <<< "${pointer}"; then
echo "tracked fixture is not a Git LFS pointer: ${file}" >&2
return 1
fi

expected_oid="$(awk '$1 == "oid" && $2 ~ /^sha256:/ { sub(/^sha256:/, "", $2); print $2 }' <<< "${pointer}")"
expected_size="$(awk '$1 == "size" { print $2 }' <<< "${pointer}")"
if ! [[ "${expected_oid}" =~ ^[0-9a-f]{64}$ ]] || ! [[ "${expected_size}" =~ ^[0-9]+$ ]]; then
echo "invalid Git LFS pointer metadata: ${file}" >&2
return 1
fi

printf '%s %s\n' "${expected_oid}" "${expected_size}"
}

verify_fixture_file() {
local downloaded_file="$1"
local display_name="$2"
local expected_oid="$3"
local expected_size="$4"
local actual_oid
local actual_size

if [ ! -f "${downloaded_file}" ]; then
echo "fixture file is missing: ${display_name}" >&2
return 1
fi

actual_size="$(wc -c < "${downloaded_file}" | tr -d '[:space:]')"
if [ "${actual_size}" != "${expected_size}" ]; then
echo "fixture size mismatch for ${display_name}: expected ${expected_size}, got ${actual_size}" >&2
return 1
fi

actual_oid="$(sha256sum "${downloaded_file}" | awk '{ print $1 }')"
if [ "${actual_oid}" != "${expected_oid}" ]; then
echo "fixture SHA-256 mismatch for ${display_name}: expected ${expected_oid}, got ${actual_oid}" >&2
return 1
fi
}

fetch_file_from_mirror() {
local file="$1"
local url="$2"
Expand Down
117 changes: 117 additions & 0 deletions .github/scripts/trace-fixture-cache.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
#!/usr/bin/env bash
# Cache-side helper for trace fixtures.
#
# key <case> [fixture-dir] derive the actions/cache key and path list
# verify <case> [fixture-dir] check restored fixtures against their pointers
# reset <case> [fixture-dir] drop restored fixtures, leaving the pointers
#
# The cache key is content-addressed on the Git LFS pointer oids tracked at
# HEAD, which are readable from a plain checkout without smudging. Fixture
# content therefore maps 1:1 onto a key: unchanged content hits, changed
# content is a new key and thus a miss, and the download path handles it. The
# key deliberately carries no restore-keys prefix in the workflow - a fixture
# that does not match the pointer exactly must never be restored.
set -euo pipefail

script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=trace-fixture-lib.sh
. "${script_dir}/trace-fixture-lib.sh"

# Bump when the key derivation changes in a way that must invalidate old
# entries; the content digest alone would not notice a format change.
key_schema="v1"

if [ "$#" -lt 2 ] || [ "$#" -gt 3 ]; then
echo "usage: $0 <key|verify|reset> <trace-case> [fixture-dir]" >&2
exit 2
fi

command_name="$1"
case_name="$2"
fixture_dir="${3:-tools/trace_replay/fixtures}"
python_bin="${PYTHON:-python3}"

if ! command -v "${python_bin}" >/dev/null 2>&1 && command -v python >/dev/null 2>&1; then
python_bin=python
fi

mapfile -t files < <(trace_fixture_files "${case_name}" "${fixture_dir}" "${python_bin}")
if [ "${#files[@]}" -eq 0 ]; then
echo "no fixture files declared for trace case: ${case_name}" >&2
exit 1
fi

# Writes "name=value" to $GITHUB_OUTPUT when running under Actions, and to
# stdout otherwise so the script stays runnable (and testable) off-CI.
emit_output() {
local name="$1"
local value="$2"
if [ -n "${GITHUB_OUTPUT:-}" ]; then
if [[ "${value}" == *$'\n'* ]]; then
local delimiter="ghadelim_$(date +%s%N)_$$"
{
printf '%s<<%s\n' "${name}" "${delimiter}"
printf '%s\n' "${value}"
printf '%s\n' "${delimiter}"
} >> "${GITHUB_OUTPUT}"
else
printf '%s=%s\n' "${name}" "${value}" >> "${GITHUB_OUTPUT}"
fi
fi
printf '%s=%s\n' "${name}" "${value}"
}

sanitize_case() {
printf '%s' "$1" | sed 's/[^A-Za-z0-9._-]/_/g'
}

case "${command_name}" in
key)
manifest=""
for file in "${files[@]}"; do
# A case whose fixtures are committed directly rather than through Git LFS
# (OpenRA) has no pointer oid to key on, and nothing to download either.
# Report it as uncacheable so the workflow skips the cache entirely.
if ! metadata="$(get_lfs_metadata "${file}" 2>/dev/null)"; then
echo "trace case ${case_name} is not stored in Git LFS; skipping fixture cache" >&2
emit_output "cacheable" "false"
emit_output "key" ""
exit 0
fi
read -r expected_oid expected_size <<< "${metadata}"
manifest+="$(basename "${file}") ${expected_oid} ${expected_size}"$'\n'
done

digest="$(printf '%s' "${manifest}" | sha256sum | awk '{ print substr($1, 1, 16) }')"
safe_case="$(sanitize_case "${case_name}")"

emit_output "cacheable" "true"
emit_output "key" "trace-fixture-${key_schema}-${safe_case}-${digest}"
emit_output "paths" "$(printf '%s\n' "${files[@]}")"
;;

verify)
for file in "${files[@]}"; do
metadata="$(get_lfs_metadata "${file}")"
read -r expected_oid expected_size <<< "${metadata}"
verify_fixture_file "${file}" "${file}" "${expected_oid}" "${expected_size}"
done
echo "Verified ${#files[@]} fixture file(s) for ${case_name} against the tracked Git LFS pointers."
;;

reset)
# Put the working tree back to the pointer files a fresh checkout would
# have, so that a rejected cache entry falls through to exactly the same
# download path a cache miss takes.
for file in "${files[@]}"; do
rm -f "${file}" "${file}.tmp"
done
git checkout -- "${files[@]}"
echo "Reset ${#files[@]} fixture file(s) for ${case_name} to their tracked Git LFS pointers."
;;

*)
echo "unknown command: ${command_name}" >&2
exit 2
;;
esac
73 changes: 73 additions & 0 deletions .github/scripts/trace-fixture-lib.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/usr/bin/env bash
# Shared helpers for trace-fixture handling: reading the in-tree Git LFS pointer
# metadata and verifying a fixture file against it. Sourced by
# fetch-trace-fixture-lfs.sh (verify after download) and by
# trace-fixture-cache.sh (cache key derivation and verify after cache restore),
# so both paths agree on what a valid fixture is.

# Reads the Git LFS pointer tracked at HEAD for a fixture path and prints
# "<oid> <size>". Fails if the tracked blob is not a well-formed LFS pointer.
get_lfs_metadata() {
local file="$1"
local pointer
local expected_oid
local expected_size

if ! pointer="$(git show "HEAD:${file}" 2>/dev/null)"; then
echo "failed to read tracked fixture metadata: ${file}" >&2
return 1
fi
if ! grep -q '^version https://git-lfs.github.com/spec/v1$' <<< "${pointer}"; then
echo "tracked fixture is not a Git LFS pointer: ${file}" >&2
return 1
fi

expected_oid="$(awk '$1 == "oid" && $2 ~ /^sha256:/ { sub(/^sha256:/, "", $2); print $2 }' <<< "${pointer}")"
expected_size="$(awk '$1 == "size" { print $2 }' <<< "${pointer}")"
if ! [[ "${expected_oid}" =~ ^[0-9a-f]{64}$ ]] || ! [[ "${expected_size}" =~ ^[0-9]+$ ]]; then
echo "invalid Git LFS pointer metadata: ${file}" >&2
return 1
fi

printf '%s %s\n' "${expected_oid}" "${expected_size}"
}

# Checks an on-disk fixture against the size and SHA-256 from its LFS pointer.
verify_fixture_file() {
local downloaded_file="$1"
local display_name="$2"
local expected_oid="$3"
local expected_size="$4"
local actual_oid
local actual_size

if [ ! -f "${downloaded_file}" ]; then
echo "fixture file is missing: ${display_name}" >&2
return 1
fi

actual_size="$(wc -c < "${downloaded_file}" | tr -d '[:space:]')"
if [ "${actual_size}" != "${expected_size}" ]; then
echo "fixture size mismatch for ${display_name}: expected ${expected_size}, got ${actual_size}" >&2
return 1
fi

actual_oid="$(sha256sum "${downloaded_file}" | awk '{ print $1 }')"
if [ "${actual_oid}" != "${expected_oid}" ]; then
echo "fixture SHA-256 mismatch for ${display_name}: expected ${expected_oid}, got ${actual_oid}" >&2
return 1
fi
}

# Prints the fixture file paths of a trace case, one per line. Strips CR so the
# result is usable when python emits CRLF (Git Bash on Windows).
trace_fixture_files() {
local case_name="$1"
local fixture_dir="$2"
local python_bin="${3:-python3}"

"${python_bin}" tools/trace_replay/trace_cases.py \
--format fixture-files \
--case "${case_name}" \
--fixture-root "${fixture_dir}" | tr -d '\r'
}
86 changes: 81 additions & 5 deletions .github/workflows/apk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,41 @@ jobs:
- name: Checkout repo
uses: actions/checkout@v6

- name: Derive trace fixture cache key
id: fixture-key
run: bash .github/scripts/trace-fixture-cache.sh key '${{ matrix.case }}'

- name: Restore trace fixture cache
id: fixture-cache
if: steps.fixture-key.outputs.cacheable == 'true'
uses: actions/cache/restore@v5
with:
path: ${{ steps.fixture-key.outputs.paths }}
key: ${{ steps.fixture-key.outputs.key }}

- name: Verify restored trace fixture
id: fixture-verify
if: steps.fixture-cache.outputs.cache-hit == 'true'
run: |
if bash .github/scripts/trace-fixture-cache.sh verify '${{ matrix.case }}'; then
echo "ok=true" >> "$GITHUB_OUTPUT"
else
echo "ok=false" >> "$GITHUB_OUTPUT"
echo "::warning::Cached fixture for ${{ matrix.case }} failed verification; falling back to the download path"
bash .github/scripts/trace-fixture-cache.sh reset '${{ matrix.case }}'
fi

- name: Fetch trace fixture
if: steps.fixture-verify.outputs.ok != 'true'
run: bash .github/scripts/fetch-trace-fixture-lfs.sh '${{ matrix.case }}'

- name: Save trace fixture cache
if: steps.fixture-key.outputs.cacheable == 'true' && steps.fixture-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v5
with:
path: ${{ steps.fixture-key.outputs.paths }}
key: ${{ steps.fixture-key.outputs.key }}

- name: Stage trace fixture
run: |
safe_case="$(printf '%s' '${{ matrix.case }}' | sed 's/[^A-Za-z0-9._-]/_/g')"
Expand Down Expand Up @@ -411,6 +443,24 @@ jobs:
run_retrace || retrace_status=$?
if [ "${retrace_status}" -eq 75 ]; then
echo "::warning::Android emulator infrastructure failed; restarting it and retrying this retrace once."
# Surface-lost is retried rather than failed, so it would otherwise
# be invisible. Report it per job - a healthy run prints nothing and
# a rate spike shows up as a row per affected case.
reason_file="android-retrace-result/infrastructure-failure-reason.txt"
surface_lost_retries=0
if [ -f "${reason_file}" ]; then
surface_lost_retries="$(grep -c 'angle-surface-lost' "${reason_file}" || true)"
fi
if [ "${surface_lost_retries}" -gt 0 ]; then
echo "surface-lost retries: ${surface_lost_retries} (${{ matrix.backend.name }}, ${{ matrix.case.name }})" \
>> "${GITHUB_STEP_SUMMARY}"
fi
# The restart truncates EMULATOR_LOG, and the attempt that lost the
# emulator is the one worth reading - the retry usually only shows
# the wreckage. Keep the first attempt's log before it is clobbered.
if [ -f "${EMULATOR_LOG}" ]; then
cp "${EMULATOR_LOG}" "${EMULATOR_LOG}.first-attempt" || true
fi
sh android-plugin/run-avd-ci.sh stop \
--avd-name "${AVD_NAME}" \
--emulator-log "${EMULATOR_LOG}" \
Expand Down Expand Up @@ -450,6 +500,13 @@ jobs:
if [ -f "${EMULATOR_LOG}" ]; then
cp "${EMULATOR_LOG}" android-retrace-result/diagnostics/emulator.log
fi
if [ -f "${EMULATOR_LOG}.first-attempt" ]; then
cp "${EMULATOR_LOG}.first-attempt" android-retrace-result/diagnostics/emulator-first-attempt.log
fi
# A vanished emulator looks identical whether the host OOM killer took
# qemu or the renderer faulted. These two say which.
free -h > android-retrace-result/diagnostics/host-memory.txt 2>&1 || true
sudo dmesg -T 2>/dev/null | tail -300 > android-retrace-result/diagnostics/host-dmesg.txt || true

- name: Stop Emulator
if: always()
Expand Down Expand Up @@ -531,22 +588,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 -<backend>-<case>, 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})"
Expand Down
Loading