nil-cli 详细开发排期任务
目标版本:v1.0.0
发布日期:2025年11月30日
技术栈:TypeScript + Bun + Yargs + Node.js 兼容层
总体开发节奏
| 阶段 | 时间范围 | 目标 |
|---|---|---|
| Phase 1: 核心架构搭建 | 2025-11-04 ~ 2025-11-08 | CLI 框架、命令系统、配置加载器就绪 |
| Phase 2: 基础功能实现 | 2025-11-11 ~ 2025-11-15 | init 和 deploy 主流程打通,支持本地构建 |
| Phase 3: 部署模块开发 | 2025-11-18 ~ 2025-11-22 | 实现 COS / Docker / SSH 三大部署方式 |
| Phase 4: 安全与测试 | 2025-11-25 ~ 2025-11-27 | 密钥管理、错误处理、单元/集成测试 |
| Phase 5: 文档与发布 | 2025-11-28 ~ 2025-11-30 | 用户文档、README、初版发布 |
Phase 1: 核心架构搭建(2025-11-04 ~ 2025-11-08)
目标
- CLI 可执行入口可用
- 支持
nil --help - 能注册并运行空命令
- 配置文件加载机制验证通过
任务列表
| 任务 | 描述 | 负责人 | 状态 | 截止 |
|---|---|---|---|---|
| [P1-T1] 初始化项目结构 | 创建仓库,初始化 package.json,设置 bun run build, dev, test 脚本 | @Nil | 🟢 已完成 | 2025-11-04 |
[P1-T2] 实现 CLI 入口 (bin/nil) | 编写 shebang 入口,集成 yargs,支持 hideBin | @Nil | 🟢 已完成 | 2025-11-05 |
[P1-T3] 设计全局类型 types/index.ts | 定义 YargsCommand 接口,统一命令格式 | @Nil | 🟢 已完成 | 2025-11-05 |
[P1-T4] 实现命令注册器 registerCommands.ts | 动态注册所有命令,支持 builder/handler | @Nil | 🟢 已完成 | 2025-11-06 |
[P1-T5] 创建 commands/init.ts 存根 | 输出“初始化”提示,暂不创建文件 | @Nil | 🟢 已完成 | 2025-11-06 |
[P1-T6] 创建 commands/deploy.ts 存根 | 输出“准备部署”信息 | @Nil | 🟢 已完成 | 2025-11-06 |
[P1-T7] 实现 loadConfig.ts 基础版本 | 支持 .ts, .js, .json 加载,抛出未找到异常 | @Nil | 🟢 已完成 | 2025-11-07 |
| [P1-T8] 添加 TypeScript 配置 | tsconfig.json 设置路径别名、输出目录等 | @Nil | 🟢 已完成 | 2025-11-07 |
| [P1-T9] 构建脚本自动化 | 使用 bun build 打包为 /dist,支持 bun run build | @Nil | 🟢 已完成 | 2025-11-08 |
| [P1-T10] Phase 1 内部评审 | 演示 nil --help, nil init, nil deploy 基本能跑通 | @Nil | 🟢 已完成 | 2025-11-08 |
Phase 2: 基础功能实现(2025-11-11 ~ 2025-11-15)
目标
nil init能创建基本项目骨架nil deploy能读取配置、执行 git pull 和 build- 支持
buildCommand自定义构建指令 - 部署流程主干打通(仅打印日志)
任务列表
| 任务 | 描述 | 负责人 | 状态 | 截止 |
|---|---|---|---|---|
[P2-T1] 实现 init 命令完整逻辑 | 创建目录、写入 package.json、README.md、.gitignore | @Nil | 🟢 已完成 | 2025-11-12 |
| [P2-T2] 添加模板系统(可复用) | 抽象 createFile(template, target) 工具函数 | @Nil | 🟢 已完成 | 2025-11-12 |
[P2-T3] 实现 gitPull 任务 | 使用 simple-git 拉取指定分支代码 | @Nil | 🟢 已完成 | 2025-11-13 |
| [P2-T4] 实现本地构建任务 | 使用 execa 执行 buildCommand,继承 stdio | @Nil | 🟢 已完成 | 2025-11-13 |
[P2-T5] 实现 runDeploy 主流程框架 | 按顺序调用 gitPull → build → switch(deploy.type) | @Nil | 🟢 已完成 | 2025-11-14 |
| [P2-T6] 验证多配置格式兼容性 | 测试 .ts, .js, .json 是否都能正确加载 | @Nil | 🔵 待开始 | 2025-11-14 |
[P2-T7] 添加 --cwd 参数支持 | 所有命令支持自定义工作目录,默认当前路径 | @Nil | 🟢 已完成 | 2025-11-15 |
| [P2-T8] Phase 2 内部评审 | 演示 nil init my-app && cd my-app && nil deploy 流程走通(无上传) | @Nil | 🟢 已完成 | 2025-11-15 |
Phase 3: 部署模块开发(2025-11-18 ~ 2025-11-22)
目标
- 支持三种部署方式:COS / Docker / SSH
- 每种方式具备完整上传能力
- 提供清晰的进度反馈和成功提示
任务列表
| 任务 | 描述 | 负责人 | 状态 | 截止 |
|---|---|---|---|---|
[P3-T1] 实现 deployToCos | 使用 cos-nodejs-sdk-v5 上传文件夹到腾讯云 COS | @Nil | 🟢 已完成 | 2025-11-19 |
[P3-T2] 支持 prefix 路径前缀 | 上传时自动添加路径前缀(如 v1/) | @Nil | 🔵 待开始 | 2025-11-19 |
[P3-T3] 实现 buildAndPushDocker | 构建镜像并推送到远程 registry(使用 dockerode 或 CLI wrapper) | @Nil | 🔵 待开始 | 2025-11-20 |
[P3-T4] 生成默认 Dockerfile(可选) | 若项目无 Dockerfile,自动创建一个适用于静态站点的 | @Nil | 🔵 待开始 | 2025-11-20 |
[P3-T5] 实现 deployToSSH | 使用 node-ssh 将 dist 文件夹上传到远程服务器 | @Nil | 🟢 已完成 | 2025-11-21 |
| [P3-T6] 支持 SSH 密钥认证与密码登录 | 从环境变量读取 SSH_PRIVATE_KEY 或 SSH_PASSWORD | @Nil | 🟢 已完成 | 2025-11-21 |
| [P3-T7] 统一部署任务接口 | 抽象 DeployTaskContext 类型,便于未来扩展 OSS/S3 | @Nil | 🔵 待开始 | 2025-11-22 |
| [P3-T8] Phase 3 内部评审 | 演示三种部署方式均能成功完成上传 | @Nil | 🔵 待开始 | 2025-11-22 |
Phase 4: 安全与测试(2025-11-25 ~ 2025-11-27)
目标
- 所有机密通过环境变量注入
- 错误信息友好且安全(不暴露密钥)
- 单元测试覆盖核心模块 ≥70%
- 集成测试验证全流程
任务列表
| 任务 | 描述 | 负责人 | 状态 | 截止 |
|---|---|---|---|---|
| [P4-T1] 审查所有密钥使用点 | 确保 secretId, secretKey, SSH_* 来自 process.env | @Nil | 🔵 待开始 | 2025-11-25 |
[P4-T2] 添加 .env 示例文件 | 提供 .env.example 并更新文档说明 | @Nil | 🔵 待开始 | 2025-11-25 |
| [P4-T3] 异常处理增强 | 捕获常见错误(网络失败、权限不足),输出用户友好提示 | @Nil | 🔵 待开始 | 2025-11-26 |
| [P4-T4] 编写单元测试(Jest/Bun Test) | 覆盖 loadConfig, gitPull, registerCommands 等纯函数逻辑 | @Nil | 🔵 待开始 | 2025-11-26 |
| [P4-T5] 编写集成测试 | 模拟真实项目目录,运行 nil deploy 观察行为 | @Nil | 🔵 待开始 | 2025-11-27 |
| [P4-T6] 日志美化 | 使用 chalk 或 picocolors 添加颜色和图标(🚀 ✅ ❌) | @Nil | 🔵 待开始 | 2025-11-27 |
| [P4-T7] Phase 4 内部评审 | 演示测试覆盖率报告、错误恢复场景、日志可读性 | @Nil | 🔵 待开始 | 2025-11-27 |
Phase 5: 文档与发布(2025-11-28 ~ 2025-11-30)
目标
- 发布首个稳定版本
v1.0.0 - GitHub README 完整可用
- 支持
bun add nil-cli安装使用
任务列表
| 任务 | 描述 | 负责人 | 状态 | 截止 |
|---|---|---|---|---|
[P5-T1] 编写 README.md | 包含安装、配置、命令、示例、贡献指南 | @Nil | 🔵 待开始 | 2025-11-28 |
| [P5-T2] 更新 GitHub Wiki(可选) | 拆解高级用法、插件机制设计草图 | @Nil | 🔵 待开始 | 2025-11-28 |
| [P5-T3] 准备 NPM 发布包 | 设置 package.json 的 bin, files, exports 字段 | @Nil | 🔵 待开始 | 2025-11-29 |
| [P5-T4] 执行预发布测试 | 在干净环境中测试 bunx nil init && nil deploy | @Nil | 🔵 待开始 | 2025-11-29 |
[P5-T5] 发布 v1.0.0 到 npm | 使用 bun npm publish | @Nil | 🔵 待开始 | 2025-11-30 |
| [P5-T6] 发布公告 | 在 Discord / Twitter / 内部群组通知上线 | @Nil | 🔵 待开始 | 2025-11-30 |
| [P5-T7] 收集团队反馈 | 收集第一轮使用体验,记录 v1.1 待优化项 | @Nil | 🔵 待开始 | 2025-11-30 |
后续迭代路线图(v1.1+)
| 版本 | 计划内容 |
|---|---|
v1.1 | 支持 --target docker 覆盖配置;多环境配置(prod/staging) |
v1.2 | 插件系统原型:nil-plugin-ali-oss |
v1.3 | 部署状态检查(COS 可写?Docker 登录?) |
v2.0 | Web UI 面板(可视化部署历史、触发按钮) |
附录:关键依赖清单(package.json snippet)
json
{
"dependencies": {
"yargs": "^17.7.2",
"cos-nodejs-sdk-v5": "^2.13.0",
"dockerode": "^3.3.6",
"node-ssh": "^13.0.2",
"simple-git": "^3.19.1",
"execa": "^8.0.1",
"chalk": "^4.1.2",
"dotenv": "^16.4.5"
},
"devDependencies": {
"@types/node": "^20",
"typescript": "^5.6",
"jest": "^29.7",
"@types/yargs": "^17.0.32"
},
"engines": {
"bun": ">=1.1.0"
}
}附录:系统架构
text
nil-cli/
├── bin/
│ └── nil # 可执行文件
├── src/
│ ├── types/
│ │ └── index.ts # 全局类型
│ ├── utils/
│ │ ├── registerCommands.ts # 命令注册器
│ │ └── loadConfig.ts # 配置加载器
│ ├── commands/
│ │ ├── init.ts # 初始化项目
│ │ └── deploy.ts # 部署命令
│ ├── ssh/ # SSH 封装
│ └── deploy/
│ ├── tasks/
│ │ ├── git.ts
│ │ ├── build.ts
│ │ ├── cos.ts
│ │ ├── docker.ts
│ │ └── ssh.ts
│ └── index.ts # 部署主流程
└── docs/ # 文档附录:关键代码片段
命令注册机制
src/utils/registerCommands.ts
ts
import type { Argv } from 'yargs';
import type { YargsCommand } from '../types';
import { commands } from '../commands';
export const registerCommands = (yargs: Argv) => {
commands.forEach((cmd: YargsCommand) => {
yargs.command(cmd.command, cmd.describe, cmd.builder, cmd.handler);
});
return yargs;
};src/types/index.ts
ts
import type { Argv } from 'yargs';
export type YargsCommand = {
command: string;
describe: string;
builder?: (yargs: Argv) => Argv;
handler: (argv: any) => Promise<void> | void;
};src/commands/index.ts
ts
import init from './init';
import deploy from './deploy';
export const commands = [init, deploy] as const;命令实现
src/commands/init.ts
ts
import type { YargsCommand } from '../types';
const init: YargsCommand = {
command: 'init',
describe: '初始化一个新项目',
builder: (yargs) => yargs.option('name', { type: 'string', default: 'my-nil-project' }),
handler: async (argv) => {
console.log(`🚀 正在初始化项目: ${argv.name}`);
// 实际创建文件逻辑...
console.log('✅ 项目初始化完成!');
},
};
export default init;src/commands/deploy.ts
ts
import type { YargsCommand } from '../types';
import { runDeploy } from '../deploy/index';
const deploy: YargsCommand = {
command: 'deploy',
describe: '部署当前项目',
builder: (yargs) =>
yargs.option('cwd', { type: 'string', default: '.', describe: '项目根目录' }),
handler: async (argv) => {
await runDeploy(argv.cwd);
},
};
export default deploy;部署系统(完整集成)
配置系统
支持格式
nil.config.tsnil.config.jsnil.config.json
配置结构
ts
interface NilConfig {
deploy: {
type: 'cos' | 'docker' | 'ssh' | 'oss' | 's3';
cos?: { bucket: string; region: string; prefix?: string };
docker?: { registry: string; imageName: string; tag?: string };
ssh?: { host: string; port?: number; username: string };
remoteAppPath: string;
localDist: string;
};
buildCommand?: string;
gitBranch?: string;
}加载器
ts
// src/utils/loadConfig.ts
export async function loadConfig(cwd: string): Promise<NilConfig> {
for (const file of ['nil.config.ts', 'nil.config.js', 'nil.config.json']) {
const path = join(cwd, file);
if (existsSync(path)) {
const mod = await import(`file://${resolve(path)}`);
return (mod.default || mod) as NilConfig;
}
}
throw new Error('配置文件未找到');
}部署主流程
src/deploy/index.ts
ts
import { loadConfig } from '../utils/loadConfig';
import { NilConfig } from '../types';
import { gitPull } from './tasks/git';
import { execa } from 'execa';
import { deployToCos } from './tasks/cos';
import { buildAndPushDocker } from './tasks/docker';
export async function runDeploy(cwd: string) {
const config = await loadConfig(cwd);
// 拉取代码
await gitPull(cwd, config.gitBranch ?? 'master');
// 构建
const buildCmd = config.buildCommand ?? 'bun run docs:build';
await execa(buildCmd, { stdio: 'inherit', cwd });
// 分发
switch (config.deploy.type) {
case 'cos':
await deployToCos({
localDist: resolve(cwd, config.deploy.localDist),
cosConfig: {
...config.deploy.cos!,
secretId: process.env.TENCENT_CLOUD_SECRET_ID!,
secretKey: process.env.TENCENT_CLOUD_SECRET_KEY!,
},
});
break;
case 'docker':
await buildAndPushDocker({
localDist: resolve(cwd, config.deploy.localDist),
dockerConfig: config.deploy.docker!,
});
break;
case 'ssh':
// 实现 SSH 上传
break;
default:
throw new Error(`不支持的部署类型: ${config.deploy.type}`);
}
console.log('🎉 部署成功!');
}技术栈与依赖
| 类别 | 技术 | 理由 |
|---|---|---|
| CLI 框架 | yargs | 成熟、类型安全、自动 help |
| 运行时 | Bun | 快速启动、TS 原生支持 |
| SSH | node-ssh + ssh2 | 高级 API,兼容 Bun(fallback) |
| 配置加载 | import() | Bun 支持 .ts 动态导入 |
| 子进程 | execa | 跨平台、Promise 风格 |
| Git | simple-git | 轻量、易用 |
| COS | cos-nodejs-sdk-v5 | 腾讯云官方 SDK |
| Docker | dockerode | 功能完整 |