test(e2e): update sandboxes follow the main channel, not the stable default

#135847 made an official-origin source checkout default to the stable channel,
which resolves only from GitHub's latest published release. The upgrade-network,
Windows install+update and Desktop update harnesses keep the official URL as
origin, publish commits on main and never a release, so every update in them
stopped at the stable default:

- e2e-upgrade (network): "Could not resolve the stable source channel: No
  published stable release could be verified" (9 failed)
- Windows install + update E2E: "Release: stable v0.21.6; this checkout is
  newer and waits for the next release", checkout never moved (12 failed)
- Desktop update E2E (app-update, update-concurrency, build-fail): the update
  check answered {"channel":"stable","error":"release-unavailable"}

These suites test moving between commits, so each seeded install now records
`hermes update --set-channel main` right after its installer (new
_install_helpers.pin_main_channel; Windows Machine.install). Stable resolution
keeps its own coverage: test_release_channel_records sets stable explicitly on
the same seeded install, and tests/hermes_cli/test_source_release_channels.py.

Local: tests/e2e/core/upgrade/network on main plus this change, 21 passed
(4 failed in test_offline_and_flaky.py on main before it).
This commit is contained in:
Teknium
2026-10-10 12:13:39 -07:00
parent b406d25f24
commit 3a4b4b6f83
4 changed files with 21 additions and 1 deletions

View File

@@ -70,6 +70,8 @@ def install(root: Path) -> None:
cp = I.run_installer(I.Sandbox(root=sb.root, env={**sb.env, "GIT_NO_LAZY_FETCH": "1"}))
if cp.returncode != 0:
_fail("scripts/install.sh --non-interactive", cp)
# publishUpstream() lands commits on main, never a release: follow main, not the stable default.
I.pin_main_channel(sb)
# The real way a CLI install gets the Desktop app on Linux: build + package into
# apps/desktop/release/linux-unpacked, the tree the Desktop updater swaps in place.
cp = sb.cli("desktop", "--build-only", timeout=1800)

View File

@@ -165,6 +165,17 @@ def run_installer(sb: Sandbox, *, timeout: float = 1800) -> subprocess.Completed
timeout=timeout, input="")
def pin_main_channel(sb: Sandbox) -> None:
"""Follow every commit on main, as `hermes update --set-channel main` records it.
An official-origin source checkout defaults to the stable channel (the latest published GitHub
release). These sandboxes publish commits on main and no releases, and their subject is moving
between commits; channel resolution has its own suites (test_release_channel_records,
tests/hermes_cli/test_source_release_channels.py)."""
cp = sb.cli("update", "--set-channel", "main", timeout=120)
assert cp.returncode == 0 and "Update channel for" in cp.stdout, "could not pin the main channel:\n" + describe(cp)
def provider_config(base_url: str, version: int | None, extra: str = "") -> str:
"""A hand-edited user config: comments, a key HEAD does not know, and the fake provider."""
ver = f"_config_version: {version}\n" if version is not None else ""

View File

@@ -197,6 +197,7 @@ def seed_install(root: Path) -> Installed:
shutil.copy(H.WORKTREE / "scripts" / "install.sh", script)
cp = sb.run(["bash", str(script), "--non-interactive", "--skip-browser"], timeout=1800, input="")
assert cp.returncode == 0, "seed install failed:\n" + I.describe(cp)
I.pin_main_channel(sb) # cells publish commits, not releases (test_release_channel_records opts back into stable)
# From here on the checkout talks to the official URL, which only the proxy can serve.
(sb.home / ".gitconfig").write_text("", encoding="utf-8")
gitroot = root / "gitroot"

View File

@@ -367,9 +367,15 @@ class Machine:
shutil.copyfile(REPO_ROOT / "scripts" / "install.ps1", script)
cwd = self.root / "install-cwd"
cwd.mkdir(parents=True, exist_ok=True)
return self._run_logged(
run = self._run_logged(
["powershell.exe", "-NoProfile", "-ExecutionPolicy", "Bypass", "-File", str(script), "-NonInteractive"],
"install", timeout=INSTALL_TIMEOUT, cwd=cwd)
if run.returncode == 0 and self.hermes_exe.is_file():
# advance() lands NEXT on main and publishes no release: follow main, not the stable
# default an official-origin checkout gets (channel resolution has its own suites).
pin = self.hermes("update", "--set-channel", "main", label="pin-main-channel")
assert pin.returncode == 0, f"could not pin the main channel\n{self.evidence()}"
return run
def hermes(self, *args: str, label: str | None = None, timeout: float = CMD_TIMEOUT,
env_extra: dict[str, str] | None = None) -> Run: