feat(LinuxTentacleE2E): Phase 12.M.L.A.3 — install-tentacle.sh v-prefix fallback E2E
Summary
Pins the .sh's two-URL retry contract: when --version 1.6.0 returns 404 from the plain URL form, the .sh MUST retry with the v-prefixed form (v1.6.0).
Real-world driver
GitHub Releases tag conventions vary: some operators publish only v1.6.0, some only 1.6.0, some both. The .sh's retry-with-v-prefix is the operator-friendly compatibility shim. Without coverage, regressions in this path break operators on legacy / private mirrors silently.
Production failure modes regression-pinned
-
.shstops retrying on plain 404 → operator on legacy mirror sees install fail with"could not download 1.6.0"even thoughv1.6.0IS published -
.shdoesn't echo the retry attempt → operators have no log signal that the fallback was tried (vs "single shot fail") -
.sh's exit-on-failure regression after retry → silently swallows the v-prefix 404 and exits 0 with no actual install
Test mechanism — surgical 404
ctx.Mirror.ConfigureNotFoundForPath($"/download/{version}/");
New ConfigureNotFoundForPath API does substring match on URL AbsolutePath. The leading slash in "/download/<version>/" makes it NOT match the v-prefixed sibling "/download/v<version>/" because the leading character of the version segment differs.
ConfigureNotFoundForVersion("1.6.0-vfallback") would have 404'd BOTH URLs (substring "1.6.0-vfallback" appears in both paths). The new API is the strict-substring escape hatch needed for path-disambiguating tests.
Assertions
| Assertion | Pins |
|---|---|
exitCode == 0 |
Fallback succeeded |
stdout contains "retrying with 'v<version>'"
|
.sh line 236 retry log fires |
| stdout echoes the v-prefixed URL | Operators verify which form worked |
INSTALL_DIR/Squid.Tentacle exists |
Binary actually downloaded via v-prefix path |
/usr/local/bin/squid-tentacle symlink exists |
Post-extract steps ran the same way as plain-URL happy path |
Infrastructure additions
LocalReleaseMirror.ConfigureNotFoundForPath(string pathSubstring) — surgical 404 sibling of ConfigureNotFoundForVersion. Composes with StagePreBuiltArchive: configure 404 for the plain path, archive serves at the v-prefixed path.
Fidelity tier
.sh + real bash + real curl + real LocalReleaseMirror responding 404 vs 200 per-URL. No mocks at OS-resource layer.
Test runs in LinuxTentacleHostStateCollection (serializes against upgrade + service-fixture tests on shared host state).
Expected runtime: ~5s.
Test plan
-
Linux E2E workflow runs (manual workflow_dispatchafter merge) -
A2u2_PlainVersion404FallsBackToVPrefix_InstallSucceedspasses within ~10s -
No regression on existing 22 Linux E2E tests