chore: add python installer script `install.py`

This commit is contained in:
insleker 2026-04-11 23:13:54 +08:00
parent c3789536d8
commit cf908184c7
3 changed files with 26 additions and 6 deletions

View File

@ -4,7 +4,13 @@ on:
push: push:
branches: branches:
- main - main
paths:
- "lib/**"
- "bin/**"
pull_request: pull_request:
paths:
- "lib/**"
- "bin/**"
jobs: jobs:
dart: dart:

View File

@ -82,7 +82,9 @@ dart run bin/code_work_spawner.dart \
Install the latest matching release binary from GitHub Releases: Install the latest matching release binary from GitHub Releases:
```bash ```bash
# export GH_TOKEN="$TOKEN" # If got 404, `GITHUB_TOKEN` also work
uv run https://github.com/existedinnettw/code_work_spawner/scripts/install.py uv run https://github.com/existedinnettw/code_work_spawner/scripts/install.py
uv run https://$GH_TOKEN@raw.githubusercontent.com/existedinnettw/code_work_spawner/main/scripts/install.py --help
``` ```
Install a specific version: Install a specific version:

View File

@ -22,6 +22,17 @@ REPO = "existedinnettw/code_work_spawner"
BINARY_NAME = "code_work_spawner" BINARY_NAME = "code_work_spawner"
def github_headers() -> dict[str, str]:
headers = {
"Accept": "application/vnd.github+json",
"User-Agent": "code_work_spawner-install-script",
}
token = os.environ.get("GH_TOKEN") or os.environ.get("GITHUB_TOKEN")
if token:
headers["Authorization"] = f"Bearer {token}"
return headers
def parse_args() -> argparse.Namespace: def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description="Install code_work_spawner from GitHub Releases." description="Install code_work_spawner from GitHub Releases."
@ -105,18 +116,19 @@ def download_release_metadata(repo: str, version: str) -> dict:
try: try:
response = httpx.get( response = httpx.get(
url, url,
headers={ headers=github_headers(),
"Accept": "application/vnd.github+json",
"User-Agent": "code_work_spawner-install-script",
},
timeout=30.0, timeout=30.0,
follow_redirects=True, follow_redirects=True,
) )
response.raise_for_status() response.raise_for_status()
return response.json() return response.json()
except httpx.HTTPStatusError as exc: except httpx.HTTPStatusError as exc:
hint = ""
if exc.response.status_code == 404:
hint = " If this release exists, set GH_TOKEN (or GITHUB_TOKEN) and retry."
raise RuntimeError( raise RuntimeError(
f"Failed to fetch release metadata ({exc.response.status_code}): {exc.response.text}" "Failed to fetch release metadata "
f"({exc.response.status_code}): {exc.response.text}{hint}"
) from exc ) from exc
except httpx.HTTPError as exc: except httpx.HTTPError as exc:
raise RuntimeError(f"Failed to fetch release metadata: {exc}") from exc raise RuntimeError(f"Failed to fetch release metadata: {exc}") from exc
@ -147,7 +159,7 @@ def download_asset(asset: dict, destination: Path) -> None:
with httpx.stream( with httpx.stream(
"GET", "GET",
download_url, download_url,
headers={"User-Agent": "code_work_spawner-install-script"}, headers=github_headers(),
timeout=60.0, timeout=60.0,
follow_redirects=True, follow_redirects=True,
) as response: ) as response: