Skip to content

Commit 476d234

Browse files
anandgupta42claude
andcommitted
release: v0.7.2 — install URL hotfix + upgrader hardening
Hotfix for v0.7.1's broken install endpoint plus a defensive pass on the upgrade fetch surface (5-persona pre-release review caught two P0s that PR #825 did not). Fixed - `Installation.upgradeCurl()` fetches from www.altimate.sh/install instead of the unreachable altimate.ai/install. (#825, closes #309) - Published GitHub Action (`github/action.yml`) realigned with the v0.7.1 binary rename: cache + PATH use ~/.altimate/bin (was ~/.altimate-code/bin), binary invoked as `altimate` (was `altimate-code`). Action was broken on every cache miss for v0.7.1+ even before this URL fix. - 15s bounded timeout on the upgrader fetch via AbortSignal.timeout (CodeRabbit feedback on #825). Changed - Curl-upgrade fetch failures now surface an actionable error naming the URL + the manual re-install one-liner + the GitHub releases fallback, instead of a raw `AbortError: The operation was aborted` or `Error: Not Found`. HTTP non-2xx also includes the status code. - `UPGRADE_INSTALL_URL` and `UPGRADE_FETCH_TIMEOUT_MS` extracted as named constants inside the `altimate_change` block, so a future timeout tune is a single edit. Testing - 30 adversarial tests in `release-v0.7.2-adversarial.test.ts` covering URL eradication, cross-file host consistency, named- constant invariants, error-surface invariants, action.yml alignment, marker integrity, migration recovery surface, and CHANGELOG presence. - 529/529 tests pass across install/branding/v0.7.1/v0.7.2 suites. - Full opencode test suite: 8100 pass / 503 skip / 0 fail. - Pre-release sanity (`bun run pre-release`): all 4 checks pass. - Marker guard (`script/upstream/analyze.ts --markers --base main --strict`): ok. If you installed v0.7.1 via curl, your `altimate upgrade` will still fail until you re-install manually once: curl -fsSL https://www.altimate.sh/install | bash v0.7.2 and forward self-heal. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent e6b5c20 commit 476d234

5 files changed

Lines changed: 366 additions & 16 deletions

File tree

CHANGELOG.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,43 @@ All notable changes to this project will be documented in this file.
55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
66
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
77

8+
## [0.7.2] - 2026-05-21
9+
10+
A focused hotfix for v0.7.1's broken install endpoint plus a defensive pass on the upgrade fetch surface. v0.7.1 documented and embedded `https://altimate.ai/install` in the curl install path and in `altimate upgrade`'s in-place upgrader — that host is the marketing-site SPA and returns an HTML 404 for `/install`, so every curl install and every curl-installed user's `altimate upgrade` silently failed end-to-end. v0.7.2 swaps the host to `https://www.altimate.sh/install` (apex `altimate.sh` is still not routed to the Amplify Next.js app — tracked separately, drop the `www.` once apex DNS is fixed), wraps the upgrader fetch with a 15s bounded timeout, replaces the raw `AbortError: The operation was aborted` with an actionable error that names the URL, prints the manual re-install one-liner, and points at the GitHub releases fallback. Realigns the published GitHub Action (`github/action.yml`) with the v0.7.1 binary rename (`altimate-code` → `altimate`) and new install directory (`~/.altimate/bin`) — pre-fix, every Action consumer hit the broken URL on cache miss and then a missing binary even if the URL had worked. 30 adversarial tests pin the regression classes (URL eradication, cross-file host consistency, named-constant invariants, error-surface invariants, action.yml alignment, marker integrity, migration recovery surface, CHANGELOG presence).
11+
12+
**If you installed v0.7.1 via curl, your `altimate upgrade` will still fail until you re-install manually once:**
13+
14+
```bash
15+
curl -fsSL https://www.altimate.sh/install | bash
16+
```
17+
18+
After that, v0.7.2 and forward self-heal.
19+
20+
### Fixed
21+
22+
- **`Installation.upgradeCurl()` now fetches from `https://www.altimate.sh/install` instead of the unreachable `https://altimate.ai/install`.** v0.7.1 had pointed the in-place upgrader at the marketing site, which routes everything through a React Router SPA — `/install` rendered an HTML 404 page, the upgrader's `fetch` succeeded with a 200, the response body was the 404 HTML, and `bash` either executed the HTML and failed cryptically or hung mid-stream. The matching curl install one-liner in `install --help`, `README.md`, and `docs/docs/reference/troubleshooting.md` (three references) was broken the same way. www.altimate.sh now serves the install script via a Next.js route handler with `Content-Type: text/x-shellscript`. (#825, closes #309)
23+
- **Published GitHub Action (`github/action.yml`) realigned with the v0.7.1 binary rename.** v0.7.1 renamed the curl-installed binary `altimate-code``altimate` and moved the install directory `~/.altimate-code/bin``~/.altimate/bin`, but the Action's cache `path:`, `$GITHUB_PATH` addition, and final `run:` step still referenced the legacy `altimate-code` name and path. Combined with the broken install URL, every Action consumer hit a 404 on cache miss followed by an empty `$PATH` and a `altimate-code: command not found` even after the install "succeeded". All four references updated in lockstep.
24+
- **`altimate upgrade` (curl method) no longer hangs indefinitely on a stalled CDN/origin.** The fetch is bounded by `AbortSignal.timeout(UPGRADE_FETCH_TIMEOUT_MS)` (15s) so a TLS-rewriting corporate proxy, a hung CloudFront edge, or a slow-loris-style stall fails fast instead of blocking the user's terminal for minutes. Surfaced via CodeRabbit review on #825.
25+
26+
### Changed
27+
28+
- **Curl-upgrade fetch failures now surface an actionable error instead of `AbortError: The operation was aborted`.** Pre-fix, a timeout, a 404, a DNS failure, or a connection refused would propagate as `DOMException: The operation was aborted` (timeout) or `Error: Not Found` (HTTP non-2xx) — neither named the URL, the recovery path, or the fallback. The fetch is now wrapped in `try/catch` and the rethrown error reads: `"Could not download install script from https://www.altimate.sh/install: <cause>. Re-run the install manually: curl -fsSL https://www.altimate.sh/install | bash — or download a release binary directly from https://github.com/AltimateAI/altimate-code/releases/latest"`. HTTP non-2xx now also includes the numeric status (`HTTP 404 Not Found` instead of just `Not Found`).
29+
- **`UPGRADE_INSTALL_URL` and `UPGRADE_FETCH_TIMEOUT_MS` extracted as named constants** inside the `altimate_change` block in `packages/opencode/src/installation/index.ts`. Pre-fix, the URL and timeout were duplicated string + literal across the source and the test assertion. A future timeout tune (15s → 20s) would have required three coordinated edits; now it's one. The adversarial test asserts the existence of the named constant separately from the literal value so the regression guard isn't brittle to constant extraction itself.
30+
- **`altimate_change` marker block in `installation/index.ts` extended.** The v0.7.1 release did not mark the line where `upgradeCurl()` fetches the install script; v0.7.2 wraps the URL + timeout constants and the entire fetch+wrap block in a single marker pair so the next upstream bridge merge sees the intent and doesn't silently revert the URL or strip the timeout.
31+
32+
### Testing
33+
34+
- 30 adversarial tests in `release-v0.7.2-adversarial.test.ts` pinning the v0.7.2 surface:
35+
- **URL eradication** — 5 surfaces (`installation/index.ts`, `install`, `README.md`, `troubleshooting.md`, `github/action.yml`) each negative-asserted to not contain `altimate.ai/install`. The intentional `altimate.ai/discord` link in `docs/mkdocs.yml` is positively asserted as still present (different path, marketing-site contact info, intentionally out of scope).
36+
- **Cross-file host consistency** — the host used in the source `UPGRADE_INSTALL_URL` is automatically compared against every other reference in README, troubleshooting docs, install script, and action.yml. A future "drop the www." that updates the source but misses README will fail loudly.
37+
- **`install --help` examples** — both examples in the `--help` block asserted (a previous half-fix had updated only the first); negative assertion against the legacy host on the help block specifically.
38+
- **Bounded timeout**`AbortSignal.timeout(` is wired, `UPGRADE_FETCH_TIMEOUT_MS = 15_000` is a named constant, the fetch references the constant by name, and a raw `AbortSignal.timeout(15_000)` literal is forbidden (would mean someone reverted the constant extraction).
39+
- **Error surface** — the fetch lives inside a try/catch, the rethrown error message names the URL, includes the manual re-install one-liner with the URL templated through the constant, points at the GitHub releases fallback, and surfaces HTTP status codes (`HTTP ${res.status} ${res.statusText}`).
40+
- **`github/action.yml` alignment** — install URL, cache path, `$GITHUB_PATH` addition, and final binary invocation all match the v0.7.1 rename; negative assertions against every legacy form. Action file existence asserted at `github/action.yml` (not `.github/action.yml`) since moving it would silently break every downstream consumer.
41+
- **Marker integrity** — URL/timeout constants live inside an `altimate_change` block; try/catch wrapper lives inside an `altimate_change` block; balanced start/end count across the file.
42+
- **Migration recovery surface** — troubleshooting doc still has the install-path section with the new URL; README curl one-liner matches the source's `UPGRADE_INSTALL_URL` host.
43+
- **CHANGELOG presence** — release-skill backstop that catches a release commit without a 0.7.2 entry.
44+
845
## [0.7.1] - 2026-05-20
946

1047
A focused provider-error pass plus the standalone-binary fix: the curl-installed binary now starts (previously crashed with `Cannot find module '@altimateai/altimate-core'`), is renamed to match the npm primary `bin` (`altimate-code``altimate` for the curl path only), and Alpine + Windows-on-ARM hit a clear early-exit instead of a cryptic gzip failure. Two 5-persona pre-release reviews (provider-error pass, then binary-fix + rename pass) drove the surface — 86 adversarial tests total pin the regression classes.

