Skip to content

nil-cli 详细开发排期任务

目标版本:v1.0.0
发布日期:2025年11月30日
技术栈:TypeScript + Bun + Yargs + Node.js 兼容层

总体开发节奏

阶段时间范围目标
Phase 1: 核心架构搭建2025-11-04 ~ 2025-11-08CLI 框架、命令系统、配置加载器就绪
Phase 2: 基础功能实现2025-11-11 ~ 2025-11-15initdeploy 主流程打通,支持本地构建
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.jsonREADME.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_KEYSSH_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] 日志美化使用 chalkpicocolors 添加颜色和图标(🚀 ✅ ❌)@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.jsonbin, 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.0Web 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.ts
  • nil.config.js
  • nil.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 原生支持
SSHnode-ssh + ssh2高级 API,兼容 Bun(fallback)
配置加载import()Bun 支持 .ts 动态导入
子进程execa跨平台、Promise 风格
Gitsimple-git轻量、易用
COScos-nodejs-sdk-v5腾讯云官方 SDK
Dockerdockerode功能完整

要求,尽量用函数式风格变成,拆分代码为纯函数