From 7c76685354f50d9e3ae9234fa640913cfb61c2b4 Mon Sep 17 00:00:00 2001 From: caorushizi <84996057@qq.com> Date: Sun, 17 May 2026 21:17:56 +0800 Subject: [PATCH 1/7] chore: move docs and installer distribution --- .github/workflows/cli.yml | 68 ++++-------------- .github/workflows/docs.yml | 69 ++++--------------- .goreleaser.yaml | 20 +++--- CLAUDE.md | 2 +- CONTRIBUTING.md | 11 +-- README.md | 16 ++--- apps/docs/content/docs/en/installation.md | 26 +++---- apps/docs/content/docs/en/skills.md | 6 +- apps/docs/content/docs/zh/installation.md | 26 +++---- apps/docs/content/docs/zh/skills.md | 6 +- .../content/tutorials/en/env-multi-env.mdx | 2 +- .../content/tutorials/en/first-workspace.mdx | 2 +- .../tutorials/en/json-output-error-codes.mdx | 2 +- apps/docs/content/tutorials/en/templates.mdx | 2 +- .../content/tutorials/zh/env-multi-env.mdx | 2 +- .../content/tutorials/zh/first-workspace.mdx | 2 +- .../tutorials/zh/json-output-error-codes.mdx | 2 +- apps/docs/content/tutorials/zh/templates.mdx | 2 +- apps/docs/next.config.mjs | 4 +- apps/docs/public/install.sh | 34 ++++++--- apps/docs/src/app/(home)/home-page.tsx | 24 +++---- .../src/app/(home)/home-template-preview.tsx | 2 +- apps/docs/src/app/[lang]/blog/[slug]/page.tsx | 2 +- .../src/app/[lang]/docs/[[...slug]]/page.tsx | 2 +- .../app/[lang]/tutorials/[[...slug]]/page.tsx | 2 +- apps/docs/src/app/docs/docs-toc.tsx | 4 +- apps/docs/src/app/layout.config.tsx | 2 +- apps/docs/src/app/layout.tsx | 2 +- apps/docs/src/app/sitemap.ts | 2 +- apps/docs/src/components/site-top-nav.tsx | 4 +- .../src/components/template-examples-nav.tsx | 4 +- apps/docs/vercel.json | 22 ++++++ packages/cli/internal/cli/install_sh_test.go | 6 +- .../cli/internal/updatecheck/background.go | 4 +- packages/cli/internal/updatecheck/checker.go | 37 ++++++---- .../cli/internal/updatecheck/checker_test.go | 26 ++++++- packages/cli/internal/updatecheck/notify.go | 2 +- packages/cli/internal/updatecheck/semver.go | 10 +-- packages/skills/one-cli/SKILL.md | 10 +-- packages/skills/one-migrate/SKILL.md | 6 +- .../astro-site/src/components/Welcome.astro | 2 +- .../apps/ui/src/nodes/HomePage/index.tsx | 2 +- .../expo-mobile/src/app/(tabs)/index.tsx | 2 +- .../templates/nextjs-app/src/app/page.tsx | 2 +- .../templates/react-spa/src/pages/Home.tsx | 2 +- .../starlight-docs/src/content/docs/index.mdx | 2 +- vercel.json | 22 ++++++ 47 files changed, 263 insertions(+), 248 deletions(-) create mode 100644 apps/docs/vercel.json create mode 100644 vercel.json diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index 0be6b30..e42c95d 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -1,10 +1,9 @@ # Release workflow for the Go rewrite. Runs on git tags shaped vN.N.N (and # their pre-release variants), cross-compiles via goreleaser, and uploads -# the artifacts to a GitHub Release that the npm wrapper postinstall reads. +# the artifacts to a GitHub Release consumed by install.sh. # # Tagging convention: `v0.3.0`, `v0.3.0-rc.1`. Tag MUST match the version -# in package.json so `one --version` and the npm package report the same -# thing. +# in VERSION so `one --version` and the release tag report the same thing. name: CLI @@ -13,8 +12,7 @@ on: tags: - "v*" # Manual trigger lets us test goreleaser end-to-end without cutting a tag. - # Empty tag input -> snapshot mode (goes to /dl/v0.0.0-test/, leaves - # /dl/latest untouched). Tag input -> full release at that tag. + # Empty tag input -> snapshot mode. Tag input -> full release at that tag. workflow_dispatch: inputs: tag: @@ -37,6 +35,12 @@ jobs: # still cheap and avoids surprise tag-resolution failures. fetch-depth: 0 + - name: Check out requested tag + if: github.event_name == 'workflow_dispatch' && inputs.tag != '' + run: | + git fetch --force origin "refs/tags/${{ inputs.tag }}:refs/tags/${{ inputs.tag }}" + git checkout "tags/${{ inputs.tag }}" + - name: Set up Go uses: actions/setup-go@v5 with: @@ -67,26 +71,18 @@ jobs: # One step decides everything that varies by trigger so the rest of # the workflow stays linear: - # - tag push (real release) → kind=release, tag=v*, full release - # - workflow_dispatch with tag → kind=release, tag=input, full release - # - branch push (test) / dispatch → kind=snapshot, tag=v0.0.0-test, snapshot - # Only kind=release updates /dl/latest in OSS. Snapshot runs upload - # to a fixed test prefix and leave the production pointer alone. + # - tag push (real release) -> full GitHub Release + # - workflow_dispatch with tag -> full GitHub Release + # - workflow_dispatch without tag -> local snapshot only - name: Determine release mode id: mode run: | set -euo pipefail if [[ "${{ github.event_name }}" == "push" && "${{ github.ref_type }}" == "tag" ]]; then - echo "kind=release" >> "$GITHUB_OUTPUT" - echo "tag=${{ github.ref_name }}" >> "$GITHUB_OUTPUT" echo "args=release --clean" >> "$GITHUB_OUTPUT" elif [[ "${{ github.event_name }}" == "workflow_dispatch" && -n "${{ inputs.tag }}" ]]; then - echo "kind=release" >> "$GITHUB_OUTPUT" - echo "tag=${{ inputs.tag }}" >> "$GITHUB_OUTPUT" echo "args=release --clean" >> "$GITHUB_OUTPUT" else - echo "kind=snapshot" >> "$GITHUB_OUTPUT" - echo "tag=v0.0.0-test" >> "$GITHUB_OUTPUT" echo "args=release --snapshot --clean" >> "$GITHUB_OUTPUT" fi @@ -97,43 +93,3 @@ jobs: args: ${{ steps.mode.outputs.args }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - # The repo is private, so GitHub Releases are not anonymously - # downloadable. Mirror the archives + checksums to Aliyun OSS so - # install.sh (curl | bash) can fetch them without authentication. - - name: Install ossutil - run: | - curl -fsSL -o /usr/local/bin/ossutil https://gosspublic.alicdn.com/ossutil/1.7.18/ossutil64 - chmod +x /usr/local/bin/ossutil - ossutil --version - - - name: Mirror release artifacts to OSS - env: - OSS_ENDPOINT: ${{ secrets.ALIYUN_OSS_ENDPOINT }} - OSS_AK: ${{ secrets.ALIYUN_OSS_ACCESS_KEY_ID }} - OSS_SK: ${{ secrets.ALIYUN_OSS_ACCESS_KEY_SECRET }} - OSS_BUCKET: ${{ secrets.ALIYUN_OSS_BUCKET }} - TAG: ${{ steps.mode.outputs.tag }} - KIND: ${{ steps.mode.outputs.kind }} - run: | - set -euo pipefail - echo "uploading $TAG (kind=$KIND) to oss://$OSS_BUCKET/dl/$TAG/" - - # Versioned artifacts: aggressive immutable cache (URL contains the tag). - ossutil cp -rf \ - -e "$OSS_ENDPOINT" -i "$OSS_AK" -k "$OSS_SK" \ - --include "*.tar.gz" --include "*.zip" --include "checksums.txt" \ - --meta "Cache-Control:public,max-age=31536000,immutable" \ - dist/ "oss://$OSS_BUCKET/dl/$TAG/" - - if [[ "$KIND" == "release" ]]; then - # latest pointer: short cache so installs see new versions promptly. - printf '%s' "$TAG" > /tmp/one-latest - ossutil cp -f \ - -e "$OSS_ENDPOINT" -i "$OSS_AK" -k "$OSS_SK" \ - --meta "Cache-Control:public,max-age=300,must-revalidate" \ - --meta "Content-Type:text/plain; charset=utf-8" \ - /tmp/one-latest "oss://$OSS_BUCKET/dl/latest" - else - echo "snapshot/test mode: leaving /dl/latest untouched" - fi diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index ad17179..20593ae 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -1,26 +1,29 @@ -# Build the docs site and sync it to the OSS bucket that fronts -# https://one.torchstellar.com. The same bucket also holds /dl//* (binaries), -# populated by .github/workflows/cli.yml. We must NEVER touch -# /dl/* from this workflow — see the guard before the upload step. -# -# Site source lives at apps/docs/ (Next.js + Fumadocs SSG, output: 'export', -# distDir: 'dist'). +# Build the docs site for PR/push confidence. Production deploys are handled +# by the Vercel project linked to apps/docs and the 1cli.dev domain. name: Docs on: + pull_request: + paths: + - "apps/docs/**" + - "package.json" + - "pnpm-lock.yaml" + - "pnpm-workspace.yaml" push: - tags: - - "v*" - # Manual run for ad-hoc redeploys (e.g. docs hotfixes between tags, or - # after editing install.sh without cutting a release). + branches: [master] + paths: + - "apps/docs/**" + - "package.json" + - "pnpm-lock.yaml" + - "pnpm-workspace.yaml" workflow_dispatch: permissions: contents: read jobs: - deploy: + build: runs-on: [self-hosted, Linux, X64] steps: - name: Check out @@ -45,45 +48,3 @@ jobs: - name: Build docs site working-directory: apps/docs run: pnpm build - - - name: Install ossutil - run: | - curl -fsSL -o /usr/local/bin/ossutil https://gosspublic.alicdn.com/ossutil/1.7.18/ossutil64 - chmod +x /usr/local/bin/ossutil - ossutil --version - - - name: Sync apps/docs/dist to OSS - env: - OSS_ENDPOINT: ${{ secrets.ALIYUN_OSS_ENDPOINT }} - OSS_AK: ${{ secrets.ALIYUN_OSS_ACCESS_KEY_ID }} - OSS_SK: ${{ secrets.ALIYUN_OSS_ACCESS_KEY_SECRET }} - OSS_BUCKET: ${{ secrets.ALIYUN_OSS_BUCKET }} - # `ossutil cp` is non-destructive: it uploads/overwrites source - # files but never deletes OSS keys that are missing locally. So - # /dl/* (owned by cli.yml) is naturally preserved as long - # as the build doesn't produce a `apps/docs/dist/dl/` tree. The guard - # below makes that an explicit failure instead of silent damage. - # ossutil v1 --include/--exclude only takes filename globs, not - # directory paths, so we cannot use --exclude "dl/*" defensively. - run: | - set -euo pipefail - if [[ -d apps/docs/dist/dl ]]; then - echo "::error::apps/docs/dist/dl/ exists; that path is reserved for binary distribution" - echo "::error::Refusing to upload — would overwrite the release tree maintained by cli.yml" - exit 1 - fi - - ossutil cp -rf \ - -e "$OSS_ENDPOINT" -i "$OSS_AK" -k "$OSS_SK" \ - --meta "Cache-Control:public,max-age=3600,must-revalidate" \ - apps/docs/dist/ "oss://$OSS_BUCKET/" - - # install.sh gets a shorter cache so script updates roll out - # quickly. Re-upload it explicitly with overriding metadata. - if [[ -f apps/docs/dist/install.sh ]]; then - ossutil cp -f \ - -e "$OSS_ENDPOINT" -i "$OSS_AK" -k "$OSS_SK" \ - --meta "Cache-Control:public,max-age=300,must-revalidate" \ - --meta "Content-Type:text/plain; charset=utf-8" \ - apps/docs/dist/install.sh "oss://$OSS_BUCKET/install.sh" - fi diff --git a/.goreleaser.yaml b/.goreleaser.yaml index ca8d248..9617667 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -1,15 +1,15 @@ # goreleaser config for the Go rewrite of one-cli. # # Cuts cross-platform binaries on every git tag, packs them into per-target -# tarballs/zips, and uploads them to a GitHub Release. The npm wrapper at -# scripts/npm-postinstall.js downloads the matching tarball at install time. +# tarballs/zips, and uploads them to a GitHub Release. install.sh downloads +# the matching tarball from those release assets at install time. # # Run locally: goreleaser release --snapshot --clean # Run on tag: goreleaser release --clean (CI / release pipeline) # -# We keep this in sync with package.json#version: the version baked into -# the binary via -ldflags must match the npm package version that -# distributes it, otherwise `one --version` would lie. +# We keep this in sync with VERSION: the version baked into the binary via +# -ldflags must match the release tag that distributes it, otherwise +# `one --version` would lie. version: 2 @@ -51,9 +51,9 @@ archives: - goos: windows formats: - zip - # The npm shim resolves binaries by archive name. Keep the template - # shape (one-cli_{os}_{arch}) stable so older shims keep working when - # we cut newer releases. + # install.sh resolves binaries by archive name. Keep the template shape + # (one-cli_{os}_{arch}) stable so older installers keep working when we + # cut newer releases. name_template: "one-cli_{{ .Os }}_{{ .Arch }}" files: - LICENSE* @@ -72,10 +72,10 @@ changelog: disable: true release: - # The wrapper downloads from /releases/download// so the + # install.sh downloads from /releases/download// so the # exact GitHub repo coordinates here matter. Adjust if the repo moves. github: - owner: torchstellar-team + owner: 1cli-team name: one-cli draft: false prerelease: auto diff --git a/CLAUDE.md b/CLAUDE.md index cb35fce..9f18f42 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -28,7 +28,7 @@ that `one create` produces for users: `testdata/`). Module path: `github.com/torchstellar-team/one-cli/packages/cli`. - `packages/templates/` — canonical template sources + `registry.json`. - `packages/skills/` — bundled agent skills. -- `apps/docs/` — Next.js + Fumadocs SSG, served at one.torchstellar.com. +- `apps/docs/` — Next.js + Fumadocs SSG, served at 1cli.dev. - `apps/dashboard/` — React + Vite UI shipped with `one serve`. `packages/cli/internal/bundled/` is `go:embed`-ed at build time and diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d694f52..e806bae 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,13 +1,13 @@ # 贡献 one cli -> 这是给"要改 one cli 自己的代码"的人看的。要"用 one cli 起项目"看 [README](./README.md) + [文档站](https://one.torchstellar.com)。 +> 这是给"要改 one cli 自己的代码"的人看的。要"用 one cli 起项目"看 [README](./README.md) + [文档站](https://1cli.dev)。 ## 一次性环境 ```bash brew install go go-task node # macOS;Linux 用 apt / dnf 类比 npm i -g pnpm # 或 corepack enable && corepack prepare pnpm@10 -git clone https://github.com/torchstellar-team/one-cli +git clone https://github.com/1cli-team/one-cli cd one-cli task install-local # 编译 + symlink packages/cli/bin/one 到 ~/.local/bin/one one --version # 验证装好 @@ -82,6 +82,7 @@ CI 会跑跟 `task pre-push` 等价的检查。 - 文档站是 Next.js + Fumadocs SSG - 本地预览:`pnpm --dir apps/docs install && pnpm --dir apps/docs dev` +- 线上部署:Vercel 项目 Root Directory 指向 `apps/docs`,Output Directory 用 `dist`,域名绑定 `1cli.dev` - `apps/docs/content/docs/reference/error-codes.md` **不要手工编辑**——跑 `task gen-error-codes` 重生成 - 新增页面要更新对应目录的 `meta.json`(sidebar 顺序) @@ -121,13 +122,13 @@ git commit -m "chore(release): v0.4.3" git push origin master git tag v0.4.3 git push origin v0.4.3 -# → cli workflow 触发,自动 cross-compile + 上传 GitHub Release + 镜像到 OSS +# → cli workflow 触发,自动 cross-compile + 上传 GitHub Release assets ``` 发布 channel: -- **GitHub Releases** — 主仓库 -- **Aliyun OSS** `/dl//` — `install.sh` 的来源 +- **GitHub Releases** — `install.sh` 下载二进制和 `checksums.txt` 的来源 +- **Vercel** `https://1cli.dev` — 文档站和 `install.sh` - ~~**npm `qzkpwoxtl`**~~ — v0.4.1 起停发 ## 环境变量(开发时常用) diff --git a/README.md b/README.md index caccb77..dcf3940 100644 --- a/README.md +++ b/README.md @@ -24,10 +24,10 @@ One CLI gives you a ready project folder first. You can add more pieces later as Install on macOS or Linux: ```bash -curl -fsSL https://one.torchstellar.com/install.sh | bash +curl -fsSL https://1cli.dev/install.sh | bash ``` -Windows users can download a build from [GitHub Releases](https://github.com/torchstellar-team/one-cli/releases/latest). +Windows users can download a build from [GitHub Releases](https://github.com/1cli-team/one-cli/releases/latest). Create a project: @@ -91,7 +91,7 @@ one add nestjs-api --name api | `one deploy` | Deploy selected parts of the project | | `one skills install` | Teach supported AI assistants how to use One CLI | -Full command docs live at [one.torchstellar.com](https://one.torchstellar.com). +Full command docs live at [1cli.dev](https://1cli.dev). ## Work With AI Assistants @@ -156,11 +156,11 @@ Read [CONTRIBUTING.md](./CONTRIBUTING.md) before opening a pull request. ## Documentation -- [Installation](https://one.torchstellar.com/docs/getting-started/installation/) -- [First project tutorial](https://one.torchstellar.com/tutorials/first-workspace/) -- [Templates](https://one.torchstellar.com/docs/templates/) -- [Command reference](https://one.torchstellar.com/docs/reference/cli-overview/) -- [Error codes](https://one.torchstellar.com/docs/reference/error-codes/) +- [Installation](https://1cli.dev/docs/installation/) +- [First project tutorial](https://1cli.dev/tutorials/first-workspace/) +- [Templates](https://1cli.dev/templates/) +- [Command reference](https://1cli.dev/docs/cli-overview/) +- [Error codes](https://1cli.dev/docs/error-codes/) ## License diff --git a/apps/docs/content/docs/en/installation.md b/apps/docs/content/docs/en/installation.md index 136fe8d..ea946b8 100644 --- a/apps/docs/content/docs/en/installation.md +++ b/apps/docs/content/docs/en/installation.md @@ -12,18 +12,18 @@ Install the `one` binary onto your `PATH`. It should take only a few seconds. ## macOS / Linux One-line Install ```bash -curl -fsSL https://one.torchstellar.com/install.sh | bash +curl -fsSL https://1cli.dev/install.sh | bash ``` The script: 1. Detects `$os/$arch` (`darwin` / `linux`, `amd64` / `arm64`) -2. Resolves the latest version from `one.torchstellar.com/dl/latest` -3. Downloads the matching tarball and verifies SHA256 +2. Resolves the latest version from the GitHub Releases latest redirect +3. Downloads the matching tarball from release assets and verifies SHA256 4. Extracts `one` into `~/.local/bin/one` 5. Tells you if `PATH` needs an update -**Audit the script**: open `https://one.torchstellar.com/install.sh` in a browser. It is plain text. +**Audit the script**: open `https://1cli.dev/install.sh` in a browser. It is plain text. Verify after installation: @@ -46,13 +46,13 @@ Open a new shell. ## Windows / Manual Download -Download the matching archive from [GitHub Releases](https://github.com/torchstellar-team/one-cli/releases/latest) (`darwin/linux/windows x amd64/arm64`), unzip it, and put `one` on `PATH`. +Download the matching archive from [GitHub Releases](https://github.com/1cli-team/one-cli/releases/latest) (`darwin/linux/windows x amd64/arm64`), unzip it, and put `one` on `PATH`. Example for Linux amd64: ```bash curl -L -o one.tar.gz \ - https://github.com/torchstellar-team/one-cli/releases/latest/download/one-cli_linux_amd64.tar.gz + https://github.com/1cli-team/one-cli/releases/latest/download/one-cli_linux_amd64.tar.gz tar -xzf one.tar.gz mv one ~/.local/bin/ one --version @@ -131,16 +131,18 @@ See [Install skill to agent](/en/tutorials/skills-install/). | Variable | Default | Meaning | |---|---|---| -| `ONE_VERSION` | read from `/dl/latest` | Lock the version, for example `v0.1.0` | +| `ONE_VERSION` | resolved from the latest GitHub release | Lock the version, for example `v0.1.0` | | `ONE_INSTALL_DIR` | `$HOME/.local/bin` | Install directory | | `ONE_FORCE` | `0` | Set to `1` to allow downgrade, same-version reinstall, or overwrite a binary whose version cannot be read | -| `ONE_BASE_URL` | `https://one.torchstellar.com` | Mirror override for debugging | +| `ONE_REPO_URL` | `https://github.com/1cli-team/one-cli` | GitHub repo URL override for debugging | +| `ONE_RELEASE_BASE_URL` | `$ONE_REPO_URL/releases/download` | Release asset download base override | +| `ONE_LATEST_URL` | `$ONE_REPO_URL/releases/latest` | Latest release resolver override | | `ONE_SKIP_VERIFY` | `0` | Set to `1` to skip SHA256 verification; debugging only | Install a specific older version into a custom directory: ```bash -curl -fsSL https://one.torchstellar.com/install.sh | ONE_VERSION=v0.1.0 ONE_INSTALL_DIR=/opt/bin bash +curl -fsSL https://1cli.dev/install.sh | ONE_VERSION=v0.1.0 ONE_INSTALL_DIR=/opt/bin bash ``` ## Uninstall @@ -153,10 +155,10 @@ If you also want to remove skills installed by `one skills install`, delete the ## Local Repo Build For Contributors -If you are changing One CLI itself, read [CONTRIBUTING.md](https://github.com/torchstellar-team/one-cli/blob/master/CONTRIBUTING.md). Short version: +If you are changing One CLI itself, read [CONTRIBUTING.md](https://github.com/1cli-team/one-cli/blob/master/CONTRIBUTING.md). Short version: ```bash -git clone https://github.com/torchstellar-team/one-cli +git clone https://github.com/1cli-team/one-cli cd one-cli brew install go go-task # macOS; adapt for Linux task install-local # build current branch and symlink to ~/.local/bin/one @@ -165,7 +167,7 @@ which one one --version ``` -For the full contributor flow, see [CONTRIBUTING.md](https://github.com/torchstellar-team/one-cli/blob/master/CONTRIBUTING.md). For command-surface reference, see [Command overview](/en/docs/cli-overview/). +For the full contributor flow, see [CONTRIBUTING.md](https://github.com/1cli-team/one-cli/blob/master/CONTRIBUTING.md). For command-surface reference, see [Command overview](/en/docs/cli-overview/). ## Installed? diff --git a/apps/docs/content/docs/en/skills.md b/apps/docs/content/docs/en/skills.md index a4d0900..fd4600a 100644 --- a/apps/docs/content/docs/en/skills.md +++ b/apps/docs/content/docs/en/skills.md @@ -17,7 +17,7 @@ One CLI is the **author** of these skills, not a delivery channel for third-part Covers every routine task **inside or on the way into** a One CLI workspace: create a workspace, add a project, fix a manifest, look up a command / JSON schema / error code. -Trigger keywords (from [SKILL.md](https://github.com/torchstellar-team/one-cli/blob/master/packages/skills/one-cli/SKILL.md) frontmatter): +Trigger keywords (from [SKILL.md](https://github.com/1cli-team/one-cli/blob/master/packages/skills/one-cli/SKILL.md) frontmatter): | Bucket | English | 中文 | |---|---|---| @@ -80,8 +80,8 @@ one skills install --yes The full skill bodies are intentionally **not inlined here** (to avoid drift against the source). Read them directly in the repo: -- [`packages/skills/one-cli/`](https://github.com/torchstellar-team/one-cli/tree/master/packages/skills/one-cli) — SKILL.md + references/INDEX.md + each playbook -- [`packages/skills/one-migrate/`](https://github.com/torchstellar-team/one-cli/tree/master/packages/skills/one-migrate) — same shape +- [`packages/skills/one-cli/`](https://github.com/1cli-team/one-cli/tree/master/packages/skills/one-cli) — SKILL.md + references/INDEX.md + each playbook +- [`packages/skills/one-migrate/`](https://github.com/1cli-team/one-cli/tree/master/packages/skills/one-migrate) — same shape Or open the local store after install: `~/.one/skills-store/one-bundled/`. diff --git a/apps/docs/content/docs/zh/installation.md b/apps/docs/content/docs/zh/installation.md index 110d547..0e7aa93 100644 --- a/apps/docs/content/docs/zh/installation.md +++ b/apps/docs/content/docs/zh/installation.md @@ -12,18 +12,18 @@ description: 把 one cli 装到本机 — macOS / Linux 一行装,Windows 手 ## macOS / Linux 一行装 ```bash -curl -fsSL https://one.torchstellar.com/install.sh | bash +curl -fsSL https://1cli.dev/install.sh | bash ``` 脚本会: 1. 检测 `$os/$arch`(darwin/linux × amd64/arm64) -2. 从 `one.torchstellar.com/dl/latest` 解析最新版本 -3. 下载对应 tarball + 校验 SHA256 +2. 从 GitHub Releases 的 latest redirect 解析最新版本 +3. 从对应 release assets 下载 tarball + 校验 SHA256 4. 解压到 `~/.local/bin/one` 5. 提示 PATH 是否需要补全 -**审计脚本**:直接浏览器访问 `https://one.torchstellar.com/install.sh`,纯文本可读。 +**审计脚本**:直接浏览器访问 `https://1cli.dev/install.sh`,纯文本可读。 跑完确认: @@ -46,13 +46,13 @@ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc ## Windows / 不想跑脚本 -从 [GitHub Releases](https://github.com/torchstellar-team/one-cli/releases/latest) 下载对应平台归档(`darwin/linux/windows × amd64/arm64`),解压把 `one` 放到 PATH。 +从 [GitHub Releases](https://github.com/1cli-team/one-cli/releases/latest) 下载对应平台归档(`darwin/linux/windows × amd64/arm64`),解压把 `one` 放到 PATH。 例(Linux amd64): ```bash curl -L -o one.tar.gz \ - https://github.com/torchstellar-team/one-cli/releases/latest/download/one-cli_linux_amd64.tar.gz + https://github.com/1cli-team/one-cli/releases/latest/download/one-cli_linux_amd64.tar.gz tar -xzf one.tar.gz mv one ~/.local/bin/ one --version @@ -131,16 +131,18 @@ one configure add container/ghcr --profile ghcr # GHCR username + PAT | 变量 | 默认 | 说明 | |---|---|---| -| `ONE_VERSION` | (读 `/dl/latest`) | 锁版本,例如 `v0.1.0` | +| `ONE_VERSION` | (解析 GitHub latest release) | 锁版本,例如 `v0.1.0` | | `ONE_INSTALL_DIR` | `$HOME/.local/bin` | 安装目录 | | `ONE_FORCE` | `0` | 设为 `1` 允许降级 / 同版本重装 / 覆盖读不出版本号的二进制 | -| `ONE_BASE_URL` | `https://one.torchstellar.com` | 镜像源覆盖(调试用) | +| `ONE_REPO_URL` | `https://github.com/1cli-team/one-cli` | GitHub repo URL 覆盖(调试用) | +| `ONE_RELEASE_BASE_URL` | `$ONE_REPO_URL/releases/download` | release assets 下载源覆盖 | +| `ONE_LATEST_URL` | `$ONE_REPO_URL/releases/latest` | latest release 解析地址覆盖 | | `ONE_SKIP_VERIFY` | `0` | 设为 `1` 跳过 SHA256 校验(仅调试) | 例:装一个特定旧版本到自定义目录: ```bash -curl -fsSL https://one.torchstellar.com/install.sh | ONE_VERSION=v0.1.0 ONE_INSTALL_DIR=/opt/bin bash +curl -fsSL https://1cli.dev/install.sh | ONE_VERSION=v0.1.0 ONE_INSTALL_DIR=/opt/bin bash ``` ## 卸载 @@ -153,10 +155,10 @@ rm ~/.local/bin/one ## 本地编译版(贡献开发用) -如果你要改 one cli 自己的代码,看 [CONTRIBUTING.md](https://github.com/torchstellar-team/one-cli/blob/master/CONTRIBUTING.md)。一句话: +如果你要改 one cli 自己的代码,看 [CONTRIBUTING.md](https://github.com/1cli-team/one-cli/blob/master/CONTRIBUTING.md)。一句话: ```bash -git clone https://github.com/torchstellar-team/one-cli +git clone https://github.com/1cli-team/one-cli cd one-cli brew install go go-task # macOS;Linux 类比 task install-local # 编译当前分支并 symlink 到 ~/.local/bin/one @@ -165,7 +167,7 @@ which one one --version ``` -开发期完整流程见 [CONTRIBUTING.md](https://github.com/torchstellar-team/one-cli/blob/master/CONTRIBUTING.md);命令面速查见 [命令总览](/zh/docs/cli-overview/)。 +开发期完整流程见 [CONTRIBUTING.md](https://github.com/1cli-team/one-cli/blob/master/CONTRIBUTING.md);命令面速查见 [命令总览](/zh/docs/cli-overview/)。 ## 装完了? diff --git a/apps/docs/content/docs/zh/skills.md b/apps/docs/content/docs/zh/skills.md index f5f4f3f..2eda1ef 100644 --- a/apps/docs/content/docs/zh/skills.md +++ b/apps/docs/content/docs/zh/skills.md @@ -17,7 +17,7 @@ One CLI 自己就是这两个 skill 的提供方,所以**装 skill ≠ 装外 覆盖**已经接入 / 想接入 One CLI 工作区**的全部日常动作:创建工作区、加项目、修 manifest、查命令 / JSON schema / 错误码。 -触发关键词(来自 [SKILL.md](https://github.com/torchstellar-team/one-cli/blob/master/packages/skills/one-cli/SKILL.md) frontmatter description): +触发关键词(来自 [SKILL.md](https://github.com/1cli-team/one-cli/blob/master/packages/skills/one-cli/SKILL.md) frontmatter description): | 类别 | 中文 | 英文 | |---|---|---| @@ -80,8 +80,8 @@ one skills install --yes Skill 全文不在本站 inline(避免与源同步漂移),直接到仓库读: -- [`packages/skills/one-cli/`](https://github.com/torchstellar-team/one-cli/tree/master/packages/skills/one-cli) —— SKILL.md + references/INDEX.md + 各 playbook -- [`packages/skills/one-migrate/`](https://github.com/torchstellar-team/one-cli/tree/master/packages/skills/one-migrate) —— 同上 +- [`packages/skills/one-cli/`](https://github.com/1cli-team/one-cli/tree/master/packages/skills/one-cli) —— SKILL.md + references/INDEX.md + 各 playbook +- [`packages/skills/one-migrate/`](https://github.com/1cli-team/one-cli/tree/master/packages/skills/one-migrate) —— 同上 或者装完之后直接打开本地 store 目录:`~/.one/skills-store/one-bundled/`。 diff --git a/apps/docs/content/tutorials/en/env-multi-env.mdx b/apps/docs/content/tutorials/en/env-multi-env.mdx index 89c33c7..7b9926e 100644 --- a/apps/docs/content/tutorials/en/env-multi-env.mdx +++ b/apps/docs/content/tutorials/en/env-multi-env.mdx @@ -111,7 +111,7 @@ env: INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET: ${{ secrets.INFISICAL_CLIENT_SECRET }} steps: - uses: actions/checkout@v4 - - run: curl -fsSL https://one.torchstellar.com/install.sh | bash + - run: curl -fsSL https://1cli.dev/install.sh | bash - run: one env pull --env staging - run: pnpm install && pnpm test ``` diff --git a/apps/docs/content/tutorials/en/first-workspace.mdx b/apps/docs/content/tutorials/en/first-workspace.mdx index 01d1cfe..06faf0e 100644 --- a/apps/docs/content/tutorials/en/first-workspace.mdx +++ b/apps/docs/content/tutorials/en/first-workspace.mdx @@ -8,7 +8,7 @@ This tutorial covers exactly one command: `one create`. Picking which templates ## 1. Install the CLI ```bash -curl -fsSL https://one.torchstellar.com/install.sh | bash +curl -fsSL https://1cli.dev/install.sh | bash one --version ``` diff --git a/apps/docs/content/tutorials/en/json-output-error-codes.mdx b/apps/docs/content/tutorials/en/json-output-error-codes.mdx index 4012dae..2147b58 100644 --- a/apps/docs/content/tutorials/en/json-output-error-codes.mdx +++ b/apps/docs/content/tutorials/en/json-output-error-codes.mdx @@ -139,7 +139,7 @@ Pinning `-o json` in CI means your pipeline behavior depends on stable code name {/* verify-cli:ignore-start */} ```yaml -- run: curl -fsSL https://one.torchstellar.com/install.sh | bash -s -- --version v0.1.0 +- run: curl -fsSL https://1cli.dev/install.sh | bash -s -- --version v0.1.0 - run: one -o json add nestjs-api --name api --yes ``` {/* verify-cli:ignore-end */} diff --git a/apps/docs/content/tutorials/en/templates.mdx b/apps/docs/content/tutorials/en/templates.mdx index e8c6362..9f53d40 100644 --- a/apps/docs/content/tutorials/en/templates.mdx +++ b/apps/docs/content/tutorials/en/templates.mdx @@ -10,7 +10,7 @@ This is the page you open before you create a workspace. It does two things: You don't run anything in this tutorial. Picking a template here, then running the command in your terminal, is the [next chapter](/en/tutorials/first-workspace/). -Open [https://one.torchstellar.com/en/templates/](/en/templates/). +Open [https://1cli.dev/en/templates/](/en/templates/). ## 1. Browse preset templates diff --git a/apps/docs/content/tutorials/zh/env-multi-env.mdx b/apps/docs/content/tutorials/zh/env-multi-env.mdx index 9e86020..6a7735e 100644 --- a/apps/docs/content/tutorials/zh/env-multi-env.mdx +++ b/apps/docs/content/tutorials/zh/env-multi-env.mdx @@ -111,7 +111,7 @@ env: INFISICAL_UNIVERSAL_AUTH_CLIENT_SECRET: ${{ secrets.INFISICAL_CLIENT_SECRET }} steps: - uses: actions/checkout@v4 - - run: curl -fsSL https://one.torchstellar.com/install.sh | bash + - run: curl -fsSL https://1cli.dev/install.sh | bash - run: one env pull --env staging - run: pnpm install && pnpm test ``` diff --git a/apps/docs/content/tutorials/zh/first-workspace.mdx b/apps/docs/content/tutorials/zh/first-workspace.mdx index 98762cd..555baf7 100644 --- a/apps/docs/content/tutorials/zh/first-workspace.mdx +++ b/apps/docs/content/tutorials/zh/first-workspace.mdx @@ -8,7 +8,7 @@ description: 直接在终端跑 one create。看清它往磁盘写了什么、 ## 1. 装 One CLI ```bash -curl -fsSL https://one.torchstellar.com/install.sh | bash +curl -fsSL https://1cli.dev/install.sh | bash one --version ``` diff --git a/apps/docs/content/tutorials/zh/json-output-error-codes.mdx b/apps/docs/content/tutorials/zh/json-output-error-codes.mdx index c1db3e0..f56c4db 100644 --- a/apps/docs/content/tutorials/zh/json-output-error-codes.mdx +++ b/apps/docs/content/tutorials/zh/json-output-error-codes.mdx @@ -139,7 +139,7 @@ CI 里钉死 `-o json` 等于把流水线行为绑定到稳定的码名上,不 {/* verify-cli:ignore-start */} ```yaml -- run: curl -fsSL https://one.torchstellar.com/install.sh | bash -s -- --version v0.1.0 +- run: curl -fsSL https://1cli.dev/install.sh | bash -s -- --version v0.1.0 - run: one -o json add nestjs-api --name api --yes ``` {/* verify-cli:ignore-end */} diff --git a/apps/docs/content/tutorials/zh/templates.mdx b/apps/docs/content/tutorials/zh/templates.mdx index eb8da1a..faf8413 100644 --- a/apps/docs/content/tutorials/zh/templates.mdx +++ b/apps/docs/content/tutorials/zh/templates.mdx @@ -10,7 +10,7 @@ description: 在 docs 站的模板页挑模板、配部署目标,复制生成 本章**不跑任何命令**。在这里挑好模板拿到命令,然后在终端真正执行,是[下一章](/zh/tutorials/first-workspace/)。 -打开 [https://one.torchstellar.com/zh/templates/](/zh/templates/)。 +打开 [https://1cli.dev/zh/templates/](/zh/templates/)。 ## 1. 浏览预设模板 diff --git a/apps/docs/next.config.mjs b/apps/docs/next.config.mjs index 8c8d773..5293f14 100644 --- a/apps/docs/next.config.mjs +++ b/apps/docs/next.config.mjs @@ -4,9 +4,9 @@ const withMDX = createMDX(); /** @type {import('next').NextConfig} */ const config = { - // SSG: 全静态导出,对接 website-deploy.yml 现有 OSS 上传逻辑。 + // SSG: 全静态导出,交给 Vercel 作为静态 Next.js 文档站托管。 output: "export", - // CI 上传 docs/dist/ 到 OSS(见 .github/workflows/website-deploy.yml)。 + // Vercel 的 Output Directory 指向 apps/docs/dist。 distDir: "dist", // SSG 模式下 next/image 默认依赖 server,关掉优化用原图。 images: { unoptimized: true }, diff --git a/apps/docs/public/install.sh b/apps/docs/public/install.sh index ac60f72..edbecf5 100644 --- a/apps/docs/public/install.sh +++ b/apps/docs/public/install.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash # install.sh — One CLI installer for macOS / Linux. # -# curl -fsSL https://one.torchstellar.com/install.sh | bash +# curl -fsSL https://1cli.dev/install.sh | bash # # Default behavior: # - First install (no existing binary): install. @@ -10,11 +10,14 @@ # - Target older than current: refuse (downgrade requires ONE_FORCE=1). # # Configurable env vars: -# ONE_VERSION Pin a version (vX.Y.Z). Default: read $ONE_BASE_URL/dl/latest. +# ONE_VERSION Pin a version (vX.Y.Z). Default: follow $ONE_LATEST_URL. # ONE_INSTALL_DIR Install dir. Default: $HOME/.local/bin (matches `task install-local`). # ONE_FORCE Set to 1 to allow downgrade, force-reinstall the same version, # or overwrite an existing binary whose version can't be read. -# ONE_BASE_URL Override the origin. Default: https://one.torchstellar.com. +# ONE_REPO_URL Override the GitHub repo URL. Default: https://github.com/1cli-team/one-cli. +# ONE_RELEASE_BASE_URL +# Override release asset base. Default: $ONE_REPO_URL/releases/download. +# ONE_LATEST_URL Override latest release URL. Default: $ONE_REPO_URL/releases/latest. # ONE_SKIP_VERIFY Set to 1 to skip SHA256 verification (debugging only). set -euo pipefail @@ -23,7 +26,9 @@ set -euo pipefail # leave a partial install behind: main is only called after the script # is fully sourced. main() { - : "${ONE_BASE_URL:=https://one.torchstellar.com}" + : "${ONE_REPO_URL:=https://github.com/1cli-team/one-cli}" + : "${ONE_RELEASE_BASE_URL:=${ONE_REPO_URL%/}/releases/download}" + : "${ONE_LATEST_URL:=${ONE_REPO_URL%/}/releases/latest}" : "${ONE_INSTALL_DIR:=$HOME/.local/bin}" : "${ONE_FORCE:=0}" : "${ONE_SKIP_VERIFY:=0}" @@ -53,7 +58,7 @@ detect_platform() { Darwin) OS="darwin" ;; Linux) OS="linux" ;; *) - err "unsupported OS: $(uname -s). Download a binary manually from https://github.com/torchstellar-team/one-cli/releases/latest" + err "unsupported OS: $(uname -s). Download a binary manually from https://github.com/1cli-team/one-cli/releases/latest" exit 1 ;; esac @@ -71,13 +76,20 @@ detect_platform() { resolve_version() { if [[ -z "${ONE_VERSION:-}" ]]; then - info "resolving latest version from $ONE_BASE_URL/dl/latest" - if ! ONE_VERSION=$(curl -fsSL --retry 3 "$ONE_BASE_URL/dl/latest" 2>/dev/null); then - err "failed to fetch /dl/latest. Set ONE_VERSION=vX.Y.Z to bypass." + info "resolving latest version from $ONE_LATEST_URL" + local effective_url + if ! effective_url=$(curl -fsSL --retry 3 -o /dev/null -w '%{url_effective}' "$ONE_LATEST_URL" 2>/dev/null); then + err "failed to resolve latest GitHub release. Set ONE_VERSION=vX.Y.Z to bypass." + exit 1 + fi + ONE_VERSION="${effective_url##*/}" + if [[ "$ONE_VERSION" == "latest" || "$ONE_VERSION" == "releases" || -z "$ONE_VERSION" ]]; then + err "could not infer a release tag from $effective_url." + err "Make sure the GitHub repo has at least one release, or set ONE_VERSION=vX.Y.Z." exit 1 fi - ONE_VERSION=$(printf '%s' "$ONE_VERSION" | tr -d '[:space:]') fi + ONE_VERSION=$(printf '%s' "$ONE_VERSION" | tr -d '[:space:]') case "$ONE_VERSION" in v[0-9]*) ;; *) err "invalid version format: '$ONE_VERSION' (expected vX.Y.Z)"; exit 1 ;; @@ -191,8 +203,8 @@ preflight() { download_and_verify() { archive="one-cli_${OS}_${ARCH}.tar.gz" - archive_url="$ONE_BASE_URL/dl/$ONE_VERSION/$archive" - checksum_url="$ONE_BASE_URL/dl/$ONE_VERSION/checksums.txt" + archive_url="${ONE_RELEASE_BASE_URL%/}/$ONE_VERSION/$archive" + checksum_url="${ONE_RELEASE_BASE_URL%/}/$ONE_VERSION/checksums.txt" TMP=$(mktemp -d -t one-cli-installer.XXXXXX) trap 'rm -rf "$TMP"' EXIT diff --git a/apps/docs/src/app/(home)/home-page.tsx b/apps/docs/src/app/(home)/home-page.tsx index 83e0ad6..8ee50f7 100644 --- a/apps/docs/src/app/(home)/home-page.tsx +++ b/apps/docs/src/app/(home)/home-page.tsx @@ -28,7 +28,7 @@ import { HomeHeroCanvas } from "./hero-canvas"; import { HomeCopyButton } from "./home-template-preview"; import { WorkflowSidebarNav, type WorkflowNavIcon } from "./workflow-nav"; -const installCommand = "curl -fsSL one.torchstellar.com/install.sh | bash"; +const installCommand = "curl -fsSL https://1cli.dev/install.sh | bash"; const homeCopy = { zh: { @@ -331,7 +331,7 @@ const homeCopy = { bullets: ["按产品类型浏览", "现成示例和自定义组合都支持", "复制命令后自己运行或交给 AI"], cta: "进入模板页", metaLabel: "模板页入口", - metaValue: "one.torchstellar.com /zh/templates/", + metaValue: "1cli.dev /zh/templates/", }, ai: { label: "方式三", @@ -693,7 +693,7 @@ const homeCopy = { bullets: ["Browse by product type", "Use ready examples or custom mixes", "Run the command yourself or hand it to AI"], cta: "Open templates", metaLabel: "Template page", - metaValue: "one.torchstellar.com /en/templates/", + metaValue: "1cli.dev /en/templates/", }, ai: { label: "Option three", @@ -819,7 +819,7 @@ function HomeNav({ lang, text }: { lang: Locale; text: HomeText }) { [text.nav.docs, localizedDocsPath(lang, ["quick-start"])], [text.nav.templates, localizedTemplatesPath(lang)], [text.nav.blog, localizedBlogPath(lang)], - [text.nav.changelog, "https://github.com/torchstellar-team/one-cli/blob/master/CHANGELOG.md"], + [text.nav.changelog, "https://github.com/1cli-team/one-cli/blob/master/CHANGELOG.md"], ] as const; return ( @@ -848,7 +848,7 @@ function HomeNav({ lang, text }: { lang: Locale; text: HomeText }) {