github/action.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,22 +52,22 @@ runs:
5252
id: cache
5353
uses: actions/cache@v4
5454
with:
55-
path: ~/.altimate-code/bin
55+
path: ~/.altimate/bin
5656
key: altimate-code-${{ runner.os }}-${{ runner.arch }}-${{ steps.version.outputs.version }}
5757

5858
- name: Install altimate-code
5959
if: steps.cache.outputs.cache-hit != 'true'
6060
shell: bash
61-
run: curl -fsSL https://altimate.ai/install | bash
61+
run: curl -fsSL https://www.altimate.sh/install | bash
6262

6363
- name: Add altimate-code to PATH
6464
shell: bash
65-
run: echo "$HOME/.altimate-code/bin" >> $GITHUB_PATH
65+
run: echo "$HOME/.altimate/bin" >> $GITHUB_PATH
6666

6767
- name: Run altimate-code
6868
shell: bash
6969
id: run_altimate_code
70-
run: altimate-code github run
70+
run: altimate github run
7171
env:
7272
MODEL: ${{ inputs.model }}
7373
AGENT: ${{ inputs.agent }}

packages/opencode/src/installation/index.ts

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,33 @@ export namespace Installation {
3333
}).then((x) => x.text)
3434
}
3535

36+
// altimate_change start — curl-upgrade endpoint config
37+
// Upstream uses opencode.ai/install. We fetch the altimate install script
38+
// from www.altimate.sh/install (the apex altimate.sh isn't routed to the
39+
// Amplify Next.js app — tracked separately; revisit when apex DNS is fixed).
40+
// Bounded timeout so a stalled CDN/origin can't hang `altimate upgrade` forever.
41+
const UPGRADE_INSTALL_URL = "https://www.altimate.sh/install"
42+
const UPGRADE_FETCH_TIMEOUT_MS = 15_000
43+
// altimate_change end
44+
3645
async function upgradeCurl(target: string) {
37-
// altimate_change start — curl-upgrade endpoint URL + bounded fetch timeout
38-
// Upstream uses opencode.ai/install. We fetch the altimate install script
39-
// from www.altimate.sh/install (the apex altimate.sh isn't routed to the
40-
// Amplify Next.js app — tracked separately; revisit when apex DNS is fixed).
41-
// 15s timeout so a stalled CDN/origin can't hang `altimate upgrade` forever.
42-
const body = await fetch("https://www.altimate.sh/install", {
43-
signal: AbortSignal.timeout(15_000),
44-
}).then((res) => {
45-
if (!res.ok) throw new Error(res.statusText)
46-
return res.text()
47-
})
46+
// altimate_change start — friendly fetch error + manual-recovery hint
47+
let body: string
48+
try {
49+
body = await fetch(UPGRADE_INSTALL_URL, {
50+
signal: AbortSignal.timeout(UPGRADE_FETCH_TIMEOUT_MS),
51+
}).then((res) => {
52+
if (!res.ok) throw new Error(`HTTP ${res.status} ${res.statusText}`)
53+
return res.text()
54+
})
55+
} catch (err) {
56+
const cause = err instanceof Error ? err.message : String(err)
57+
throw new Error(
58+
`Could not download install script from ${UPGRADE_INSTALL_URL}: ${cause}. ` +
59+
`Re-run the install manually: curl -fsSL ${UPGRADE_INSTALL_URL} | bash — ` +
60+
`or download a release binary directly from https://github.com/AltimateAI/altimate-code/releases/latest`,
61+
)
62+
}
4863
// altimate_change end
4964
const proc = Process.spawn(["bash"], {
5065
stdin: "pipe",

packages/opencode/test/install/upgrade-method.test.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,20 @@ describe("upgrade execution", () => {
101101
// Without a timeout the install-script fetch can stall indefinitely on a
102102
// hung CDN/origin, blocking `altimate upgrade` forever. Use AbortSignal.timeout
103103
// so the request fails fast with a clear error instead.
104-
expect(INSTALLATION_SRC).toMatch(/AbortSignal\.timeout\(\s*15_000\s*\)/)
104+
// Assert on the named constant + 15s value separately so a future refactor
105+
// that extracts the literal (e.g., `AbortSignal.timeout(UPGRADE_FETCH_TIMEOUT_MS)`)
106+
// doesn't break this regression guard for cosmetic reasons.
107+
expect(INSTALLATION_SRC).toMatch(/AbortSignal\.timeout\(/)
108+
expect(INSTALLATION_SRC).toMatch(/UPGRADE_FETCH_TIMEOUT_MS\s*=\s*15_000/)
109+
})
110+
111+
test("curl upgrade fetch failure surfaces an actionable error", () => {
112+
// A raw `AbortError: The operation was aborted` is useless to a user on a
113+
// flaky network — they should see the URL, the manual-recovery curl
114+
// one-liner, and the GitHub releases fallback so they can self-recover.
115+
expect(INSTALLATION_SRC).toContain("Could not download install script from")
116+
expect(INSTALLATION_SRC).toContain("Re-run the install manually")
117+
expect(INSTALLATION_SRC).toContain("github.com/AltimateAI/altimate-code/releases/latest")
105118
})
106119

107120
test("VERSION normalization strips v prefix", () => {

0 commit comments

Comments
 (0)