fix(install-e2e): windows transcripts were empty; player gets #zip= hash + one player per run

Windows transcripts were ZERO bytes: ts-prefix.ps1 formatted with
{0:D2}, but Floor() returns a double and the D specifier is
integer-only - it threw per line, and under the driver's relaxed EAP
every line errored into the void. {0:00} fixes it (custom numeric
format works on doubles). Reproduced the exact pipeline locally
(empty file + Format specifier invalid), verified the fix produces
prefixed merged stdout+stderr with exit code intact. That is also
why the log timeline never auto-synced: there was nothing in the
files to sync.

The GitHub artifact URL 307s to /suites/... server-side and strips
the ?zip= query param. The player now reads the zip URL from a
#zip= HASH param (client-side, survives the redirect) with ?zip=
as fallback; the hash path was verified in a real browser against a
real leg zip (auto-fetch + boot).

Per ethie's design, one player artifact for the whole run: new
leg-player job uploads playback.html (archive:false) before the
matrix legs, the report job needs it, and each ran cell gets TWO
links - 📼 to the player with #zip=<that leg's logs zip> and ⬇️ to
the raw zip. Per-leg player uploads removed from all three run
workflows.
This commit is contained in:
ethernet
2026-08-13 22:51:44 -04:00
parent 08d9f27773
commit cd667debfa
7 changed files with 67 additions and 56 deletions
@@ -93,16 +93,6 @@ jobs:
with:
fetch-depth: 0
- name: Upload leg player
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: install-e2e-player-${{ inputs.leg-id }}
path: tests/install/e2e-assets/playback.html
archive: false
retention-days: 14
if-no-files-found: error
- name: Start screen recording
uses: ./.github/actions/e2e-screen-record
with:
+4 -17
View File
@@ -134,23 +134,10 @@ jobs:
-c copy "${{ runner.temp }}/e2e-logs/recording.mp4"
fi
# The leg player: one static HTML, uploaded BEFORE the driver runs
# (if: always() covers failures too). Single file, no zip, so the
# artifacts URL serves playback.html directly.
- name: Upload leg player
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: install-e2e-player-${{ inputs.leg-id }}
path: tests/install/e2e-assets/playback.html
archive: false
retention-days: 14
if-no-files-found: error
# Artifact names cannot contain '/', and install-ref may be a full ref
# like refs/heads/main. GitHub Actions expressions have no string-replace
# function, so build the safe name here. Runs even on failure -- that is
# exactly when the logs are wanted.
# The leg player: ONE static HTML per run, uploaded up front by the
# leg-player job in install-e2e.yml (archive: false, so GitHub names
# the artifact after the file: playback.html). The report job links
# every ran leg to it with the leg's zip as a #zip= hash param.
- name: Build artifact name
if: always()
id: artifact
@@ -119,16 +119,6 @@ jobs:
with:
fetch-depth: 0
- name: Upload leg player
if: always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: install-e2e-player-${{ inputs.leg-id }}
path: tests/install/e2e-assets/playback.html
archive: false
retention-days: 14
if-no-files-found: error
# One recording mechanism on every OS: the composite action installs
# ffmpeg (cached - winget's download is the slow part), starts the
# capture, and record-stop fails on a zero-frame file so a silently
+25 -1
View File
@@ -194,6 +194,30 @@ jobs:
tag-has-desktop: ${{ matrix.tag_has_desktop }}
leg-id: ${{ matrix.leg_id }}
# The leg player: one static HTML for the whole run. Uploaded BEFORE the
# matrix legs so it exists even when every leg dies; the report job links
# every ran leg to it with that leg's logs zip as a #zip= hash param
# (hash survives the artifact URL's server-side redirect, the query does
# not). archive: false makes GitHub name the artifact after the FILE
# (playback.html), ignoring the name: input -- harmless, the renderer
# looks it up by that name.
leg-player:
name: Upload leg player
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
sparse-checkout: tests/install/e2e-assets/playback.html
sparse-checkout-cone-mode: false
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: install-e2e-player
path: tests/install/e2e-assets/playback.html
archive: false
retention-days: 14
if-no-files-found: error
# The outcome, human-readable: the plan chart again, with each cell
# replaced by how that leg actually concluded. Per-leg conclusions are
# NOT reachable through `needs` (a matrix job's result collapses to one
@@ -203,7 +227,7 @@ jobs:
report:
name: Result chart
if: always()
needs: [pick-releases, linux, windows, macos]
needs: [leg-player, pick-releases, linux, windows, macos]
runs-on: ubuntu-latest
timeout-minutes: 5
steps: