Skip to content

Commit 2fed617

Browse files
ssh-randyclaude
andauthored
Fix install.sh GitHub API rate limiting (#150)
* Fix install.sh GitHub API rate limiting Pass GITHUB_TOKEN or GH_TOKEN as auth header when available. Unauthenticated GitHub API requests are limited to 60/hr, which causes install failures locally. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * update issue --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3d04895 commit 2fed617

File tree

2 files changed

+18
-2
lines changed

2 files changed

+18
-2
lines changed

.sudocode/issues.jsonl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -669,3 +669,4 @@
669669
{"id":"i-1ebt","uuid":"fc58688b-8c78-4e2c-8bea-6cf652c5f963","title":"Add binary update flow to CLI update command","content":"Modify `cli/src/cli/update-commands.ts` to support binary self-update on Unix and show reinstall instructions on Windows.\n\n## Changes to `handleUpdate()`\n\nBranch on `detectInstallSource()`:\n- `\"binary\"` → `handleBinaryUpdate()` (new)\n- `\"npm-meta\"` / `\"npm-standalone\"` / `\"volta\"` → existing npm flow (unchanged)\n\n## `handleBinaryUpdate()` (new function)\n\n1. **Windows** (`process.platform === 'win32'`):\n - Print error: \"Self-update is not supported on Windows\"\n - Print reinstall instructions: `Remove-Item ...` + `irm ... | iex`\n - Exit\n\n2. **Unix** (Linux/macOS):\n - Fetch `manifest.json` from latest GitHub Release\n - Look up current platform in manifest\n - Download tarball to temp dir\n - Verify SHA256 checksum\n - Extract to temp dir\n - Detect install dir from `process.execPath` (go up 2 levels from `bin/sudocode`)\n - Replace files in install directory\n - Print success\n\n## Changes to `handleUpdateCheck()`\n\n- Show install source in output (e.g., `Source: binary (linux-x64)` vs `Package: sudocode`)\n\n## Dependencies\n- Depends on [[i-51mm]] (install source detection)\n- Depends on [[i-6v10]] (source-aware update checker)\n\n## References\n- [[i-7vg8]] Parent issue\n- [[s-15l0]] Spec","status":"closed","priority":1,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-21 05:40:55","updated_at":"2026-02-21 05:43:54","closed_at":"2026-02-21 05:43:54","parent_id":"i-7vg8","parent_uuid":"2281e29c-19f6-486d-a2a2-da1b6a987fa9","relationships":[{"from":"i-1ebt","from_type":"issue","to":"i-51mm","to_type":"issue","type":"depends-on"},{"from":"i-1ebt","from_type":"issue","to":"i-6v10","to_type":"issue","type":"depends-on"},{"from":"i-1ebt","from_type":"issue","to":"s-15l0","to_type":"spec","type":"implements"}],"tags":["binary","cli","updates"]}
670670
{"id":"i-mzrr","uuid":"36ce85ab-0eff-467a-beac-157dd4e49b6c","title":"Make server update route source-aware","content":"Modify `server/src/routes/update.ts` to support binary installs.\n\n## Changes\n\n- `GET /api/update/check` — no change needed (already calls `checkForUpdates()` which will auto-detect)\n- `POST /api/update/install` — branch on `detectInstallSource()`:\n - `\"binary\"` on Windows → return error JSON with reinstall instructions\n - `\"binary\"` on Unix → download + replace (reuse logic from CLI binary update)\n - npm/volta → existing `npm install -g` logic (unchanged)\n\n## Dependencies\n- Depends on [[i-51mm]] (install source detection)\n- Depends on [[i-1ebt]] (binary update flow — reuse download/replace logic)\n\n## References\n- [[i-7vg8]] Parent issue\n- [[s-15l0]] Spec","status":"closed","priority":2,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-21 05:41:03","updated_at":"2026-02-21 05:46:43","closed_at":"2026-02-21 05:46:43","parent_id":"i-7vg8","parent_uuid":"2281e29c-19f6-486d-a2a2-da1b6a987fa9","relationships":[{"from":"i-mzrr","from_type":"issue","to":"i-1ebt","to_type":"issue","type":"depends-on"},{"from":"i-mzrr","from_type":"issue","to":"s-15l0","to_type":"spec","type":"implements"}],"tags":["binary","server","updates"]}
671671
{"id":"i-7jhg","uuid":"6c9bba11-7560-4f84-8941-b2d26828f017","title":"Fix ETXTBSY error on Linux binary self-update","content":"## Problem\n\nWhen running `sudocode update` on a binary installation on Linux, `fs.copyFileSync()` fails with `ETXTBSY` because Linux prevents overwriting a running executable's file.\n\n```\nError: ETXTBSY: text file is busy, copyfile '.../bin/sudocode' -> '.../bin/sudocode'\n```\n\nmacOS doesn't have this issue (it allows overwriting via a new inode), but Linux blocks writes to an inode that has an active text segment.\n\n## Fix\n\nUnlink the destination file before copying. `unlink()` removes the directory entry while the OS keeps the old inode alive for the running process via its open file descriptor. The new `copyFileSync()` creates a fresh inode.\n\n```typescript\ntry { fs.unlinkSync(destFile); } catch { /* may not exist */ }\nfs.copyFileSync(srcFile, destFile);\n```\n\n## File\n\n`cli/src/cli/update-commands.ts` — `handleBinaryUpdate()`, bin/ copy loop","status":"in_progress","priority":1,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-23 04:12:20","updated_at":"2026-02-23 04:12:27","closed_at":null,"parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-7jhg","from_type":"issue","to":"s-15l0","to_type":"spec","type":"implements"}],"tags":["binary","bug","linux"]}
672+
{"id":"i-8abg","uuid":"698d8386-af52-43ee-b72b-b9c62f2c2504","title":"Fix install.sh GitHub API rate limiting","content":"## Problem\n\n`curl -fsSL .../install.sh | bash` fails locally with HTTP 403 when fetching the latest release version from the GitHub API. Unauthenticated requests are limited to 60/hr. Codespaces aren't affected because they have `GITHUB_TOKEN` set automatically.\n\n## Fix\n\nPass `GITHUB_TOKEN` or `GH_TOKEN` as an `Authorization` header in the GitHub API calls (`get_latest_version` and `get_latest_dev_version`) when either env var is available.\n\n## File\n\n`scripts/install.sh`","status":"closed","priority":1,"assignee":null,"archived":0,"archived_at":null,"created_at":"2026-02-23 05:53:16","updated_at":"2026-02-23 05:55:11","closed_at":"2026-02-23 05:55:11","parent_id":null,"parent_uuid":null,"relationships":[{"from":"i-8abg","from_type":"issue","to":"s-15l0","to_type":"spec","type":"implements"}],"tags":["binary","bug","installer"],"feedback":[{"id":"3008d81b-86bd-44a0-b6b5-8dc3fbd7dcfa","from_id":"i-8abg","to_id":"s-15l0","feedback_type":"comment","content":"Added GITHUB_TOKEN/GH_TOKEN auth header to install.sh GitHub API calls. PR #150.","agent":"randy","anchor":null,"dismissed":false,"created_at":"2026-02-23T05:55:10.821Z","updated_at":"2026-02-23T05:55:10.821Z"}]}

scripts/install.sh

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,13 @@ CHANNEL="stable"
2020
PLATFORM=""
2121
TEMP_DIR=""
2222

23+
# GitHub API auth header (avoids 60 req/hr rate limit for unauthenticated requests)
24+
GH_AUTH_TOKEN="${GITHUB_TOKEN:-${GH_TOKEN:-}}"
25+
GH_AUTH_HEADER=""
26+
if [ -n "$GH_AUTH_TOKEN" ]; then
27+
GH_AUTH_HEADER="Authorization: token ${GH_AUTH_TOKEN}"
28+
fi
29+
2330
RED='\033[0;31m'
2431
GREEN='\033[0;32m'
2532
YELLOW='\033[0;33m'
@@ -111,7 +118,11 @@ get_platform() {
111118

112119
get_latest_version() {
113120
info "Fetching latest stable version..."
114-
VERSION=$(curl -fsSL "https://api.github.com/repos/${GITHUB_REPO}/releases/latest" \
121+
local curl_args="-fsSL"
122+
if [ -n "$GH_AUTH_HEADER" ]; then
123+
curl_args="$curl_args -H \"$GH_AUTH_HEADER\""
124+
fi
125+
VERSION=$(eval curl $curl_args "https://api.github.com/repos/${GITHUB_REPO}/releases/latest" \
115126
| grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
116127
if [ -z "$VERSION" ]; then
117128
die "Failed to fetch latest version. Use --version to specify."
@@ -121,7 +132,11 @@ get_latest_version() {
121132

122133
get_latest_dev_version() {
123134
info "Fetching latest dev build..."
124-
VERSION=$(curl -fsSL "https://api.github.com/repos/${GITHUB_REPO}/releases" \
135+
local curl_args="-fsSL"
136+
if [ -n "$GH_AUTH_HEADER" ]; then
137+
curl_args="$curl_args -H \"$GH_AUTH_HEADER\""
138+
fi
139+
VERSION=$(eval curl $curl_args "https://api.github.com/repos/${GITHUB_REPO}/releases" \
125140
| grep '"tag_name":' | grep '"dev-' | sed -E 's/.*"([^"]+)".*/\1/' | head -n 1)
126141
if [ -z "$VERSION" ]; then
127142
die "No dev builds found."

0 commit comments

Comments
 (0)