215 lines
11 KiB
YAML
215 lines
11 KiB
YAML
name: Install & Update E2E — Windows desktop (reusable)
|
|
|
|
# Runs ONE Windows {install-method, update-method} combination: install
|
|
# OLD, then update OLD -> HEAD through the route a user would take.
|
|
#
|
|
# The Windows sibling of install-e2e-run.yml. No bubblewrap anywhere -- the
|
|
# drivers fake GitHub with git's own transport rewrite: a driver-owned
|
|
# GIT_CONFIG_GLOBAL carrying url.<file://serve.git>.insteadOf for both
|
|
# canonical repo URLs, so the installer and updater run byte-for-byte
|
|
# against their real URLs and land on a local bare repo. Its `main` serves
|
|
# OLD (install-ref, default: the newest release tag) during the install,
|
|
# then advances to HEAD for the update leg -- an update becomes available
|
|
# exactly the way it does for a real user.
|
|
#
|
|
# Two install arms, two drivers:
|
|
# desktop-installer@latest the REAL desktop user flow
|
|
# (tests/install/windows-desktop-gui-e2e.ps1):
|
|
# the website's published Hermes-Setup.exe runs
|
|
# headed, AutoHotkey clicks Install -> Launch,
|
|
# the real Electron window must appear. Update
|
|
# methods:
|
|
# app-update the app's own Update button:
|
|
# the installed Hermes.exe runs
|
|
# under Playwright's Electron
|
|
# driver, which clicks Settings
|
|
# -> About -> "Update now"; the
|
|
# production hand-off chain runs
|
|
# untouched.
|
|
# (hermes-update, desktop-installer@latest,
|
|
# installer-script re-run: declared TODOs.)
|
|
# installer-script the irm | iex one-liner
|
|
# (tests/install/windows-installer-script-e2e
|
|
# .ps1): runs the install.ps1 shipped AT the
|
|
# OLD ref, headless. Update methods:
|
|
# hermes-update venv hermes.exe update
|
|
# installer-script re-run HEAD's install.ps1
|
|
# (app-update from a script install: TODO.)
|
|
#
|
|
# Method pairs without a driver yet NATIVELY SKIP (grey check, no runner):
|
|
# the capability knowledge lives here, next to the drivers, so the caller
|
|
# can dispatch every declared combination without knowing which ones work.
|
|
#
|
|
# Call it:
|
|
#
|
|
# jobs:
|
|
# windows:
|
|
# uses: ./.github/workflows/install-e2e-windows-run.yml
|
|
# with:
|
|
# install-method: desktop-installer@latest
|
|
# update-method: app-update
|
|
# install-ref: v2026.8.3
|
|
|
|
on:
|
|
workflow_call:
|
|
inputs:
|
|
install-method:
|
|
description: 'How OLD gets installed. Supported: desktop-installer@latest (website exe, AHK-clicked) and installer-script (irm | iex install.ps1). Declared-but-TODO methods skip.'
|
|
required: true
|
|
type: string
|
|
update-method:
|
|
description: 'How the install updates to HEAD. Supported: app-update (Update button under Playwright, from a desktop install) and hermes-update / installer-script (from a script install). Declared-but-TODO pairs skip.'
|
|
required: true
|
|
type: string
|
|
install-ref:
|
|
description: 'Ref to install as OLD (served as main while the installer runs). auto = the newest release tag in the checkout.'
|
|
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
|
|
type: string
|
|
default: https://hermes-assets.nousresearch.com/Hermes-Setup.exe
|
|
timeout-minutes:
|
|
description: 'Job timeout. The install leg does real toolchain work and the update leg a full Electron rebuild.'
|
|
required: false
|
|
type: number
|
|
default: 240
|
|
|
|
permissions:
|
|
contents: read
|
|
|
|
jobs:
|
|
# ---- arm 1: install via the website's Hermes-Setup.exe (GUI) -------------
|
|
e2e:
|
|
name: Hermes-Setup.exe
|
|
# The one pair the driver can run today, and only from a starting
|
|
# 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 == 'app-update' && inputs.tag-has-desktop
|
|
runs-on: windows-latest
|
|
timeout-minutes: ${{ inputs.timeout-minutes }}
|
|
|
|
env:
|
|
# Sibling of the checkout (D:\a\hermes-agent\hermes-desktop-gui-e2e):
|
|
# outside the repo so the staged bare clone and the install never
|
|
# collide with the checkout itself. NOTE: ${{ runner.temp }} is NOT
|
|
# available in job-level env (only github/inputs/matrix/needs/
|
|
# secrets/strategy/vars).
|
|
HERMES_E2E_WORKROOT: ${{ github.workspace }}\..\hermes-desktop-gui-e2e
|
|
|
|
steps:
|
|
# Full history: the driver bare-clones this checkout as the repo the
|
|
# installer/updater talk to, and the installer's baked release pin
|
|
# must be reachable in that clone. A shallow checkout cannot serve
|
|
# either need.
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
# ffmpeg records the screen for the whole run so a failed click is
|
|
# diagnosable from the artifact instead of by guesswork. NOT
|
|
# preinstalled on windows-latest; the driver skips recording
|
|
# gracefully when it's absent, so this step is what makes the
|
|
# recording actually happen. Cached — winget's ffmpeg download is
|
|
# the slow part.
|
|
- name: Restore cached ffmpeg
|
|
id: ffmpeg-cache
|
|
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5
|
|
with:
|
|
path: ${{ runner.temp }}\test-bins\ffmpeg
|
|
key: e2e-ffmpeg-${{ runner.os }}-v1
|
|
|
|
- name: Install ffmpeg
|
|
if: steps.ffmpeg-cache.outputs.cache-hit != 'true'
|
|
shell: pwsh
|
|
run: |
|
|
$bins = "$env:RUNNER_TEMP\test-bins\ffmpeg"
|
|
New-Item -ItemType Directory -Path $bins -Force | Out-Null
|
|
winget install -e --id Gyan.FFmpeg --silent --accept-source-agreements --accept-package-agreements --disable-interactivity --location "$env:RUNNER_TEMP\ffmpeg_dir"
|
|
Copy-Item -Path "$env:RUNNER_TEMP\ffmpeg_dir\*\*" -Destination $bins -Recurse -Force
|
|
|
|
- name: Add ffmpeg to PATH
|
|
shell: pwsh
|
|
run: Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\test-bins\ffmpeg\bin"
|
|
|
|
- name: Stage serve repo (main -> ${{ inputs.install-ref }})
|
|
shell: powershell
|
|
run: powershell -NoProfile -ExecutionPolicy Bypass -File tests\install\windows-desktop-gui-e2e.ps1 -Phase stage -Route "${{ inputs.update-method }}" -InstallRef "${{ inputs.install-ref }}" -SetupExeUrl ${{ inputs.setup-exe-url }}
|
|
|
|
- name: Install ${{ inputs.install-ref }} via website Hermes-Setup.exe (headed, AHK-clicked)
|
|
shell: powershell
|
|
run: powershell -NoProfile -ExecutionPolicy Bypass -File tests\install\windows-desktop-gui-e2e.ps1 -Phase install-gui -Route "${{ inputs.update-method }}" -InstallRef "${{ inputs.install-ref }}" -SetupExeUrl ${{ inputs.setup-exe-url }}
|
|
|
|
- name: Update ${{ inputs.install-ref }} -> HEAD (${{ inputs.update-method }})
|
|
shell: powershell
|
|
run: powershell -NoProfile -ExecutionPolicy Bypass -File tests\install\windows-desktop-gui-e2e.ps1 -Phase update-gui -Route "${{ inputs.update-method }}" -InstallRef "${{ inputs.install-ref }}" -SetupExeUrl ${{ inputs.setup-exe-url }}
|
|
|
|
- name: Collect proof + logs
|
|
if: always()
|
|
shell: powershell
|
|
run: |
|
|
$out = "gui-e2e-proof"
|
|
New-Item -ItemType Directory -Path $out -Force | Out-Null
|
|
$work = $env:HERMES_E2E_WORKROOT
|
|
$home_ = Join-Path $work "hermes-home"
|
|
foreach ($pair in @(
|
|
@{ src = (Join-Path $work "proof"); dst = "proof" },
|
|
@{ src = (Join-Path $work "shas.json"); dst = "shas.json" },
|
|
@{ src = (Join-Path $home_ "logs"); dst = "logs" },
|
|
@{ src = (Join-Path $home_ ".hermes-update-result.json"); dst = ".hermes-update-result.json" }
|
|
)) {
|
|
if (Test-Path $pair.src) { Copy-Item $pair.src (Join-Path $out $pair.dst) -Recurse -Force }
|
|
}
|
|
|
|
- name: Upload proof + logs
|
|
if: always()
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: install-e2e-windows-${{ inputs.update-method }}-${{ inputs.install-ref }}-${{ github.sha }}
|
|
path: gui-e2e-proof
|
|
retention-days: 14
|
|
if-no-files-found: ignore
|
|
|
|
# ---- arm 2: install via the irm | iex one-liner (headless) ---------------
|
|
script-e2e:
|
|
# Same static-name reasoning as e2e above.
|
|
name: install.ps1
|
|
# The pairs the script driver can run today. app-update from a script
|
|
# install is a declared TODO (the desktop app also has to be BUILT by
|
|
# that path first).
|
|
if: inputs.install-method == 'installer-script' && contains(fromJSON('["hermes-update", "installer-script"]'), inputs.update-method)
|
|
runs-on: windows-latest
|
|
timeout-minutes: ${{ inputs.timeout-minutes }}
|
|
|
|
steps:
|
|
# Full history: the driver bare-clones this checkout as the repo the
|
|
# installer/updater talk to, and both OLD and HEAD must be reachable
|
|
# in that clone.
|
|
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
|
|
with:
|
|
fetch-depth: 0
|
|
|
|
- name: Run install + update E2E
|
|
shell: powershell
|
|
run: powershell -NoProfile -ExecutionPolicy Bypass -File tests\install\windows-installer-script-e2e.ps1 -UpdateMethod "${{ inputs.update-method }}" -InstallRef "${{ inputs.install-ref }}"
|
|
env:
|
|
HERMES_E2E_LOG_DIR: ${{ runner.temp }}\e2e-logs
|
|
|
|
- name: Upload installer logs
|
|
if: always()
|
|
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
|
with:
|
|
name: install-e2e-windows-script-${{ inputs.update-method }}-${{ inputs.install-ref }}-${{ github.sha }}
|
|
path: ${{ runner.temp }}\e2e-logs
|
|
retention-days: 14
|
|
if-no-files-found: ignore
|