Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,5 @@ bin-go/
.seo/blog-drafts/
.seo/skills/
.seo/patches/
# Fixed mise release archives fetched by task sync-mise, embedded per target.
/packages/cli/internal/adapters/runtime/mise/assets/
5 changes: 5 additions & 0 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ version: 2

project_name: one-cli

before:
hooks:
- go run ./packages/cli/tools/sync-mise --all

builds:
- id: one
dir: packages/cli
Expand Down Expand Up @@ -53,6 +57,7 @@ archives:
name_template: "one-cli_{{ .Os }}_{{ .Arch }}"
files:
- README*
- third_party/mise/LICENSE

checksum:
name_template: "checksums.txt"
Expand Down
15 changes: 14 additions & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ one --version # 验证装好

> **fresh-clone 提示**:`packages/cli/internal/resources/bundled/` 整个目录是 gitignore 的——
> registry / templates / dashboard dist 都由 `task sync-bundled` +
> `task sync-web` 按需重建,作为 `task vet` / `test` / `build` 的依赖自动跑。
> `task sync-web` 按需重建。`sync-bundled` 还会运行 `sync-mise`,下载并校验
> 当前平台的固定 mise 压缩包用于内置,作为 `task vet` / `test` / `build` 的依赖自动跑。
> 第一次 `task install` 会触发 `pnpm install + vite build`,~30s;之后
> task fingerprint 命中,几乎零成本。如果你直接跑 `go build` 而不走 Taskfile,
> 会看到 `pattern all:_templates: no matching files found` 这种报错——跑一次
Expand Down Expand Up @@ -68,6 +69,18 @@ PR CI 会并行执行 `task check:static` 与 `task check:test`,两者合起
- 公开 API(`packages/cli/pkg/`)改动要考虑 semver;详见 [CLAUDE.md 的 Public API stability](./CLAUDE.md)
- 加新错误码:在 `packages/cli/internal/platform/errors/codes.go` 注册 `Code` 常量 + `Codes` map 条目;测试会强制对应;改完跑 `task gen-error-codes` 刷新文档

### 内置 mise

发布的 One 文件内置对应平台的 mise 压缩包,首次运行从自身解压,不下载 mise。
`task sync-mise` 在构建时下载并校验本机平台资源;`task sync-mise-all` 准备五个平台。
`task build`、检查任务自动准备本机资源,`task build-all` 和 GoReleaser 自动准备全部平台。
资源位于被忽略的 `packages/cli/internal/adapters/runtime/mise/assets/`,不提交二进制资源。
资源已准备且摘要匹配时可离线构建。首次构建需要访问 GitHub Releases。

升级时更新 `internal/adapters/runtime/mise/miserelease/release.go` 中的版本、压缩包和解压后程序的 SHA256,
以及 runtime 最低版本和相关文档;重新执行 `task sync-mise-all`。上游许可证保留于
`third_party/mise/LICENSE`,也包含在内置的原始压缩包和 One 发布归档中。

### 改 templates(`packages/templates/<id>/`)

- 模板会被 `go:embed` 进二进制(`task sync-bundled` 是同步入口,自动跑)
Expand Down
49 changes: 33 additions & 16 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ env:
GOPROXY: '{{.GOPROXY}}'

tasks:
# Keep cached tasks at the repository root so sources/generates resolve
# against the same paths. Use go -C when a command needs the CLI directory.
default:
desc: List available tasks
cmds:
Expand All @@ -39,30 +41,35 @@ tasks:
build:
desc: Build the local binary into packages/cli/bin/one
deps: [sync-bundled, sync-web]
dir: '{{.CLI_DIR}}'
status:
- test -f 'bin/one{{.GOEXE}}'
- test "$(bin/one{{.GOEXE}} --version)" = "{{.BUILD_VERSION}}"
- test -f '{{.BIN}}'
- test "$({{.BIN}} --version)" = "{{.BUILD_VERSION}}"
cmds:
- mkdir -p bin
- go build -trimpath -ldflags '{{.LDFLAGS}}' -o 'bin/one{{.GOEXE}}' ./cmd/one
- mkdir -p '{{.BIN_DIR}}'
- go -C '{{.CLI_DIR}}' build -trimpath -ldflags '{{.LDFLAGS}}' -o 'bin/one{{.GOEXE}}' ./cmd/one
sources:
- 'Taskfile.yml'
- 'go.work'
- 'go.work.sum'
- 'packages/kernel/go.mod'
- 'packages/kernel/**/*.go'
- 'packages/cli/cmd/**/*.go'
- 'packages/cli/internal/**/*.go'
- 'packages/cli/internal/adapters/runtime/mise/assets/*.tar.gz'
- 'packages/cli/internal/adapters/runtime/mise/assets/*.zip'
- 'packages/cli/internal/adapters/deploy/kustomize/templates/*'
- 'packages/cli/internal/platform/i18n/locales/*.json'
- 'packages/cli/internal/resources/bundled/**/*'
- 'packages/cli/pkg/**/*.go'
- 'packages/cli/go.mod'
- 'packages/cli/go.sum'
generates:
- '{{.BIN}}'

gen-error-codes:
desc: Render apps/docs/content/docs/zh/error-codes.md from internal/platform/errors/codes.go
dir: '{{.CLI_DIR}}'
cmds:
- go run ./tools/gen-error-codes
- go -C '{{.CLI_DIR}}' run ./tools/gen-error-codes
sources:
- 'packages/cli/internal/platform/errors/codes.go'
- 'packages/cli/tools/gen-error-codes/**/*.go'
Expand All @@ -76,9 +83,8 @@ tasks:
# registry/_templates; sync-web covers _web. Both run before
# `go run` here so a fresh checkout works without prior task invocations.
deps: [sync-bundled, sync-web]
dir: '{{.CLI_DIR}}'
cmds:
- go run ./tools/verify-cli-references
- go -C '{{.CLI_DIR}}' run ./tools/verify-cli-references
sources:
- 'packages/cli/internal/**/*.go'
- 'packages/cli/tools/verify-cli-references/**/*.go'
Expand All @@ -94,9 +100,8 @@ tasks:
# The test package imports internal/core/template → internal/resources/bundled, so it
# needs the embed sources present. Mirrors verify-cli-references.
deps: [sync-bundled, sync-web]
dir: '{{.CLI_DIR}}'
cmds:
- go test -count=1 -run 'TestTemplateCodesMatchGoldenAndRegistry|TestDeployCodesMatchGolden|TestEnvCodesMatchGolden|TestContainerCodesMatchGolden|TestGoldenSortedByCode' ./internal/modules/preset/...
- go -C '{{.CLI_DIR}}' test -count=1 -run 'TestTemplateCodesMatchGoldenAndRegistry|TestDeployCodesMatchGolden|TestEnvCodesMatchGolden|TestContainerCodesMatchGolden|TestGoldenSortedByCode' ./internal/modules/preset/...
sources:
- 'packages/cli/internal/modules/preset/**/*.go'
- 'packages/cli/testdata/preset/v1_codes.json'
Expand All @@ -105,9 +110,8 @@ tasks:
verify-preset-vectors:
desc: Lock the v1 preset id encoding — Encode(spec) and Parse(id) roundtrip every frozen vector
deps: [sync-bundled, sync-web]
dir: '{{.CLI_DIR}}'
cmds:
- go test -count=1 -run 'TestEncodeVectors|TestParseEncodeRoundTrip|TestEncodeOrderIndependent' ./internal/modules/preset/...
- go -C '{{.CLI_DIR}}' test -count=1 -run 'TestEncodeVectors|TestParseEncodeRoundTrip|TestEncodeOrderIndependent' ./internal/modules/preset/...
sources:
- 'packages/cli/internal/modules/preset/**/*.go'
- 'packages/cli/testdata/preset/v1_vectors.json'
Expand All @@ -119,11 +123,11 @@ tasks:
# registry/_templates; sync-web covers _web. Mirrors the deps
# on verify-cli-references and verify-preset-codes.
deps: [sync-bundled, sync-web]
dir: '{{.CLI_DIR}}'
cmds:
- go run ./tools/verify-help
- go -C '{{.CLI_DIR}}' run ./tools/verify-help
sources:
- 'packages/cli/internal/**/*.go'
- 'packages/cli/internal/platform/i18n/locales/*.json'
- 'packages/cli/tools/verify-help/**/*.go'

verify-docs:
Expand Down Expand Up @@ -183,7 +187,7 @@ tasks:

build-all:
desc: Cross-compile every supported platform under go-dist/
deps: [sync-bundled]
deps: [sync-bundled, sync-mise-all, sync-web]
dir: '{{.CLI_DIR}}'
cmds:
- rm -rf ../../go-dist
Expand Down Expand Up @@ -361,7 +365,20 @@ tasks:
generates:
- 'apps/dashboard/dist/index.html'

sync-mise:
desc: Fetch and verify the pinned mise archive embedded for the local platform
run: once
cmds:
- go run ./packages/cli/tools/sync-mise

sync-mise-all:
desc: Fetch and verify mise archives for all release platforms
run: once
cmds:
- go run ./packages/cli/tools/sync-mise --all

sync-bundled:
deps: [sync-mise]
desc: Regenerate registry/_templates under packages/cli/internal/resources/bundled (go:embed sources)
run: once
summary: |
Expand Down
6 changes: 4 additions & 2 deletions apps/docs/content/docs/zh/add.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ title: one add
description: 往工作区里加一个模板化项目。
---

工作区已启用 hk 时,`one add` 会同步更新语言检查:Go 加入格式检查,JS/TS 根据项目工具加入 lint 和格式检查。用户的 `hk.pkl` 保留不变。旧工作区可先通过 `one configure hooks` 启用,详见 [`one hk`](/zh/docs/hk/)。

`one add` 选择技术栈,生成一个可本地开发的项目并登记到 manifest。CI 和部署默认都保持未配置。

