|
| 1 | +--- |
| 2 | +name: serve-release |
| 3 | +description: > |
| 4 | + Download a released backend.ai-webui bundle from GitHub Releases and serve it |
| 5 | + locally via Portless so the URL carries the version name |
| 6 | + (e.g. `https://v26-4-8-rc-3.localhost:1355`). Uses `scripts/serve-release.sh` |
| 7 | + under the hood, which fetches the bundle, copies the local `config.toml` / |
| 8 | + plugins into the extracted folder, and runs `serve` behind Portless. |
| 9 | + Trigger on: "릴리즈 띄워", "릴리즈 버전 실행", "serve release", "run release", |
| 10 | + "release 띄워줘", "특정 버전 띄워줘", "released bundle 띄워줘", "stage release", |
| 11 | + or any request that names a specific webui release version (e.g. "v26.4.8-rc.3 |
| 12 | + 실행해줘", "26.4.7 띄워줘"). |
| 13 | +--- |
| 14 | + |
| 15 | +# Serve Release |
| 16 | + |
| 17 | +Serves an already-published `backend.ai-webui` release bundle locally so it can |
| 18 | +be tested under a stable, version-named Portless URL. Wraps |
| 19 | +`scripts/serve-release.sh` — do not reinvent the download/extract logic. |
| 20 | + |
| 21 | +## 1. Resolve the version |
| 22 | + |
| 23 | +Pick a version with this priority: |
| 24 | + |
| 25 | +1. **User-provided version in the prompt** — accept `26.4.8-rc.3`, `v26.4.8-rc.3`, |
| 26 | + or a release URL (`.../releases/tag/v26.4.8-rc.3`). Strip the leading `v` if |
| 27 | + present; everything downstream uses the bare semver. |
| 28 | +2. **Most recent release** — if the user said "릴리즈 띄워줘" without a version, |
| 29 | + fetch the latest tag with: |
| 30 | + ```bash |
| 31 | + gh release list --repo lablup/backend.ai-webui --limit 10 |
| 32 | + ``` |
| 33 | + Show the top 5–10 entries with `AskUserQuestion` so the user can pick (include |
| 34 | + stable and prerelease releases; mark prereleases). Do **not** silently default |
| 35 | + to the absolute latest — the user usually wants a specific one. |
| 36 | +3. **Tag exists check** — before running the script, confirm the tag exists: |
| 37 | + ```bash |
| 38 | + gh release view v<VERSION> --repo lablup/backend.ai-webui --json tagName -q .tagName |
| 39 | + ``` |
| 40 | + If the tag does not exist, surface the error and offer the `gh release list` |
| 41 | + output so the user can correct the version. Do not try fuzzy matching. |
| 42 | + |
| 43 | +The bundle asset must exist on the release. The script downloads |
| 44 | +`backend.ai-webui-bundle-<VERSION>.zip` from |
| 45 | +`https://github.com/lablup/backend.ai-webui/releases/download/v<VERSION>/...`. |
| 46 | +If the user picked a release where this asset is missing (rare, mostly for |
| 47 | +hotfix-only tags), the `curl` step will fail with 404 — surface the failure and |
| 48 | +suggest a different version rather than retrying. |
| 49 | + |
| 50 | +## 2. Pre-flight checks |
| 51 | + |
| 52 | +Before invoking the script, verify: |
| 53 | + |
| 54 | +- **`config.toml` exists** in the project root. The script copies it into the |
| 55 | + extracted folder so the served bundle points at your local backend. If missing, |
| 56 | + copy `config.toml.sample` to `config.toml` first and remind the user to edit |
| 57 | + endpoints if needed. |
| 58 | +- **`serve` is on PATH** (`command -v serve`). If absent, tell the user to run |
| 59 | + `npm install -g serve` — the script also errors with the same hint. |
| 60 | +- **`portless` is on PATH** (`command -v portless`). If absent, the script |
| 61 | + silently falls back to plain `serve` on `http://localhost:<SERVE_PORT>`; tell |
| 62 | + the user the URL will be HTTP-only without Portless and suggest |
| 63 | + `npm install -g portless` (or `pnpm add -g portless`) if they want the |
| 64 | + named-subdomain experience. |
| 65 | + |
| 66 | +## 3. Decide ports |
| 67 | + |
| 68 | +The script reads two optional env vars: |
| 69 | + |
| 70 | +- `SERVE_PORT` — the HTTP port `serve` listens on (default `9091`). Pin only |
| 71 | + if the user asked for a specific port, or `9091` is occupied. |
| 72 | +- `PORTLESS_PORT` — the Portless daemon port (default `1355`, same as |
| 73 | + `scripts/dev.mjs`). Do not change unless the user explicitly asks. |
| 74 | + |
| 75 | +Quick check for port conflict on the default: |
| 76 | + |
| 77 | +```bash |
| 78 | +lsof -nP -iTCP:9091 -sTCP:LISTEN 2>/dev/null | head -1 |
| 79 | +``` |
| 80 | + |
| 81 | +If something's already on `9091`, pick the next free port in the 9091–9099 range |
| 82 | +and pass `SERVE_PORT=<port>`. |
| 83 | + |
| 84 | +## 4. Compute the Portless URL |
| 85 | + |
| 86 | +The script derives the Portless app slug from the version. Replicate the same |
| 87 | +sanitization so you can announce the URL before the server is fully up: |
| 88 | + |
| 89 | +``` |
| 90 | +v<VERSION> -> lowercased |
| 91 | + -> [^a-z0-9-] replaced with - |
| 92 | + -> repeated - collapsed |
| 93 | + -> leading/trailing - trimmed |
| 94 | + -> capped at 40 chars |
| 95 | +``` |
| 96 | + |
| 97 | +Examples: |
| 98 | +- `26.4.8-rc.3` -> app `v26-4-8-rc-3` -> `https://v26-4-8-rc-3.localhost:1355` |
| 99 | +- `26.4.7` -> app `v26-4-7` -> `https://v26-4-7.localhost:1355` |
| 100 | +- `25.7.1` -> app `v25-7-1` -> `https://v25-7-1.localhost:1355` |
| 101 | + |
| 102 | +Use the standard daemon port (`1355`) unless the user pinned `PORTLESS_PORT`. |
| 103 | + |
| 104 | +## 5. Run the script |
| 105 | + |
| 106 | +Always run **in the background** — `serve-release.sh` blocks on `serve`/`portless` |
| 107 | +and the user will need their shell back to interact with the served instance. |
| 108 | +Run from the project root so the `config.toml` and `dist/plugins` lookup paths |
| 109 | +resolve correctly. |
| 110 | + |
| 111 | +Default invocation: |
| 112 | + |
| 113 | +```bash |
| 114 | +./scripts/serve-release.sh <VERSION> |
| 115 | +``` |
| 116 | + |
| 117 | +With a custom serve port: |
| 118 | + |
| 119 | +```bash |
| 120 | +SERVE_PORT=9092 ./scripts/serve-release.sh <VERSION> |
| 121 | +``` |
| 122 | + |
| 123 | +Use `run_in_background: true` and announce in one short sentence what's |
| 124 | +happening (e.g. *"Downloading v26.4.8-rc.3 bundle and serving via Portless at |
| 125 | +https://v26-4-8-rc-3.localhost:1355."*). |
| 126 | + |
| 127 | +## 6. Wait for "Server starting" |
| 128 | + |
| 129 | +The script prints a few stages — download, extract, copy `config.toml`, then |
| 130 | +finally Portless + `serve` startup. Poll the background task's output with a |
| 131 | +short until-loop (cap ~30s for first download, ~5s if the bundle is cached) for |
| 132 | +the line containing `Press Ctrl+C to stop the server`. Once seen, the URL is |
| 133 | +ready. |
| 134 | + |
| 135 | +If `curl` fails (404 / network error), the script exits non-zero — surface the |
| 136 | +last ~20 lines of output to the user and don't pretend it's running. |
| 137 | + |
| 138 | +## 7. Announce both URLs |
| 139 | + |
| 140 | +After the server is up, present **two** URLs on separate lines so the user can |
| 141 | +pick whichever they prefer — Portless (HTTPS, named) and direct (HTTP, port). |
| 142 | +Format exactly like this, no preamble: |
| 143 | + |
| 144 | +``` |
| 145 | +Portless: https://v26-4-8-rc-3.localhost:1355 |
| 146 | +Direct: http://localhost:9091 |
| 147 | +``` |
| 148 | + |
| 149 | +If Portless wasn't available and the script fell back to plain `serve`, show |
| 150 | +only the Direct line and call out the fallback once. |
| 151 | + |
| 152 | +## 8. Common follow-ups |
| 153 | + |
| 154 | +- **"Stop the server"** — kill the background task. Don't `portless proxy stop` |
| 155 | + unless asked; that kills *all* portless apps including any running dev server. |
| 156 | +- **"Serve a different version"** — stop the current background task first |
| 157 | + (port collision otherwise), then invoke the script with the new version. |
| 158 | +- **"Switch the backend endpoint"** — the served bundle uses the project-root |
| 159 | + `config.toml` that was copied at script-start. To change endpoints, edit |
| 160 | + `config.toml`, then **restart** the script (the in-place copy is one-shot). |
| 161 | +- **Cached extraction** — the script reuses `scripts/temp-releases/webui-<VERSION>/` |
| 162 | + if it exists, skipping download. If the user reports stale content, delete that |
| 163 | + directory and rerun. |
| 164 | + |
| 165 | +## 9. Out of scope |
| 166 | + |
| 167 | +- Do not modify `scripts/serve-release.sh` for one-off behaviour changes — |
| 168 | + prefer driving via env vars (`SERVE_PORT`, `PORTLESS_PORT`). |
| 169 | +- Do not try to install `serve` or `portless` for the user; surface the missing |
| 170 | + binary and let them choose. |
| 171 | +- Do not run alongside `pnpm dev` on the same Portless daemon if you suspect a |
| 172 | + port conflict between `serve` (9091) and the React dev server (Portless picks |
| 173 | + free port, but pinned `PORT=9081`/etc. from the user could collide). When in |
| 174 | + doubt, check `lsof` first. |
0 commit comments