ci(install-e2e): per-leg names are just the transition; tag capability annotated at pick time

Graph polish + one structural simplification, after the first render
of the combo-box layout:

* Leg names: every combination job's display name is now
  '${{ matrix.tag.ref }} -> HEAD' - the box title (job id) already
  carries os+methods, so repeating them per leg was noise. The inner
  job renders as a short static 'e2e' tail (dynamic names render
  unexpanded on skipped jobs, so it must stay static).

* The windows probe job is gone: pick-releases now annotates each
  picked tag with whether its tree ships apps/desktop
  ({ref, desktop} objects in the matrix), and the windows run
  workflow gates on the new tag-has-desktop boolean input directly.
  One tree listing at pick time replaces N probe jobs, and the
  'probe tag' noise disappears from the graph.

Annotation loop verified against the real tag set (pre/post-desktop
split lands exactly at the app's introduction); 16-combo inventory
re-asserted; all four workflows pass actionlint.
This commit is contained in:
ethernet
2026-08-11 16:43:26 -04:00
parent 6515f8132a
commit 83e9f883d8
4 changed files with 84 additions and 96 deletions
+1 -1
View File
@@ -39,7 +39,7 @@ jobs:
# Static name on purpose: the caller's job name already carries the
# method pair, and GitHub renders name expressions UNEXPANDED (literal
# "${{ inputs... }}") on natively skipped jobs.
name: run
name: e2e
# No macOS driver exists yet: every pair is a declared TODO, so this is
# constant-false until the first method lands. Written as an impossible
# input comparison rather than `if: false` because actionlint rejects
+5 -5
View File
@@ -60,11 +60,11 @@ jobs:
e2e:
# Static name on purpose: the caller's job name already carries the
# method pair, and GitHub renders name expressions UNEXPANDED (literal
# "${{ inputs... }}") on natively skipped jobs.
name: run
# The pairs the sandbox driver can run today. Anything else is a
# declared TODO: native skip, so the coverage gap is a grey check on
# every run.
# "${{ inputs... }}") on natively skipped jobs. Short because it is
# only a rendered tail ("<tag> -> HEAD / e2e").
name: e2e
# The pairs the sandbox driver can run today; anything else is a
# declared TODO and natively skips.
if: inputs.install-method == 'curl-bash' && contains(fromJSON('["hermes-update", "curl-bash"]'), inputs.update-method)
runs-on: ${{ inputs.runner }}
timeout-minutes: ${{ inputs.timeout-minutes }}
+11 -41
View File
@@ -57,6 +57,11 @@ on:
required: false
type: string
default: auto
tag-has-desktop:
description: 'Whether install-ref ships the desktop app (apps/desktop). The caller annotates this from the tag''s own tree; desktop-method legs from pre-desktop releases natively skip.'
required: false
type: boolean
default: true
setup-exe-url:
description: 'Bootstrap installer to install OLD with. Default: the latest published one — what a user downloads today.'
required: false
@@ -72,52 +77,17 @@ permissions:
contents: read
jobs:
# Can this starting version run this flow at all? The desktop app
# (apps/desktop) only exists in releases from v2026.5.31 on (#20059):
# older tags have no window to launch and no Update button to click, so
# desktop-method legs from them natively skip below. Data-driven from the
# tag's own tree -- no hardcoded version list to rot.
probe:
name: probe tag
if: inputs.install-method == 'desktop-installer@latest' && inputs.update-method == 'desktop-app'
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
has-desktop: ${{ steps.probe.outputs.has-desktop }}
steps:
# Tree listings only: no blobs, full history + tags so any ref
# resolves.
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
fetch-depth: 0
filter: blob:none
- id: probe
run: |
set -euo pipefail
ref='${{ inputs.install-ref }}'
if [ "$ref" = "auto" ]; then
# Same choice the driver's stage phase makes: newest release tag.
ref="$(git tag --list 'v[0-9]*' --sort=-creatordate | head -1)"
fi
if git ls-tree -d "$ref" apps/desktop | grep -q .; then
has=true
else
has=false
fi
echo "ref $ref: has-desktop=$has"
echo "has-desktop=$has" >> "$GITHUB_OUTPUT"
e2e:
# Static name on purpose: the caller's job name already carries the
# method pair, and GitHub renders name expressions UNEXPANDED (literal
# "${{ inputs... }}") on natively skipped jobs.
name: run
needs: probe
name: e2e
# The one pair the driver can run today, and only from a starting
# version that ships the desktop app. Anything else is a native skip:
# a declared-TODO method pair, or a tag from before the app existed.
# (When probe itself skipped, its output is empty and this is false.)
if: inputs.install-method == 'desktop-installer@latest' && inputs.update-method == 'desktop-app' && needs.probe.outputs.has-desktop == 'true'
# version that ships the desktop app (the caller annotates
# tag-has-desktop from the tag's own tree; releases before #20059 have
# no window to launch and no Update button to click). Anything else is
# a native skip: a declared-TODO method pair, or a pre-desktop tag.
if: inputs.install-method == 'desktop-installer@latest' && inputs.update-method == 'desktop-app' && inputs.tag-has-desktop
runs-on: windows-latest
timeout-minutes: ${{ inputs.timeout-minutes }}
+67 -49
View File
@@ -95,12 +95,22 @@ jobs:
set -euo pipefail
tags="$(scripts/sandbox/pick-release-tags.sh --count '${{ inputs.tag-count || 5 }}')"
echo "Testing updates from: $tags"
echo "tags=$tags" >> "$GITHUB_OUTPUT"
# Annotate each tag with what its own tree supports, so legs can
# natively skip surfaces the starting version does not have.
# Today: does the release ship the desktop app (apps/desktop,
# #20059)? Cheaper and simpler here -- the tags are already
# checked out -- than a probe job per windows leg.
enriched="$(for t in $(echo "$tags" | jq -r '.[]'); do
if git ls-tree -d "$t" apps/desktop | grep -q .; then d=true; else d=false; fi
echo "{\"ref\":\"$t\",\"desktop\":$d}"
done | jq -sc .)"
echo "Annotated: $enriched"
echo "tags=$enriched" >> "$GITHUB_OUTPUT"
# ---- linux: install via curl-bash ---------------------------------------
linux-curl-bash-to-hermes-update:
name: "linux: curl-bash -> hermes-update"
name: "${{ matrix.tag.ref }} -> HEAD"
if: github.event_name != 'workflow_dispatch' || contains(fromJSON('["all", "both", "update"]'), inputs.route)
needs: pick-releases
strategy:
@@ -108,32 +118,32 @@ jobs:
# failed, so let every leg report.
fail-fast: false
matrix:
install-ref: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
tag: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
uses: ./.github/workflows/install-e2e-run.yml
with:
install-method: curl-bash
update-method: hermes-update
install-ref: ${{ matrix.install-ref }}
install-ref: ${{ matrix.tag.ref }}
linux-curl-bash-to-curl-bash:
name: "linux: curl-bash -> curl-bash"
name: "${{ matrix.tag.ref }} -> HEAD"
if: github.event_name != 'workflow_dispatch' || contains(fromJSON('["all", "both", "installer"]'), inputs.route)
needs: pick-releases
strategy:
fail-fast: false
max-parallel: 3
matrix:
install-ref: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
tag: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
uses: ./.github/workflows/install-e2e-run.yml
with:
install-method: curl-bash
update-method: curl-bash
install-ref: ${{ matrix.install-ref }}
install-ref: ${{ matrix.tag.ref }}
# ---- windows: install via the website's Hermes-Setup.exe ----------------
windows-desktop-installer-to-desktop-app:
name: "windows: desktop-installer@latest -> desktop-app"
name: "${{ matrix.tag.ref }} -> HEAD"
if: github.event_name != 'workflow_dispatch' || contains(fromJSON('["all", "windows-desktop"]'), inputs.route)
needs: pick-releases
strategy:
@@ -142,195 +152,203 @@ jobs:
# enough for a 5-tag axis without hogging the Windows pool.
max-parallel: 2
matrix:
install-ref: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
tag: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
uses: ./.github/workflows/install-e2e-windows-run.yml
with:
tag-has-desktop: ${{ matrix.tag.desktop }}
install-method: desktop-installer@latest
update-method: desktop-app
install-ref: ${{ matrix.install-ref }}
install-ref: ${{ matrix.tag.ref }}
windows-desktop-installer-to-installer-rerun:
name: "windows: desktop-installer@latest -> desktop-installer-rerun@latest"
name: "${{ matrix.tag.ref }} -> HEAD"
if: github.event_name != 'workflow_dispatch' || contains(fromJSON('["all", "windows-desktop"]'), inputs.route)
needs: pick-releases
strategy:
fail-fast: false
matrix:
install-ref: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
tag: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
uses: ./.github/workflows/install-e2e-windows-run.yml
with:
tag-has-desktop: ${{ matrix.tag.desktop }}
install-method: desktop-installer@latest
update-method: desktop-installer-rerun@latest
install-ref: ${{ matrix.install-ref }}
install-ref: ${{ matrix.tag.ref }}
windows-desktop-installer-to-hermes-update:
name: "windows: desktop-installer@latest -> hermes-update"
name: "${{ matrix.tag.ref }} -> HEAD"
if: github.event_name != 'workflow_dispatch' || contains(fromJSON('["all", "windows-desktop"]'), inputs.route)
needs: pick-releases
strategy:
fail-fast: false
matrix:
install-ref: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
tag: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
uses: ./.github/workflows/install-e2e-windows-run.yml
with:
tag-has-desktop: ${{ matrix.tag.desktop }}
install-method: desktop-installer@latest
update-method: hermes-update
install-ref: ${{ matrix.install-ref }}
install-ref: ${{ matrix.tag.ref }}
windows-desktop-installer-to-irm-iex:
name: "windows: desktop-installer@latest -> irm-iex"
name: "${{ matrix.tag.ref }} -> HEAD"
if: github.event_name != 'workflow_dispatch' || contains(fromJSON('["all", "windows-desktop"]'), inputs.route)
needs: pick-releases
strategy:
fail-fast: false
matrix:
install-ref: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
tag: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
uses: ./.github/workflows/install-e2e-windows-run.yml
with:
tag-has-desktop: ${{ matrix.tag.desktop }}
install-method: desktop-installer@latest
update-method: irm-iex
install-ref: ${{ matrix.install-ref }}
install-ref: ${{ matrix.tag.ref }}
# ---- windows: install via irm | iex --------------------------------------
windows-irm-iex-to-desktop-app:
name: "windows: irm-iex -> desktop-app"
name: "${{ matrix.tag.ref }} -> HEAD"
if: github.event_name != 'workflow_dispatch' || contains(fromJSON('["all", "windows-desktop"]'), inputs.route)
needs: pick-releases
strategy:
fail-fast: false
matrix:
install-ref: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
tag: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
uses: ./.github/workflows/install-e2e-windows-run.yml
with:
tag-has-desktop: ${{ matrix.tag.desktop }}
install-method: irm-iex
update-method: desktop-app
install-ref: ${{ matrix.install-ref }}
install-ref: ${{ matrix.tag.ref }}
windows-irm-iex-to-installer-rerun:
name: "windows: irm-iex -> desktop-installer-rerun@latest"
name: "${{ matrix.tag.ref }} -> HEAD"
if: github.event_name != 'workflow_dispatch' || contains(fromJSON('["all", "windows-desktop"]'), inputs.route)
needs: pick-releases
strategy:
fail-fast: false
matrix:
install-ref: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
tag: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
uses: ./.github/workflows/install-e2e-windows-run.yml
with:
tag-has-desktop: ${{ matrix.tag.desktop }}
install-method: irm-iex
update-method: desktop-installer-rerun@latest
install-ref: ${{ matrix.install-ref }}
install-ref: ${{ matrix.tag.ref }}
windows-irm-iex-to-hermes-update:
name: "windows: irm-iex -> hermes-update"
name: "${{ matrix.tag.ref }} -> HEAD"
if: github.event_name != 'workflow_dispatch' || contains(fromJSON('["all", "windows-desktop"]'), inputs.route)
needs: pick-releases
strategy:
fail-fast: false
matrix:
install-ref: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
tag: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
uses: ./.github/workflows/install-e2e-windows-run.yml
with:
tag-has-desktop: ${{ matrix.tag.desktop }}
install-method: irm-iex
update-method: hermes-update
install-ref: ${{ matrix.install-ref }}
install-ref: ${{ matrix.tag.ref }}
windows-irm-iex-to-irm-iex:
name: "windows: irm-iex -> irm-iex"
name: "${{ matrix.tag.ref }} -> HEAD"
if: github.event_name != 'workflow_dispatch' || contains(fromJSON('["all", "windows-desktop"]'), inputs.route)
needs: pick-releases
strategy:
fail-fast: false
matrix:
install-ref: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
tag: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
uses: ./.github/workflows/install-e2e-windows-run.yml
with:
tag-has-desktop: ${{ matrix.tag.desktop }}
install-method: irm-iex
update-method: irm-iex
install-ref: ${{ matrix.install-ref }}
install-ref: ${{ matrix.tag.ref }}
# ---- macos: no driver yet (every leg natively skips in the run workflow) -
macos-curl-bash-to-curl-bash:
name: "macos: curl-bash -> curl-bash"
name: "${{ matrix.tag.ref }} -> HEAD"
if: github.event_name != 'workflow_dispatch' || inputs.route == 'all'
needs: pick-releases
strategy:
fail-fast: false
matrix:
install-ref: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
tag: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
uses: ./.github/workflows/install-e2e-macos-run.yml
with:
install-method: curl-bash
update-method: curl-bash
install-ref: ${{ matrix.install-ref }}
install-ref: ${{ matrix.tag.ref }}
macos-curl-bash-to-hermes-update:
name: "macos: curl-bash -> hermes-update"
name: "${{ matrix.tag.ref }} -> HEAD"
if: github.event_name != 'workflow_dispatch' || inputs.route == 'all'
needs: pick-releases
strategy:
fail-fast: false
matrix:
install-ref: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
tag: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
uses: ./.github/workflows/install-e2e-macos-run.yml
with:
install-method: curl-bash
update-method: hermes-update
install-ref: ${{ matrix.install-ref }}
install-ref: ${{ matrix.tag.ref }}
macos-curl-bash-to-app-update:
name: "macos: curl-bash -> app-update"
name: "${{ matrix.tag.ref }} -> HEAD"
if: github.event_name != 'workflow_dispatch' || inputs.route == 'all'
needs: pick-releases
strategy:
fail-fast: false
matrix:
install-ref: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
tag: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
uses: ./.github/workflows/install-e2e-macos-run.yml
with:
install-method: curl-bash
update-method: app-update
install-ref: ${{ matrix.install-ref }}
install-ref: ${{ matrix.tag.ref }}
macos-packaged-app-to-curl-bash:
name: "macos: packaged-app -> curl-bash"
name: "${{ matrix.tag.ref }} -> HEAD"
if: github.event_name != 'workflow_dispatch' || inputs.route == 'all'
needs: pick-releases
strategy:
fail-fast: false
matrix:
install-ref: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
tag: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
uses: ./.github/workflows/install-e2e-macos-run.yml
with:
install-method: packaged-app
update-method: curl-bash
install-ref: ${{ matrix.install-ref }}
install-ref: ${{ matrix.tag.ref }}
macos-packaged-app-to-hermes-update:
name: "macos: packaged-app -> hermes-update"
name: "${{ matrix.tag.ref }} -> HEAD"
if: github.event_name != 'workflow_dispatch' || inputs.route == 'all'
needs: pick-releases
strategy:
fail-fast: false
matrix:
install-ref: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
tag: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
uses: ./.github/workflows/install-e2e-macos-run.yml
with:
install-method: packaged-app
update-method: hermes-update
install-ref: ${{ matrix.install-ref }}
install-ref: ${{ matrix.tag.ref }}
macos-packaged-app-to-app-update:
name: "macos: packaged-app -> app-update"
name: "${{ matrix.tag.ref }} -> HEAD"
if: github.event_name != 'workflow_dispatch' || inputs.route == 'all'
needs: pick-releases
strategy:
fail-fast: false
matrix:
install-ref: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
tag: ${{ fromJSON(needs.pick-releases.outputs.tags) }}
uses: ./.github/workflows/install-e2e-macos-run.yml
with:
install-method: packaged-app
update-method: app-update
install-ref: ${{ matrix.install-ref }}
install-ref: ${{ matrix.tag.ref }}