有两条入口:
Expand All @@ -28,7 +30,7 @@ one add [template-id] --name <project-name> [--deploy-provider <backend>] [optio
| `--deploy-provider <backend>` | 显式选择 deploy 后端(必须在模板的 compat 列表里) |
| `-o, --output <fmt>` | `json` / `yaml` / `text` |

工作区根用 pnpm;项目自身的工具链由模板决定(Node 模板用 pnpm,Go 模板用 Go toolchain,等等)。
首次添加 JS/TS 项目时初始化 Node monorepo,新工作区默认使用 pnpm;已有 Node 工作区沿用其包管理器。首次添加 Go 模块时初始化根 `go.work`,从第一个模块开始维护 `use` 成员。Go 与 Node 配置可以共存,后续添加只增量登记。已有 `go.work` 的注释、`replace`、`toolchain` 和外部成员会保留;配置冲突会在写入前报告。

## 交互模式

Expand Down Expand Up @@ -127,4 +129,4 @@ one add nestjs-api --name user-api --yes -o json | jq
- Agent 文档和本地开发配置会由 `one add` 同步
- 下一步运行 `one dev <project>`;需要部署时再运行 `one deploy <project>`
- 如需持续集成,单独运行 `one ci enable <project>` 生成 GitHub Actions 工作流
- `one add` 不自动安装依赖:JS / TS 工作区在根目录跑 package manager install;Go 项目进项目目录跑 `go mod download`,修改 imports 或需要修复模块元数据时再跑 `go mod tidy`
- `one add` 只生成项目和工作区配置;`one dev` 会自动准备工具与应用依赖。JS/TS 在根目录统一安装,Go 按当前模块或 `go.work` 构建图准备依赖。修改 imports 或模块声明需要修复时,显式运行 `one run <project> -- go mod tidy`。
3 changes: 3 additions & 0 deletions apps/docs/content/docs/zh/cli-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ description: one 顶层命令、常用子命令、输出模式和 agent 自动
| `one deploy` | 按 project 派发 kustomize / S3-compatible / Vercel / Cloudflare / EdgeOne 部署 | `one deploy --dry-run` |
| `one ci` | 查看或管理可选的持续集成 | `one ci` |
| `one run` | 注入项目 `.env` 后执行任意命令 | `one run -- npm test` |
| `one hk` | 工作区检查、显式修复和 Git hooks | `one hk check --all` |
| `one configure` | 配置机器级 endpoint profile | `one configure` |
| `one serve` | 启动本地 Workspace、Project 与 Profile Dashboard | `one serve` |

Expand Down Expand Up @@ -73,6 +74,8 @@ one env pull [--env <env>] [-p <name|path>] [--force] [--dry-run]

## 本机连接

工作区的检查与提交 hook 使用 `one configure hooks` 配置,详见 [`one hk`](/zh/docs/hk/)。下面的连接命令用于机器级服务配置。

```bash
one configure
one configure add
Expand Down
40 changes: 39 additions & 1 deletion apps/docs/content/docs/zh/configure.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: one configure
description: 管理部署、环境变量和镜像仓库所需的本机连接与偏好设置。
---

`one configure` 管理**本机连接和偏好设置**,不是工作区业务配置。密钥只保存在本机,不写入工作区或 Git。
`one configure` 管理**本机连接和偏好设置**;`one configure mise` 生成工作区工具配置,`one configure hooks` 生成 hk 检查并安装本地 Git 启动器。连接密钥只保存在本机,不写入工作区或 Git。

## 用法

Expand All @@ -18,10 +18,16 @@ one configure use <pair> --profile <name>
one configure remove <pair> --profile <name>
one configure locale [auto|zh-CN|en-US]
one configure open
one configure mise [--dry-run] [--node-version <version>] [--go-version <version>]
one configure hooks [--dry-run]
```

没有连接时,无参 `one configure` 进入建立连接向导;已有连接时显示简洁概览。`show` / `use` / `remove` 在终端可直接选择已有连接;脚本仍显式传 `<pair>` 和 `--profile`。

## hooks 工作区提交检查

新工作区已经配置 hk。克隆后运行 `one configure hooks` 安装当前 checkout 的钩子;旧工作区可先用 `one configure hooks --dry-run -o json` 预览迁移。配置过程不下载工具,保留用户自定义检查;具体规则和迁移限制见 [`one hk`](/zh/docs/hk/)。

## 交互模式

本地人工配置推荐用交互式向导:
Expand Down Expand Up @@ -112,6 +118,37 @@ one configure add container/ghcr --profile ghcr \

三个 JSON 文件都是 mode `0600` 的机器本地文件;`profile-bindings.json` 只含名字。它们都不会修改或升级 `one.manifest.json`。`show` 默认掩码敏感字段,只有 `show --reveal` 会输出明文。

## mise 工作区工具配置

新建 workspace 会自动生成 mise 配置,添加项目时自动更新。日常仍使用原来的命令:

```bash
one create my-app -y
cd my-app
one add react-spa --name web -y
one dev web
one run web -- pnpm build
```

旧 workspace 可一次性生成配置,之后也使用同样的日常命令:

```bash
one configure mise --dry-run -o json
one configure mise
```

预览返回每个文件的 `before` / `after`,不执行 mise、不联网、不读取项目密钥。实际写入仅涉及根目录和各项目的 `.mise/conf.d/one.toml`,这些生成文件可纳入 Git。Manifest schema 保持 v1。

根配置固定 Node 版本(默认 `24.15.0`,再次生成沿用之前的版本),包管理器版本来自根 `package.json#packageManager`;Go 项目使用 `go.mod` 的 `go` / `toolchain` 声明。需要调整时用 `--node-version` / `--go-version` 指定完整版本。Go override 不能低于 `go.mod` 最低要求;自定义 Node engines 的兼容性需自行确认,当前尚未解析完整 npm 版本范围。

One 保留用户的 `mise.toml` 和自定义任务;同目录的 `mise.toml` 可以覆盖生成默认值。手改生成文件会触发 `MISE_CONFIG_CONFLICT`,应将定制内容移入用户配置,再恢复生成文件。已有冲突会在 `one add` 渲染项目之前报告;若后续磁盘写入失败,项目保留,修复错误后运行 `one configure mise` 完成配置。

根据项目已有能力生成 `one:dev`、`one:build`、`one:test`、`one:lint`。这些任务执行时读取当前 Manifest、package scripts 或 Taskfile;额外命令参数继续通过 `one run <project> -- <cmd> [args...]` 传递。按需使用 `one mise` 访问配置信任、诊断和任务命令,无需单独安装 mise。手动运行 mise 任务时,PATH 中的 One 必须支持生成配置的执行协议;也可设置 `ONE_BINARY_PATH` 为测试版 One 的绝对路径。

`ONE_RUNTIME=builtin` 可用于临时诊断,让 `one run` / `one dev` 使用机器现有工具;该模式不提供 mise 环境。移除该变量即可恢复自动选择。没有根生成配置的旧 workspace 默认使用 builtin,不会静默迁移。

此轮仅接入 `run`、`dev` 和创建流程。CI、部署前构建、工具锁文件生成和跨平台工具安装矩阵留待下一阶段;它们目前仍沿用原有实现。工具的精确版本声明不等于完整的跨平台 `mise.lock`。

## 输出 schema

| 命令 | schema |
Expand All @@ -124,6 +161,7 @@ one configure add container/ghcr --profile ghcr \
| `show` | `one-cli/configure-show/v1` |
| `use` | `one-cli/configure-use/v1` |
| `remove` | `one-cli/configure-remove/v1` |
| `mise` | `one-cli/mise-config/v1` |

## 错误恢复

Expand Down
14 changes: 12 additions & 2 deletions apps/docs/content/docs/zh/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ one create my-app --yes --env-provider infisical
|---|---|---|
| 环境变量 | 本地 `.env` 文件 | 可通过 `--env-provider infisical` 或后续 `one env switch infisical` 切换到 Infisical |
| 本地开发 | `one dev` | 通过内置进程管理器运行各项目的开发命令 |
| 工具环境 | mise | 自动生成根 `.mise/conf.d/one.toml`;后续 `one add` 自动生成项目配置 |
| Git 检查 | hk | 创建共享检查配置并安装本地提交钩子;后续 `one add` 增量加入语言检查 |

创建和添加项目只生成配置,不下载工具。首次运行时 One 从自身解压内置 mise,用户无需单独安装或下载 mise;正常命令保持不变。工具版本与已有 workspace 的启用方式见 [`one configure mise`](/zh/docs/configure/#mise-工作区工具配置)。

空工作区先保持语言无关:首次添加 Go 模块时创建根 `go.work` 并登记该模块;首次添加 JS/TS 项目时创建根 `package.json` 和 `pnpm-workspace.yaml`。后续项目增量加入,两套配置可以共存。Git hooks 从创建工作区时就由 hk 提供,纯 Go 工作区不生成 Node 配置;JS 工作区也不再依赖 Husky 或 commitlint。工作区不默认安装版本管理工具或生成 Changesets 配置,发布流程由项目按需配置。

提交前默认只检查暂存内容,使用 `one hk fix` 显式修复。用法与自定义方式见 [`one hk`](/zh/docs/hk/)。Git 未安装或已有 hooks 配置发生冲突时,工作区仍会创建,输出的 `warnings` 会提示后续执行 `one configure hooks`。

持续集成默认不配置。创建工作区不会写入 `.github/workflows/`;添加项目后如有
需要,再显式运行 `one ci enable <project>`。
Expand Down Expand Up @@ -83,13 +91,15 @@ one configure add env/infisical --profile work \
"project_name": "my-app",
"created_path": "/abs/path/my-app",
"created_in_place": false,
"package_manager": "pnpm",
"package_manager": "",
"secrets_backend": "dotenv",
"ci_enabled": false,
"dev_enabled": true
}
```

`package_manager` 在空工作区或纯 Go 工作区中为空字符串;含 Node 项目的 preset 会返回实际包管理器名称。

`secrets_backend` 是 env 域 backend 名(`dotenv` / `infisical`);`ci_enabled`
为兼容 wire format 继续保留,默认是 `false`,`dev_enabled` 是 `true`。部署配置会在首次部署时写入。

Expand Down Expand Up @@ -128,7 +138,7 @@ one create . --yes
one create my-app --yes
cd my-app
one add nestjs-api --name api --yes
pnpm install
one dev api
```

## 错误恢复
Expand Down
Loading
Loading