- one.torchstellar.com + 1cli.dev {templatesHref}

@@ -1350,7 +1350,7 @@ function FinalCTA({ lang, text }: { lang: Locale; text: HomeText }) {
diff --git a/apps/docs/src/app/(home)/home-template-preview.tsx b/apps/docs/src/app/(home)/home-template-preview.tsx index e16b19d..a44e51d 100644 --- a/apps/docs/src/app/(home)/home-template-preview.tsx +++ b/apps/docs/src/app/(home)/home-template-preview.tsx @@ -97,7 +97,7 @@ export function HomeTemplatePreview({ lang = "zh" }: { lang?: Locale }) { {text.label}
- one.torchstellar.com + 1cli.dev {text.path}
diff --git a/apps/docs/src/app/[lang]/blog/[slug]/page.tsx b/apps/docs/src/app/[lang]/blog/[slug]/page.tsx index 85e2284..2966783 100644 --- a/apps/docs/src/app/[lang]/blog/[slug]/page.tsx +++ b/apps/docs/src/app/[lang]/blog/[slug]/page.tsx @@ -109,7 +109,7 @@ export default async function BlogArticleRoute(props: { {post.readingTime} {labels.readTime}
diff --git a/apps/docs/src/app/[lang]/docs/[[...slug]]/page.tsx b/apps/docs/src/app/[lang]/docs/[[...slug]]/page.tsx index 8273e1e..f17eec8 100644 --- a/apps/docs/src/app/[lang]/docs/[[...slug]]/page.tsx +++ b/apps/docs/src/app/[lang]/docs/[[...slug]]/page.tsx @@ -131,7 +131,7 @@ function ArticleMeta({ docPath, lang }: { docPath: string; lang: Locale }) { {labels.updated} diff --git a/apps/docs/src/app/[lang]/tutorials/[[...slug]]/page.tsx b/apps/docs/src/app/[lang]/tutorials/[[...slug]]/page.tsx index e337329..a34f7fb 100644 --- a/apps/docs/src/app/[lang]/tutorials/[[...slug]]/page.tsx +++ b/apps/docs/src/app/[lang]/tutorials/[[...slug]]/page.tsx @@ -158,7 +158,7 @@ function ArticleMeta({ {labels.updated} diff --git a/apps/docs/src/app/docs/docs-toc.tsx b/apps/docs/src/app/docs/docs-toc.tsx index f51db21..5041b00 100644 --- a/apps/docs/src/app/docs/docs-toc.tsx +++ b/apps/docs/src/app/docs/docs-toc.tsx @@ -43,7 +43,7 @@ export function DocsToc({ docPath, items, lang }: DocsTocProps) {
@@ -51,7 +51,7 @@ export function DocsToc({ docPath, items, lang }: DocsTocProps) { {labels.edit} diff --git a/apps/docs/src/app/layout.config.tsx b/apps/docs/src/app/layout.config.tsx index a6e3da5..16a2cbb 100644 --- a/apps/docs/src/app/layout.config.tsx +++ b/apps/docs/src/app/layout.config.tsx @@ -24,7 +24,7 @@ export const baseOptions: BaseLayoutProps = { { text: "Blog", url: "/zh/blog/", active: "nested-url" }, { text: "Changelog", - url: "https://github.com/torchstellar-team/one-cli/blob/master/CHANGELOG.md", + url: "https://github.com/1cli-team/one-cli/blob/master/CHANGELOG.md", external: true, }, ], diff --git a/apps/docs/src/app/layout.tsx b/apps/docs/src/app/layout.tsx index 41b08cc..5cc76f3 100644 --- a/apps/docs/src/app/layout.tsx +++ b/apps/docs/src/app/layout.tsx @@ -8,7 +8,7 @@ import { cn } from "@/lib/utils"; const geist = Geist({subsets:['latin'],variable:'--font-sans'}); export const metadata = { - metadataBase: new URL("https://one.torchstellar.com"), + metadataBase: new URL("https://1cli.dev"), title: "One CLI", description: "面向团队工作区的脚手架与治理工具", icons: { diff --git a/apps/docs/src/app/sitemap.ts b/apps/docs/src/app/sitemap.ts index ce159be..4678762 100644 --- a/apps/docs/src/app/sitemap.ts +++ b/apps/docs/src/app/sitemap.ts @@ -7,7 +7,7 @@ import { import { getAllBlogPosts } from "@/lib/blog"; import { source } from "@/lib/source"; -const siteUrl = "https://one.torchstellar.com"; +const siteUrl = "https://1cli.dev"; export const dynamic = "force-static"; diff --git a/apps/docs/src/components/site-top-nav.tsx b/apps/docs/src/components/site-top-nav.tsx index bd78b41..9da23bf 100644 --- a/apps/docs/src/components/site-top-nav.tsx +++ b/apps/docs/src/components/site-top-nav.tsx @@ -61,7 +61,7 @@ export function SiteTopNav({ ))} @@ -77,7 +77,7 @@ export function SiteTopNav({
100ms, the GitHub-equivalent /dl/latest endpoint usually +// commands run >100ms, the GitHub Releases redirect usually // responds in <300ms over good network, and long-running commands // (`one serve`, `one dev`, `one env pull`) easily give the goroutine // time to finish. @@ -67,7 +67,7 @@ func MaybeRefreshAsync(currentVersion string) { // notifyWait is how long Notify will block waiting for an in-flight // refresh goroutine to finish. Short enough not to be perceptible // (CLI usability research puts the human-noticeable threshold at ~200ms), -// long enough that a typical /dl/latest round-trip on a residential +// long enough that a typical latest-release round-trip on a residential // connection (~80ms warm DNS, ~50ms TLS, ~50ms response) usually fits. const notifyWait = 200 * time.Millisecond diff --git a/packages/cli/internal/updatecheck/checker.go b/packages/cli/internal/updatecheck/checker.go index 8be4f06..6f13a20 100644 --- a/packages/cli/internal/updatecheck/checker.go +++ b/packages/cli/internal/updatecheck/checker.go @@ -1,9 +1,8 @@ package updatecheck // HTTP fetch of the canonical "latest stable version" string. Uses the -// same source the installer reads (apps/docs/public/install.sh:74), so the -// notification can never disagree with what `install.sh` would actually -// download. +// same GitHub Releases redirect the installer follows, so the notification +// can never disagree with what `install.sh` would actually download. import ( "context" @@ -14,10 +13,9 @@ import ( "time" ) -// latestEndpoint is the source of truth, owned by torchstellar's docs -// origin. Plain-text body, content `vX.Y.Z\n`. No JSON parsing, no rate -// limit (vs GitHub API's 60 req/h unauthenticated). -const latestEndpoint = "https://one.torchstellar.com/dl/latest" +// latestEndpoint is the source of truth. GitHub redirects this URL to +// /releases/tag/vX.Y.Z, which avoids the unauthenticated API rate limit. +const latestEndpoint = "https://github.com/1cli-team/one-cli/releases/latest" // fetchTimeout caps the network call. 5s is generous for a CDN-served // text file; if it's slower we'd rather fail and retry on the next 24h @@ -25,9 +23,9 @@ const latestEndpoint = "https://one.torchstellar.com/dl/latest" const fetchTimeout = 5 * time.Second // fetchLatest GETs the latest version string. Returns the normalized -// `vX.Y.Z` form. Any failure (network, HTTP non-2xx, garbage body) is -// surfaced as an error; the caller treats all errors as "skip cache -// update, try again next time". +// `vX.Y.Z` form. Any failure (network, HTTP non-2xx, garbage response) is +// surfaced as an error; the caller treats all errors as "skip cache update, +// try again next time". func fetchLatest(ctx context.Context, currentVersion string) (string, error) { ctx, cancel := context.WithTimeout(ctx, fetchTimeout) defer cancel() @@ -47,8 +45,11 @@ func fetchLatest(ctx context.Context, currentVersion string) (string, error) { if resp.StatusCode != http.StatusOK { return "", fmt.Errorf("updatecheck: %s returned %d", latestEndpoint, resp.StatusCode) } - // Cap the body read — should be a tiny version string. Anything - // bigger than 64 bytes is suspect (longest plausible: "v999.999.999-rc99\n" ≈ 18). + if v := versionFromReleasePath(resp.Request.URL.Path); v != "" { + return v, nil + } + // Fallback for mirrors that return a plain version string instead of a + // GitHub-style redirect. Cap the body read because it should be tiny. raw, err := io.ReadAll(io.LimitReader(resp.Body, 64)) if err != nil { return "", err @@ -59,3 +60,15 @@ func fetchLatest(ctx context.Context, currentVersion string) (string, error) { } return v, nil } + +func versionFromReleasePath(path string) string { + parts := strings.Split(strings.Trim(path, "/"), "/") + if len(parts) < 3 { + return "" + } + n := len(parts) + if parts[n-3] != "releases" || parts[n-2] != "tag" { + return "" + } + return normalizeTag(parts[n-1]) +} diff --git a/packages/cli/internal/updatecheck/checker_test.go b/packages/cli/internal/updatecheck/checker_test.go index b6fc1ac..1ead872 100644 --- a/packages/cli/internal/updatecheck/checker_test.go +++ b/packages/cli/internal/updatecheck/checker_test.go @@ -24,6 +24,9 @@ func fetchAt(ctx context.Context, url, currentVersion string) (string, error) { if resp.StatusCode != http.StatusOK { return "", &httpError{status: resp.StatusCode} } + if v := versionFromReleasePath(resp.Request.URL.Path); v != "" { + return v, nil + } buf := make([]byte, 64) n, _ := resp.Body.Read(buf) v := normalizeTag(strings.TrimSpace(string(buf[:n]))) @@ -58,6 +61,27 @@ func TestFetch_Happy(t *testing.T) { } } +func TestFetch_GitHubLatestRedirect(t *testing.T) { + srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + switch r.URL.Path { + case "/latest": + http.Redirect(w, r, "/releases/tag/v0.9.0", http.StatusFound) + case "/releases/tag/v0.9.0": + _, _ = w.Write([]byte("release page")) + default: + t.Fatalf("unexpected path: %s", r.URL.Path) + } + })) + defer srv.Close() + got, err := fetchAt(context.Background(), srv.URL+"/latest", "v0.8.0") + if err != nil { + t.Fatalf("fetch: %v", err) + } + if got != "v0.9.0" { + t.Errorf("got %q, want v0.9.0", got) + } +} + func TestFetch_Non2xx(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(503) @@ -90,5 +114,5 @@ func TestFetchLatest_RealURL_Skipped(t *testing.T) { if err != nil { t.Fatalf("real fetch: %v", err) } - t.Logf("live /dl/latest = %s", v) + t.Logf("live latest release = %s", v) } diff --git a/packages/cli/internal/updatecheck/notify.go b/packages/cli/internal/updatecheck/notify.go index 4844c03..784af2e 100644 --- a/packages/cli/internal/updatecheck/notify.go +++ b/packages/cli/internal/updatecheck/notify.go @@ -16,7 +16,7 @@ import ( // installCommand is what the warning tells the user to run. Matches the // command in [README.md](README.md) so the notification's recommendation // is the same path users have already seen. -const installCommand = "curl -fsSL https://one.torchstellar.com/install.sh | bash" +const installCommand = "curl -fsSL https://1cli.dev/install.sh | bash" // Notify reads the cached check result and prints a yellow warning to // stderr if a strictly newer version is available. Idempotent and diff --git a/packages/cli/internal/updatecheck/semver.go b/packages/cli/internal/updatecheck/semver.go index fa72d5c..0a317b3 100644 --- a/packages/cli/internal/updatecheck/semver.go +++ b/packages/cli/internal/updatecheck/semver.go @@ -3,8 +3,8 @@ package updatecheck // Minimal vX.Y.Z comparison without pulling golang.org/x/mod/semver. We // only need a less-than test: "is `latest` strictly newer than the running // binary's version?" — anything more nuanced (pre-release ordering, build -// metadata) is out of scope because /dl/latest only ever returns stable -// releases. +// metadata) is out of scope because the latest-release endpoint is only +// expected to resolve to stable releases. import ( "strconv" @@ -72,9 +72,9 @@ func parseTriple(v string) ([3]int, bool) { return out, true } -// normalizeTag re-shapes whatever /dl/latest returned into a canonical -// `vX.Y.Z` (no pre-release suffix). Empty / unparseable input → "" so the -// caller can short-circuit cache writes. +// normalizeTag re-shapes a release tag into a canonical `vX.Y.Z` (no +// pre-release suffix). Empty / unparseable input → "" so the caller can +// short-circuit cache writes. func normalizeTag(raw string) string { t, ok := parseTriple(raw) if !ok { diff --git a/packages/skills/one-cli/SKILL.md b/packages/skills/one-cli/SKILL.md index d4fe478..a994c10 100644 --- a/packages/skills/one-cli/SKILL.md +++ b/packages/skills/one-cli/SKILL.md @@ -9,7 +9,7 @@ metadata: # One CLI — Unified Skill -This skill covers every interaction with [One CLI](https://github.com/torchstellar-team/one-cli), +This skill covers every interaction with [One CLI](https://github.com/1cli-team/one-cli), a Go-based scaffolding + governance tool for AI-Native monorepo workspaces. Commands are minimal (`create`, `add`, `templates`, `env`, `container`, `dev`, `deploy`, `run`, `configure`, `serve`, `skills`), @@ -44,11 +44,11 @@ If this command fails, **stop and tell the user**: > One CLI 还没装。请用 curl 一键安装(macOS / Linux): > > ```bash -> curl -fsSL https:///install.sh | bash +> curl -fsSL https://1cli.dev/install.sh | bash > ``` > > 或从 GitHub Releases 下载对应平台的归档: -> https://github.com/torchstellar-team/one-cli/releases/latest +> https://github.com/1cli-team/one-cli/releases/latest > > 装完再回来重试这个请求。 @@ -140,6 +140,6 @@ For the complete code → recovery mapping see `references/REFERENCE.md`. ## References -- One CLI repo: -- Error code reference: (Codes registry — source of truth) +- One CLI repo: +- Error code reference: (Codes registry — source of truth) - Agent Skills format spec: diff --git a/packages/skills/one-migrate/SKILL.md b/packages/skills/one-migrate/SKILL.md index 0d73e66..4cf39f3 100644 --- a/packages/skills/one-migrate/SKILL.md +++ b/packages/skills/one-migrate/SKILL.md @@ -57,11 +57,11 @@ If this command fails, **stop and tell the user**: > One CLI 还没装。请用 curl 一键安装(macOS / Linux): > > ```bash -> curl -fsSL https:///install.sh | bash +> curl -fsSL https://1cli.dev/install.sh | bash > ``` > > 或从 GitHub Releases 下载对应平台的归档: -> https://github.com/torchstellar-team/one-cli/releases/latest +> https://github.com/1cli-team/one-cli/releases/latest > > 装完再回来重试这个请求。 @@ -165,5 +165,5 @@ skill for the full table.) - Manifest schema source: `packages/cli/internal/workspace/manifest.go` - Workspace scaffold inventory: `packages/cli/internal/scaffold/scaffold.go` - Template registry: `packages/templates/registry.json` -- Error code reference: +- Error code reference: - Agent Skills format spec: diff --git a/packages/templates/astro-site/src/components/Welcome.astro b/packages/templates/astro-site/src/components/Welcome.astro index 0640fd2..47adcf5 100644 --- a/packages/templates/astro-site/src/components/Welcome.astro +++ b/packages/templates/astro-site/src/components/Welcome.astro @@ -52,7 +52,7 @@
(
- + (
Date: Sun, 17 May 2026 21:25:06 +0800 Subject: [PATCH 2/7] ci: use GitHub-hosted runners --- .github/workflows/ci.yml.disabled | 12 ++++++------ .github/workflows/cli.yml | 2 +- .github/workflows/docs.yml | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml.disabled b/.github/workflows/ci.yml.disabled index 22815ea..49af486 100644 --- a/.github/workflows/ci.yml.disabled +++ b/.github/workflows/ci.yml.disabled @@ -12,9 +12,9 @@ # Both jobs need Node + pnpm because sync-web runs `pnpm install` + # `vite build` against apps/dashboard/. # -# Runners (self-hosted): -# - thunder: [self-hosted, Linux, X64] -# - nano: [self-hosted, macOS, ARM64] +# Runners: +# - ubuntu-latest for Linux checks +# - macos-latest for macOS checks # # Windows is deferred until testdata/bin/ has .bat siblings of the POSIX # shell stubs (Phase 3 in the test plan). @@ -31,7 +31,7 @@ permissions: jobs: lint: - runs-on: [self-hosted, Linux, X64] + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -83,9 +83,9 @@ jobs: matrix: include: - name: linux - runs-on: [self-hosted, Linux, X64] + runs-on: ubuntu-latest - name: macos - runs-on: [self-hosted, macOS, ARM64] + runs-on: macos-latest runs-on: ${{ matrix.runs-on }} steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index e42c95d..4b6cf04 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -25,7 +25,7 @@ permissions: jobs: release: - runs-on: [self-hosted, Linux, X64] + runs-on: ubuntu-latest steps: - name: Check out uses: actions/checkout@v4 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 20593ae..a38223f 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -24,7 +24,7 @@ permissions: jobs: build: - runs-on: [self-hosted, Linux, X64] + runs-on: ubuntu-latest steps: - name: Check out uses: actions/checkout@v4 From 7a18a272cbd7192e17707bbe3c378fe485516be0 Mon Sep 17 00:00:00 2001 From: caorushizi <84996057@qq.com> Date: Sun, 17 May 2026 21:26:00 +0800 Subject: [PATCH 3/7] ci: enable GitHub Actions workflow --- .github/workflows/{ci.yml.disabled => ci.yml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/workflows/{ci.yml.disabled => ci.yml} (100%) diff --git a/.github/workflows/ci.yml.disabled b/.github/workflows/ci.yml similarity index 100% rename from .github/workflows/ci.yml.disabled rename to .github/workflows/ci.yml From e73a4d0edba102c5576efaed76466a1ed9fff4d2 Mon Sep 17 00:00:00 2001 From: caorushizi <84996057@qq.com> Date: Sun, 17 May 2026 21:33:22 +0800 Subject: [PATCH 4/7] release: create draft GitHub releases --- .goreleaser.yaml | 2 +- CONTRIBUTING.md | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.goreleaser.yaml b/.goreleaser.yaml index 9617667..b8bfad4 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -77,7 +77,7 @@ release: github: owner: 1cli-team name: one-cli - draft: false + draft: true prerelease: auto header: | # one-cli {{ .Tag }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e806bae..7da847d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -122,7 +122,8 @@ git commit -m "chore(release): v0.4.3" git push origin master git tag v0.4.3 git push origin v0.4.3 -# → cli workflow 触发,自动 cross-compile + 上传 GitHub Release assets +# → cli workflow 触发,自动 cross-compile + 上传 GitHub Release draft assets +# → 检查 assets / checksums / release notes 后,在 GitHub 手动 Publish ``` 发布 channel: From fffd575d6be3db1aa5cb0abb3de3ed5eb915a963 Mon Sep 17 00:00:00 2001 From: caorushizi <84996057@qq.com> Date: Sun, 17 May 2026 21:48:21 +0800 Subject: [PATCH 5/7] ci: speed up GitHub-hosted checks --- .github/workflows/ci.yml | 65 ++++++++++++++++++++++++++++++++++----- .github/workflows/cli.yml | 3 ++ 2 files changed, 61 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 49af486..abbd666 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,16 +5,16 @@ # tree (registry/skills/_templates/_web) is gitignored and regenerated # via `task sync-bundled` + `task sync-web`, both of which run as deps # of `task vet` — so vet implicitly bootstraps the bundle here. -# - test: matrix on linux + macos, builds bin/one then runs `task test` +# - test: Linux PR gate, builds bin/one then runs `task test` # (go test -race ./...). Build is required because internal/cli/snapshot_e2e_test.go -# skips when bin/one is missing. +# skips when bin/one is missing. macOS runs on master/manual triggers only. # # Both jobs need Node + pnpm because sync-web runs `pnpm install` + # `vite build` against apps/dashboard/. # # Runners: -# - ubuntu-latest for Linux checks -# - macos-latest for macOS checks +# - ubuntu-latest for PR checks +# - macos-latest for master/manual compatibility checks # # Windows is deferred until testdata/bin/ has .bat siblings of the POSIX # shell stubs (Phase 3 in the test plan). @@ -25,10 +25,16 @@ on: pull_request: push: branches: [master] + workflow_dispatch: permissions: contents: read +env: + # GitHub-hosted runners are outside China; the default Taskfile proxy + # (goproxy.cn) is slower/flakier there and has caused CI download failures. + GOPROXY: https://proxy.golang.org,direct + jobs: lint: runs-on: ubuntu-latest @@ -58,6 +64,10 @@ jobs: - name: Install task run: go install github.com/go-task/task/v3/cmd/task@latest + - name: Download Go modules + working-directory: packages/cli + run: go mod download + - name: Verify documentation in sync run: task verify-docs @@ -77,15 +87,12 @@ jobs: fi test: - needs: lint strategy: fail-fast: false matrix: include: - name: linux runs-on: ubuntu-latest - - name: macos - runs-on: macos-latest runs-on: ${{ matrix.runs-on }} steps: - uses: actions/checkout@v4 @@ -112,6 +119,50 @@ jobs: - name: Install task run: go install github.com/go-task/task/v3/cmd/task@latest + - name: Download Go modules + working-directory: packages/cli + run: go mod download + + - name: Build binary + run: task build + + - name: Run tests + run: task test + + test-macos: + # macOS runners are much slower to start and are scarce on PRs. Keep the + # cross-platform signal for master/manual runs without making every PR wait. + if: github.event_name != 'pull_request' + runs-on: macos-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: packages/cli/go.mod + cache: true + cache-dependency-path: packages/cli/go.sum + + - name: Set up pnpm + uses: pnpm/action-setup@v4 + with: + run_install: false + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + cache-dependency-path: apps/dashboard/pnpm-lock.yaml + + - name: Install task + run: go install github.com/go-task/task/v3/cmd/task@latest + + - name: Download Go modules + working-directory: packages/cli + run: go mod download + - name: Build binary run: task build diff --git a/.github/workflows/cli.yml b/.github/workflows/cli.yml index 4b6cf04..91b7dd8 100644 --- a/.github/workflows/cli.yml +++ b/.github/workflows/cli.yml @@ -23,6 +23,9 @@ permissions: # goreleaser needs write access to upload release artifacts. contents: write +env: + GOPROXY: https://proxy.golang.org,direct + jobs: release: runs-on: ubuntu-latest From ac698b56d0de70cd633bf110cca9c8a0442d4a89 Mon Sep 17 00:00:00 2001 From: caorushizi <84996057@qq.com> Date: Sun, 17 May 2026 21:53:53 +0800 Subject: [PATCH 6/7] ci: keep PR checks fast --- .github/workflows/ci.yml | 67 ++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index abbd666..40778c5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,13 +1,14 @@ -# PR-time test gate. Mirrors `task pre-push` so green CI ≡ green local run. +# PR-time test gate. Keeps the merge path fast while preserving slower +# compatibility checks on master/manual runs. # # Two jobs: # - lint: documentation drift, go vet, gofmt cleanliness. The whole bundled # tree (registry/skills/_templates/_web) is gitignored and regenerated # via `task sync-bundled` + `task sync-web`, both of which run as deps # of `task vet` — so vet implicitly bootstraps the bundle here. -# - test: Linux PR gate, builds bin/one then runs `task test` -# (go test -race ./...). Build is required because internal/cli/snapshot_e2e_test.go -# skips when bin/one is missing. macOS runs on master/manual triggers only. +# - test: Linux PR gate, builds bin/one then runs `go test ./...`. +# Build is required because internal/cli/snapshot_e2e_test.go skips when +# bin/one is missing. Race + macOS checks run on master/manual triggers only. # # Both jobs need Node + pnpm because sync-web runs `pnpm install` + # `vite build` against apps/dashboard/. @@ -27,6 +28,10 @@ on: branches: [master] workflow_dispatch: +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + permissions: contents: read @@ -87,13 +92,48 @@ jobs: fi test: - strategy: - fail-fast: false - matrix: - include: - - name: linux - runs-on: ubuntu-latest - runs-on: ${{ matrix.runs-on }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: packages/cli/go.mod + cache: true + cache-dependency-path: packages/cli/go.sum + + - name: Set up pnpm + uses: pnpm/action-setup@v4 + with: + run_install: false + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: 20 + cache: pnpm + cache-dependency-path: apps/dashboard/pnpm-lock.yaml + + - name: Install task + run: go install github.com/go-task/task/v3/cmd/task@latest + + - name: Download Go modules + working-directory: packages/cli + run: go mod download + + - name: Build binary + run: task build + + - name: Run tests + working-directory: packages/cli + run: go test ./... + + test-race: + # Race tests are useful but slow on GitHub-hosted runners. Keep them off + # the PR critical path and run them before/after merging to master. + if: github.event_name != 'pull_request' + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 @@ -130,7 +170,7 @@ jobs: run: task test test-macos: - # macOS runners are much slower to start and are scarce on PRs. Keep the + # macOS runners are slower to start and are scarce on PRs. Keep the # cross-platform signal for master/manual runs without making every PR wait. if: github.event_name != 'pull_request' runs-on: macos-latest @@ -167,4 +207,5 @@ jobs: run: task build - name: Run tests - run: task test + working-directory: packages/cli + run: go test ./... From 4475dfae1ee03295d91d6b6f1fe210bd6cb43c96 Mon Sep 17 00:00:00 2001 From: caorushizi <84996057@qq.com> Date: Sun, 17 May 2026 21:58:19 +0800 Subject: [PATCH 7/7] test: stabilize CLI e2e on clean runners --- packages/cli/internal/cli/e2e_helpers_test.go | 21 ++++++++++++++++++- packages/cli/internal/cmd/addcmd/cmd.go | 9 +++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/packages/cli/internal/cli/e2e_helpers_test.go b/packages/cli/internal/cli/e2e_helpers_test.go index b1457e7..675a63f 100644 --- a/packages/cli/internal/cli/e2e_helpers_test.go +++ b/packages/cli/internal/cli/e2e_helpers_test.go @@ -64,10 +64,12 @@ func runBinary(t *testing.T, args ...string) (stdout, stderr string, exitCode in // Inherits the test process env, so t.Setenv("HOME", ...) propagates. func runBinaryIn(t *testing.T, dir string, args ...string) (stdout, stderr string, exitCode int) { t.Helper() - cmd := exec.Command(binaryPath(t), args...) + bin := binaryPath(t) + cmd := exec.Command(bin, args...) if dir != "" { cmd.Dir = dir } + cmd.Env = prependPath(os.Environ(), filepath.Dir(bin)) var out, errBuf bytes.Buffer cmd.Stdout = &out cmd.Stderr = &errBuf @@ -80,6 +82,23 @@ func runBinaryIn(t *testing.T, dir string, args ...string) (stdout, stderr strin return out.String(), errBuf.String(), exitCode } +func prependPath(env []string, dir string) []string { + out := append([]string{}, env...) + prefix := "PATH=" + for i, kv := range out { + if strings.HasPrefix(kv, prefix) { + path := strings.TrimPrefix(kv, prefix) + if path == "" { + out[i] = prefix + dir + } else { + out[i] = prefix + dir + string(os.PathListSeparator) + path + } + return out + } + } + return append(out, prefix+dir) +} + // loadFixture reads a JSON fixture from testdata/reference/ and // decodes it into a map for structural comparison. func loadFixture(t *testing.T, name string) map[string]any { diff --git a/packages/cli/internal/cmd/addcmd/cmd.go b/packages/cli/internal/cmd/addcmd/cmd.go index aa589fa..6a4cbe3 100644 --- a/packages/cli/internal/cmd/addcmd/cmd.go +++ b/packages/cli/internal/cmd/addcmd/cmd.go @@ -157,10 +157,13 @@ func runAdd(cmd *cobra.Command, positional string, flags *addFlags) error { // engine `one create --preset` orchestrates over multiple projects). // addcmd remains a thin shell: validate flags, prompt where the // command-specific UX is, then hand off. + // Plain `one add` follows the template registry default. Presets pass an + // empty container to opt into the preset-level default instead. result, err := preset.ApplyProject(cmd.Context(), projectRoot, preset.ProjectInput{ - Template: entry, - Name: name, - Deploy: flags.deploy, + Template: entry, + Name: name, + Deploy: flags.deploy, + Container: entry.Defaults["container"], }, interactive) if err != nil { return err