refactor: 重命名扩展包,统一命名规范

- 将 `@spaceflow/ci-scripts` 重命名为 `@spaceflow/scripts`
- 将 `@spaceflow/ci-shell` 重命名为 `@spaceflow/shell`
- 将 `@spaceflow/period-summary` 重命名为 `@spaceflow/review-summary`
- 更新所有相关配置文件、文档和工作流中的包名引用
- 移除 `ci-` 前缀,简化命名并提高一致性
This commit is contained in:
Lydanne
2026-02-17 00:43:13 +08:00
parent 1e880b1e53
commit 13bfefe94a
58 changed files with 476 additions and 466 deletions

View File

@@ -10,8 +10,8 @@ on:
options:
- publish
- review
- ci-scripts
- ci-shell
- scripts
- shell
args:
description: "Additional arguments for the command"
required: false

View File

@@ -4,14 +4,14 @@ on:
workflow_dispatch:
inputs:
command:
description: "Command to run (publish, review, ci-scripts, ci-shell, claude-config)"
description: "Command to run (publish, review, scripts, shell, claude-config)"
required: true
type: choice
options:
- publish
- review
- ci-scripts
- ci-shell
- scripts
- shell
- claude-config
args:
description: "Additional arguments for the command"

View File

@@ -2,8 +2,8 @@
"name": "spaceflow-local",
"private": true,
"dependencies": {
"@spaceflow/ci-scripts": "link:../extensions/ci-scripts",
"@spaceflow/ci-shell": "link:../extensions/ci-shell",
"@spaceflow/scripts": "link:../extensions/scripts",
"@spaceflow/shell": "link:../extensions/shell",
"@spaceflow/core": "link:../packages/core",
"@spaceflow/publish": "link:../extensions/publish",
"@spaceflow/review": "link:../extensions/review"

View File

@@ -18,8 +18,8 @@
"retryDelay": 1000
},
"dependencies": {
"@spaceflow/ci-shell": "link:./extensions/ci-shell",
"@spaceflow/ci-scripts": "link:./extensions/ci-scripts",
"@spaceflow/shell": "link:./extensions/shell",
"@spaceflow/scripts": "link:./extensions/scripts",
"@spaceflow/review": "link:./extensions/review",
"@spaceflow/publish": "link:./extensions/publish"
},

View File

@@ -24,9 +24,9 @@
"i18n-ally-next.localesPaths": [
"packages/cli/src/locales",
"packages/core/src/locales",
"extensions/ci-scripts/src/locales",
"extensions/ci-shell/src/locales",
"extensions/period-summary/src/locales",
"extensions/scripts/src/locales",
"extensions/shell/src/locales",
"extensions/review-summary/src/locales",
"extensions/publish/src/locales",
"extensions/review/src/locales"
]

View File

@@ -50,9 +50,9 @@ spaceflow/
├── extensions/ # 扩展
│ ├── review/ # AI 代码审查(@spaceflow/review
│ ├── publish/ # 自动化发布(@spaceflow/publish
│ ├── ci-scripts/ # CI 脚本执行(@spaceflow/ci-scripts
│ ├── ci-shell/ # CI Shell 执行(@spaceflow/ci-shell
│ └── period-summary/ # 周期统计(@spaceflow/period-summary
│ ├── scripts/ # 脚本执行(@spaceflow/scripts
│ ├── shell/ # Shell 执行(@spaceflow/shell
│ └── review-summary/ # 审查统计(@spaceflow/review-summary
├── actions/ # GitHub Actions
├── docs/ # 文档站点VitePress
└── templates/ # 扩展模板
@@ -66,9 +66,9 @@ spaceflow/
| `@spaceflow/core` | 核心能力库,提供共享模块和扩展系统基础设施 |
| `@spaceflow/review` | AI 代码审查扩展 |
| `@spaceflow/publish` | 自动化版本发布扩展 |
| `@spaceflow/ci-scripts` | CI 环境下执行 JS 脚本 |
| `@spaceflow/ci-shell` | CI 环境下执行 Shell 命令 |
| `@spaceflow/period-summary` | PR 贡献周期统计 |
| `@spaceflow/scripts` | CI 环境下执行 JS 脚本 |
| `@spaceflow/shell` | CI 环境下执行 Shell 命令 |
| `@spaceflow/review-summary` | PR 贡献审查统计 |
## 内置命令

View File

@@ -4,7 +4,7 @@ author: "spaceflow"
inputs:
command:
description: "The spaceflow command to run (e.g. review, publish, ci-scripts, ci-shell, or get-output for extracting cached values)"
description: "The spaceflow command to run (e.g. review, publish, scripts, shell, or get-output for extracting cached values)"
required: true
args:
description: "Additional arguments to pass to the command"

View File

@@ -72,9 +72,9 @@ export default defineConfig({
items: [
{ text: "review — 代码审查", link: "/guide/commands/review" },
{ text: "publish — 版本发布", link: "/guide/commands/publish" },
{ text: "ci-scripts — 脚本执行", link: "/guide/commands/ci-scripts" },
{ text: "ci-shell — Shell 执行", link: "/guide/commands/ci-shell" },
{ text: "period-summary — 周期总结", link: "/guide/commands/period-summary" },
{ text: "scripts — 脚本执行", link: "/guide/commands/scripts" },
{ text: "shell — Shell 执行", link: "/guide/commands/shell" },
{ text: "review-summary — 审查总结", link: "/guide/commands/review-summary" },
],
},
],

View File

@@ -15,11 +15,11 @@ Spaceflow 提供预配置的 GitHub Actions可以在 CI 中自动执行各种
### 输入参数
| 参数 | 必填 | 说明 |
|------|------|------|
| `github-token` | ✅ | GitHub Token |
| `github-server-url` | ❌ | GitHub Server URL默认自动检测 |
| `command` | ✅ | 要执行的 spaceflow 命令 |
| 参数 | 必填 | 说明 |
| ------------------- | ---- | --------------------------------- |
| `github-token` | ✅ | GitHub Token |
| `github-server-url` | ❌ | GitHub Server URL默认自动检测 |
| `command` | ✅ | 要执行的 spaceflow 命令 |
## 预配置工作流
@@ -155,13 +155,13 @@ jobs:
在 GitHub 仓库的 Settings → Secrets and variables → Actions 中配置:
| Secret | 说明 |
|--------|------|
| `OPENAI_API_KEY` | OpenAI API Keyreview 命令需要) |
| `ANTHROPIC_API_KEY` | Anthropic API Key可选 |
| `NPM_TOKEN` | npm 发布 Tokenpublish 命令需要) |
| `FEISHU_APP_ID` | 飞书 App ID通知需要 |
| `FEISHU_APP_SECRET` | 飞书 App Secret通知需要 |
| Secret | 说明 |
| ------------------- | ---------------------------------- |
| `OPENAI_API_KEY` | OpenAI API Keyreview 命令需要) |
| `ANTHROPIC_API_KEY` | Anthropic API Key可选 |
| `NPM_TOKEN` | npm 发布 Tokenpublish 命令需要) |
| `FEISHU_APP_ID` | 飞书 App ID通知需要 |
| `FEISHU_APP_SECRET` | 飞书 App Secret通知需要 |
::: tip
`GITHUB_TOKEN` 由 GitHub Actions 自动注入,无需手动配置。
@@ -171,9 +171,9 @@ jobs:
根据使用的命令,需要配置不同的权限:
| 命令 | 需要的权限 |
|------|-----------|
| `review` | `contents: read`, `pull-requests: write` |
| `publish` | `contents: write`, `packages: write` |
| `ci-scripts` | `contents: read` |
| `ci-shell` | `contents: read` |
| 命令 | 需要的权限 |
| --------- | ---------------------------------------- |
| `review` | `contents: read`, `pull-requests: write` |
| `publish` | `contents: write`, `packages: write` |
| `scripts` | `contents: read` |
| `shell` | `contents: read` |

View File

@@ -56,7 +56,7 @@ addLocaleResources("hello", {
| -------------- | --------------------- | ------------------------------------------- |
| 公共 key | 默认(`translation` | `common.*`, `config.*`, `extensionLoader.*` |
| 内部 Extension | Extension 名称 | `build:`, `dev:`, `commit:`, `install:` 等 |
| 外部 Extension | Extension 名称 | `review:`, `publish:`, `ci-scripts:` 等 |
| 外部 Extension | Extension 名称 | `review:`, `publish:`, `scripts:` |
## 语言包结构

View File

@@ -335,29 +335,29 @@ class ConfigReader {
#### 旧版NestJS
```typescript
// ci-scripts.module.ts
// scripts.module.ts
import { Module } from "@nestjs/common";
import { ConfigModule } from "@nestjs/config";
import { GitProviderModule, ciConfig } from "@spaceflow/core";
import { CiScriptsCommand } from "./ci-scripts.command";
import { CiScriptsService } from "./ci-scripts.service";
import { ScriptsCommand } from "./scripts.command";
import { ScriptsService } from "./scripts.service";
@Module({
imports: [ConfigModule.forFeature(ciConfig), GitProviderModule.forFeature()],
providers: [CiScriptsCommand, CiScriptsService],
providers: [ScriptsCommand, ScriptsService],
})
export class CiScriptsModule {}
export class ScriptsModule {}
// ci-scripts.command.ts
// scripts.command.ts
import { Command, CommandRunner, Option } from "nest-commander";
@Command({
name: "ci-script",
description: "执行 CI 脚本",
name: "script",
description: "执行脚本",
arguments: "<script>",
})
export class CiScriptsCommand extends CommandRunner {
constructor(private readonly ciScriptsService: CiScriptsService) {
export class ScriptsCommand extends CommandRunner {
constructor(private readonly scriptsService: ScriptsService) {
super();
}
@@ -373,21 +373,21 @@ export class CiScriptsCommand extends CommandRunner {
// index.ts
import type { SpaceflowExtension } from "@spaceflow/core";
import { CiScriptsModule } from "./ci-scripts.module";
import { ScriptsModule } from "./scripts.module";
export class CiScriptsExtension implements SpaceflowExtension {
export class ScriptsExtension implements SpaceflowExtension {
getMetadata() {
return {
name: "@spaceflow/ci-scripts",
commands: ["ci-script"],
name: "@spaceflow/scripts",
commands: ["script"],
configKey: "ci",
};
}
getModule() {
return CiScriptsModule;
return ScriptsModule;
}
}
export default CiScriptsExtension;
export default ScriptsExtension;
```
#### 新版(无 NestJS
@@ -407,15 +407,15 @@ const CiConfigSchema = z.object({
type CiConfig = z.infer<typeof CiConfigSchema>;
export default defineExtension({
name: "@spaceflow/ci-scripts",
name: "@spaceflow/scripts",
version: "0.19.3",
description: "CI 脚本执行插件",
description: "脚本执行插件",
configKey: "ci",
configSchema: () => CiConfigSchema,
commands: [
{
name: "ci-script",
name: "script",
description: t("description"),
arguments: "<script>",
argsDescription: { script: t("argsDescription.script") },
@@ -1200,7 +1200,7 @@ export const mcpCommand: CommandDefinition = {
**目标**:将现有扩展迁移到 `defineExtension` 接口
1. 按复杂度排序ci-scripts → ci-shell → publish → period-summary → review
1. 按复杂度排序ci-scripts → ci-shell → publish → review-summary → period-summary
2. 每个扩展:去除 NestJS 装饰器 → 改用 `defineExtension` → 声明 `services` 工厂 → 各自管理 i18n
3. 每个扩展迁移后单独测试

View File

@@ -4,12 +4,12 @@
## 概览
| 阶段 | 内容 | 预计时间 | 依赖 |
|------|------|----------|------|
| 1 | CLI 内联构建(快速止血) | 1-2 天 | 无 |
| 2 | core 去 NestJS + 定义新接口 | 3-4 天 | 阶段 1 |
| 3 | CLI 去 NestJS | 3-5 天 | 阶段 2 |
| 4 | 迁移扩展 | 2.5-5 天 | 阶段 3 |
| 阶段 | 内容 | 预计时间 | 依赖 |
| ---- | --------------------------- | -------- | ------ |
| 1 | CLI 内联构建(快速止血) | 1-2 天 | 无 |
| 2 | core 去 NestJS + 定义新接口 | 3-4 天 | 阶段 1 |
| 3 | CLI 去 NestJS | 3-5 天 | 阶段 2 |
| 4 | 迁移扩展 | 2.5-5 天 | 阶段 3 |
**总计**10-16 天
@@ -29,12 +29,10 @@ externals: [
{ "@spaceflow/core": "module @spaceflow/core" },
{ "@nestjs/common": "module @nestjs/common" },
// ...
]
];
// 改为:只排除 Node.js 内置模块
externals: [
/^node:/,
]
externals: [/^node:/];
```
### 1.2 验证步骤
@@ -72,7 +70,7 @@ space mcp --verbose
**新建文件**`packages/core/src/extension-system/types.ts`
```typescript
// SpaceflowContext, CommandDefinition, ExtensionDefinition,
// SpaceflowContext, CommandDefinition, ExtensionDefinition,
// ServiceDefinition, McpToolDefinition, McpServerDefinition
// 详见 architecture-v2.md 2.3.1 节
```
@@ -108,9 +106,15 @@ export class ConfigReader {
this.config = readConfigSync();
}
get<T>(key: string): T | undefined { /* ... */ }
getPluginConfig<T>(key: string): T | undefined { /* ... */ }
registerSchema(key: string, schema: ZodSchema): void { /* ... */ }
get<T>(key: string): T | undefined {
/* ... */
}
getPluginConfig<T>(key: string): T | undefined {
/* ... */
}
registerSchema(key: string, schema: ZodSchema): void {
/* ... */
}
}
```
@@ -130,17 +134,17 @@ export function loadEnvFiles(paths: string[]): void {
需要修改的服务文件(按依赖顺序):
| 文件 | 改动 |
|------|------|
| `shared/output/output.service.ts` | 移除 `@Injectable()` |
| `shared/storage/storage.service.ts` | 移除 `@Injectable()``@Inject()`,构造函数改为接收 config |
| `shared/git-sdk/git-sdk.service.ts` | 移除 `@Injectable()` |
| 文件 | 改动 |
| --------------------------------------------- | ---------------------------------------------------------- |
| `shared/output/output.service.ts` | 移除 `@Injectable()` |
| `shared/storage/storage.service.ts` | 移除 `@Injectable()``@Inject()`,构造函数改为接收 config |
| `shared/git-sdk/git-sdk.service.ts` | 移除 `@Injectable()` |
| `shared/git-provider/git-provider.service.ts` | 移除 `@Injectable()``@Inject()`,构造函数改为接收 config |
| `shared/llm-proxy/llm-proxy.service.ts` | 移除 `@Injectable()``@Inject()`,构造函数改为接收 config |
| `shared/llm-proxy/adapters/*.adapter.ts` | 移除 `@Injectable()` |
| `shared/feishu-sdk/feishu-sdk.service.ts` | 移除 `@Injectable()``@Inject()` |
| `shared/claude-setup/claude-setup.service.ts` | 移除 `@Injectable()` |
| `config/schema-generator.service.ts` | 移除 `@Injectable()` |
| `shared/llm-proxy/llm-proxy.service.ts` | 移除 `@Injectable()``@Inject()`,构造函数改为接收 config |
| `shared/llm-proxy/adapters/*.adapter.ts` | 移除 `@Injectable()` |
| `shared/feishu-sdk/feishu-sdk.service.ts` | 移除 `@Injectable()``@Inject()` |
| `shared/claude-setup/claude-setup.service.ts` | 移除 `@Injectable()` |
| `config/schema-generator.service.ts` | 移除 `@Injectable()` |
### 2.4 移除 NestJS 模块
@@ -186,7 +190,7 @@ export { loadEnvFiles } from "./config/load-env";
// "@nestjs/core": "catalog:",
// "nest-commander": "catalog:",
// "reflect-metadata": "catalog:",
// 新增
"dotenv": "^16.4.5"
}
@@ -254,22 +258,22 @@ import { Command } from "commander";
需要迁移的内置命令(按复杂度排序):
| 命令 | 文件 | 复杂度 |
|------|------|--------|
| version | `commands/version/` | 低 |
| list | `commands/list/` | 低 |
| schema | `commands/schema/` | 低 |
| clear | `commands/clear/` | 低 |
| install | `commands/install/` | 中 |
| uninstall | `commands/uninstall/` | 中 |
| update | `commands/update/` | 中 |
| create | `commands/create/` | 中 |
| build | `commands/build/` | 中 |
| dev | `commands/dev/` | 中 |
| commit | `commands/commit/` | 中 |
| setup | `commands/setup/` | 中 |
| runx | `commands/runx/` | 中 |
| mcp | `commands/mcp/` | 高 |
| 命令 | 文件 | 复杂度 |
| --------- | --------------------- | ------ |
| version | `commands/version/` | 低 |
| list | `commands/list/` | 低 |
| schema | `commands/schema/` | 低 |
| clear | `commands/clear/` | 低 |
| install | `commands/install/` | 中 |
| uninstall | `commands/uninstall/` | 中 |
| update | `commands/update/` | 中 |
| create | `commands/create/` | 中 |
| build | `commands/build/` | 中 |
| dev | `commands/dev/` | 中 |
| commit | `commands/commit/` | 中 |
| setup | `commands/setup/` | 中 |
| runx | `commands/runx/` | 中 |
| mcp | `commands/mcp/` | 高 |
**迁移模板**
@@ -277,8 +281,12 @@ import { Command } from "commander";
// 旧版 (NestJS)
@Command({ name: "list", description: "..." })
export class ListCommand extends CommandRunner {
constructor(private readonly service: ListService) { super(); }
async run() { /* ... */ }
constructor(private readonly service: ListService) {
super();
}
async run() {
/* ... */
}
}
// 新版 (defineExtension)
@@ -299,8 +307,8 @@ export const listCommand: CommandDefinition = {
{
"dependencies": {
// 新增
"commander": "^12.1.0",
"commander": "^12.1.0"
// 移除 peerDependencies
},
"peerDependencies": {
@@ -351,24 +359,24 @@ space -h
### 4.1 迁移顺序
| 扩展 | 复杂度 | service 数量 | MCP |
|------|--------|--------------|-----|
| ci-scripts | 低 | 1 | 无 |
| ci-shell | 低 | 1 | 无 |
| publish | 中 | 2 | 无 |
| period-summary | 中 | 1 | 无 |
| review | 高 | 6 | 有 |
| 扩展 | 复杂度 | service 数量 | MCP |
| -------------- | ------ | ------------ | --- |
| scripts | 低 | 1 | 无 |
| shell | 低 | 1 | 无 |
| publish | 中 | 2 | 无 |
| review-summary | 中 | 1 | 无 |
| review | 高 | 6 | 有 |
### 4.2 迁移模板
**旧版结构**
```
extensions/ci-scripts/
extensions/scripts/
├── src/
│ ├── ci-scripts.module.ts # 删除
│ ├── ci-scripts.command.ts # 合并到 index.ts
│ ├── ci-scripts.service.ts # 保留,去装饰器
│ ├── scripts.module.ts # 删除
│ ├── scripts.command.ts # 合并到 index.ts
│ ├── scripts.service.ts # 保留,去装饰器
│ └── index.ts # 重写
└── package.json # 更新
```
@@ -376,9 +384,9 @@ extensions/ci-scripts/
**新版结构**
```
extensions/ci-scripts/
extensions/scripts/
├── src/
│ ├── ci-scripts.service.ts # 纯 class
│ ├── scripts.service.ts # 纯 class
│ ├── i18n.ts # 扩展自己的 i18n
│ ├── locales/
│ │ ├── zh-cn.json
@@ -398,15 +406,15 @@ extensions/ci-scripts/
}
```
### 4.4 ci-scripts 迁移示例
### 4.4 scripts 迁移示例
**`extensions/ci-scripts/src/index.ts`**
**`extensions/scripts/src/index.ts`**
```typescript
import { defineExtension } from "@spaceflow/core";
import { z } from "zod";
import { t } from "./i18n";
import { CiScriptsService } from "./ci-scripts.service";
import { ScriptsService } from "./scripts.service";
import type { GitProviderService } from "@spaceflow/core";
const CiConfigSchema = z.object({
@@ -415,7 +423,7 @@ const CiConfigSchema = z.object({
});
export default defineExtension({
name: "@spaceflow/ci-scripts",
name: "@spaceflow/scripts",
version: "0.19.3",
configKey: "ci",
configSchema: () => CiConfigSchema,
@@ -423,23 +431,22 @@ export default defineExtension({
services: [
{
key: "ci.service",
factory: (ctx) => new CiScriptsService(
ctx.getService<GitProviderService>("gitProvider"),
ctx.config,
),
factory: (ctx) =>
new ScriptsService(
ctx.getService<GitProviderService>("gitProvider"),
ctx.config,
),
},
],
commands: [
{
name: "ci-script",
name: "script",
description: t("description"),
arguments: "<script>",
options: [
{ flags: "-d, --dry-run", description: t("options.dryRun") },
],
options: [{ flags: "-d, --dry-run", description: t("options.dryRun") }],
async run(args, options, ctx) {
const service = ctx.getService<CiScriptsService>("ci.service");
const service = ctx.getService<ScriptsService>("ci.service");
await service.execute(args.join(" "), options);
},
},
@@ -503,14 +510,14 @@ mcp: defineMcpServer({
```bash
# 1. 构建扩展
cd extensions/ci-scripts && pnpm build
cd extensions/scripts && pnpm build
# 2. 在 .spaceflow 中安装
cd /path/to/test/project
pnpm add @spaceflow/ci-scripts --filter .spaceflow
pnpm add @spaceflow/scripts --filter .spaceflow
# 3. 测试命令
space ci-script "console.log('test')" --dry-run
space script "console.log('test')" --dry-run
# 4. 测试 MCP如果有
space mcp --verbose
@@ -577,9 +584,9 @@ space mcp --verbose
### 阶段 4 完成
- [ ] ci-scripts 迁移
- [ ] ci-shell 迁移
- [ ] scripts 迁移
- [ ] shell 迁移
- [ ] publish 迁移
- [ ] period-summary 迁移
- [ ] review-summary 迁移
- [ ] review 迁移
- [ ] 全局安装集成测试通过

View File

@@ -1,34 +0,0 @@
# ci-scripts — 脚本执行
`ci-scripts` 命令用于在 CI 环境中执行仓库中的自定义脚本。
## 安装
```bash
spaceflow install @spaceflow/ci-scripts
```
## 基本用法
```bash
# 执行指定脚本
spaceflow ci-scripts --script ./scripts/deploy.sh
# CI 模式
spaceflow ci-scripts --script ./scripts/test.sh --ci
```
## 使用场景
- 在 PR 合并后执行部署脚本
- 在 CI 中运行自定义检查脚本
- 批量执行仓库中的自动化任务
## 命令行选项
| 选项 | 说明 |
|------|------|
| `--script <path>` | 脚本文件路径 |
| `--ci` | CI 模式 |
| `--dry-run` | 试运行 |
| `--verbose` | 详细日志 |

View File

@@ -1,34 +0,0 @@
# ci-shell — Shell 执行
`ci-shell` 命令用于在 CI 环境中执行自定义 Shell 命令。
## 安装
```bash
spaceflow install @spaceflow/ci-shell
```
## 基本用法
```bash
# 执行 Shell 命令
spaceflow ci-shell --command "npm test"
# CI 模式
spaceflow ci-shell --command "npm run build" --ci
```
## 使用场景
- 在 CI 中执行任意 Shell 命令
- 通过 GitHub Actions 触发自定义命令
- 配合飞书机器人远程执行命令
## 命令行选项
| 选项 | 说明 |
|------|------|
| `--command <cmd>` | 要执行的 Shell 命令 |
| `--ci` | CI 模式 |
| `--dry-run` | 试运行 |
| `--verbose` | 详细日志 |

View File

@@ -19,8 +19,8 @@ spaceflow list
publish @spaceflow/publish [link]
命令: publish
ci-shell @spaceflow/ci-shell [npm]
命令: ci-shell
shell @spaceflow/shell [npm]
命令: shell
```
输出包含:
@@ -32,6 +32,6 @@ spaceflow list
## 命令行选项
| 选项 | 简写 | 说明 |
|------|------|------|
| 选项 | 简写 | 说明 |
| ----------- | ---- | ---------------- |
| `--verbose` | `-v` | 显示更多详细信息 |

View File

@@ -1,37 +0,0 @@
# period-summary — 周期总结
`period-summary` 命令用于生成周期性工作总结,支持飞书消息推送。
## 安装
```bash
spaceflow install @spaceflow/period-summary
```
## 基本用法
```bash
# 生成周总结
spaceflow period-summary --period week
# 生成月总结
spaceflow period-summary --period month
# 推送到飞书
spaceflow period-summary --period week --notify feishu
```
## 功能特性
- **Git 日志分析** — 自动分析指定周期内的 Git 提交记录
- **AI 总结** — 使用 LLM 生成结构化的工作总结
- **飞书推送** — 支持将总结推送到飞书群聊
## 命令行选项
| 选项 | 说明 |
|------|------|
| `--period <period>` | 总结周期week / month |
| `--notify <channel>` | 通知渠道feishu |
| `--dry-run` | 试运行 |
| `--verbose` | 详细日志 |

View File

@@ -0,0 +1,37 @@
# review-summary — 审查总结
`review-summary` 命令用于生成周期性工作总结,支持飞书消息推送。
## 安装
```bash
spaceflow install @spaceflow/review-summary
```
## 基本用法
```bash
# 生成周总结
spaceflow review-summary --period week
# 生成月总结
spaceflow review-summary --period month
# 推送到飞书
spaceflow review-summary --period week --notify feishu
```
## 功能特性
- **Git 日志分析** — 自动分析指定周期内的 Git 提交记录
- **AI 总结** — 使用 LLM 生成结构化的工作总结
- **飞书推送** — 支持将总结推送到飞书群聊
## 命令行选项
| 选项 | 说明 |
| -------------------- | ------------------------ |
| `--period <period>` | 总结周期week / month |
| `--notify <channel>` | 通知渠道feishu |
| `--dry-run` | 试运行 |
| `--verbose` | 详细日志 |

View File

@@ -9,7 +9,7 @@
spaceflow x @spaceflow/review --help
# 运行本地路径的 Extension
spaceflow x ./extensions/ci-scripts -- --script ./deploy.sh
spaceflow x ./extensions/scripts -- --script ./deploy.sh
# 使用完整命令名
spaceflow runx @spaceflow/review -- -p 123
@@ -38,7 +38,7 @@ spaceflow x @spaceflow/review -- --help
spaceflow x @spaceflow/review -- -p 123
# 指定名称并传递参数
spaceflow x ./extensions/ci-scripts -n ci-scripts -- --script ./test.sh
spaceflow x ./extensions/scripts -n scripts -- --script ./test.sh
```
## 与 install 的区别

View File

@@ -0,0 +1,34 @@
# scripts — 脚本执行
`scripts` 命令用于在 CI 环境中执行仓库中的自定义脚本。
## 安装
```bash
spaceflow install @spaceflow/scripts
```
## 基本用法
```bash
# 执行指定脚本
spaceflow scripts --script ./scripts/deploy.sh
# CI 模式
spaceflow scripts --script ./scripts/test.sh --ci
```
## 使用场景
- 在 PR 合并后执行部署脚本
- 在 CI 中运行自定义检查脚本
- 批量执行仓库中的自动化任务
## 命令行选项
| 选项 | 说明 |
| ----------------- | ------------ |
| `--script <path>` | 脚本文件路径 |
| `--ci` | CI 模式 |
| `--dry-run` | 试运行 |
| `--verbose` | 详细日志 |

View File

@@ -0,0 +1,34 @@
# shell — Shell 执行
`shell` 命令用于在 CI 环境中执行自定义 Shell 命令。
## 安装
```bash
spaceflow install @spaceflow/shell
```
## 基本用法
```bash
# 执行 Shell 命令
spaceflow shell --command "npm test"
# CI 模式
spaceflow shell --command "npm run build" --ci
```
## 使用场景
- 在 CI 中执行任意 Shell 命令
- 通过 GitHub Actions 触发自定义命令
- 配合飞书机器人远程执行命令
## 命令行选项
| 选项 | 说明 |
| ----------------- | ------------------- |
| `--command <cmd>` | 要执行的 Shell 命令 |
| `--ci` | CI 模式 |
| `--dry-run` | 试运行 |
| `--verbose` | 详细日志 |

View File

@@ -99,7 +99,7 @@ AI 代码审查相关配置。
"dependencies": {
"@spaceflow/review": "link:./extensions/review",
"@spaceflow/publish": "link:./extensions/publish",
"@spaceflow/ci-shell": "link:./extensions/ci-shell"
"@spaceflow/shell": "link:./extensions/shell"
}
}
```

View File

@@ -8,33 +8,33 @@ Spaceflow 的所有功能命令都以 Extension 形式组织。Extension 分为*
内置在 `@spaceflow/cli` 中,无需安装即可使用:
| 命令 | 说明 |
|------|------|
| `install` | 安装 Extension |
| `uninstall` | 卸载 Extension |
| `update` | 更新 Extension |
| `build` | 构建 Extension |
| `dev` | 开发模式 |
| `create` | 创建 Extension 模板 |
| `list` | 列出已安装 Extension |
| `clear` | 清理缓存 |
| `commit` | Git 提交辅助 |
| `setup` | 编辑器配置 |
| `schema` | 生成 JSON Schema |
| `mcp` | MCP 服务 |
| `runx` | 运行外部命令 |
| 命令 | 说明 |
| ----------- | -------------------- |
| `install` | 安装 Extension |
| `uninstall` | 卸载 Extension |
| `update` | 更新 Extension |
| `build` | 构建 Extension |
| `dev` | 开发模式 |
| `create` | 创建 Extension 模板 |
| `list` | 列出已安装 Extension |
| `clear` | 清理缓存 |
| `commit` | Git 提交辅助 |
| `setup` | 编辑器配置 |
| `schema` | 生成 JSON Schema |
| `mcp` | MCP 服务 |
| `runx` | 运行外部命令 |
### 外部 Extension
独立的 npm 包,需要通过 `spaceflow install` 安装:
| Extension | 包名 | 说明 |
|-----------|------|------|
| review | `@spaceflow/review` | AI 代码审查 |
| publish | `@spaceflow/publish` | 版本发布 |
| ci-scripts | `@spaceflow/ci-scripts` | 自定义脚本执行 |
| ci-shell | `@spaceflow/ci-shell` | Shell 命令执行 |
| period-summary | `@spaceflow/period-summary` | 周期总结 |
| Extension | 包名 | 说明 |
| -------------- | --------------------------- | -------------- |
| review | `@spaceflow/review` | AI 代码审查 |
| publish | `@spaceflow/publish` | 版本发布 |
| scripts | `@spaceflow/scripts` | 自定义脚本执行 |
| shell | `@spaceflow/shell` | Shell 命令执行 |
| review-summary | `@spaceflow/review-summary` | 审查总结 |
## Extension 生命周期
@@ -53,7 +53,10 @@ install → 注册到 spaceflow.json → CLI 启动时加载 → 注入 NestJS
每个 Extension 必须实现 `SpaceflowExtension` 接口:
```typescript
import type { SpaceflowExtension, SpaceflowExtensionMetadata } from "@spaceflow/core";
import type {
SpaceflowExtension,
SpaceflowExtensionMetadata,
} from "@spaceflow/core";
export class ReviewExtension implements SpaceflowExtension {
getMetadata(): SpaceflowExtensionMetadata {
@@ -73,14 +76,14 @@ export class ReviewExtension implements SpaceflowExtension {
### SpaceflowExtensionMetadata
| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| `name` | `string` | ✅ | Extension 名称 |
| `commands` | `string[]` | ✅ | 提供的命令列表 |
| `configKey` | `string` | ❌ | 对应 `spaceflow.json` 中的配置 key |
| `description` | `string` | ❌ | Extension 描述 |
| `version` | `string` | ❌ | 版本号 |
| `locales` | `Record<string, Record<string, string>>` | ❌ | i18n 语言资源 |
| 字段 | 类型 | 必填 | 说明 |
| ------------- | ---------------------------------------- | ---- | ---------------------------------- |
| `name` | `string` | ✅ | Extension 名称 |
| `commands` | `string[]` | ✅ | 提供的命令列表 |
| `configKey` | `string` | ❌ | 对应 `spaceflow.json` 中的配置 key |
| `description` | `string` | ❌ | Extension 描述 |
| `version` | `string` | ❌ | 版本号 |
| `locales` | `Record<string, Record<string, string>>` | ❌ | i18n 语言资源 |
## 管理命令

View File

@@ -14,28 +14,28 @@ Spaceflow 是一个**可扩展的 AI 工作流引擎**,为团队提供统一
## 技术栈
| 技术 | 用途 |
|------|------|
| [NestJS](https://nestjs.com/) | 核心框架,依赖注入和模块化 |
| [nest-commander](https://docs.nestjs.com/recipes/nest-commander) | CLI 命令系统 |
| [Rspack](https://rspack.dev/) | 构建打包 |
| [i18next](https://www.i18next.com/) | 国际化 |
| [Zod](https://zod.dev/) | 配置校验 |
| [pnpm](https://pnpm.io/) | 包管理Monorepo |
| 技术 | 用途 |
| ---------------------------------------------------------------- | -------------------------- |
| [NestJS](https://nestjs.com/) | 核心框架,依赖注入和模块化 |
| [nest-commander](https://docs.nestjs.com/recipes/nest-commander) | CLI 命令系统 |
| [Rspack](https://rspack.dev/) | 构建打包 |
| [i18next](https://www.i18next.com/) | 国际化 |
| [Zod](https://zod.dev/) | 配置校验 |
| [pnpm](https://pnpm.io/) | 包管理Monorepo |
## 包结构
Spaceflow 采用 Monorepo 结构,主要包含以下包:
| 包名 | 说明 |
|------|------|
| `@spaceflow/core` | 核心能力库,提供 Git Provider、LLM Proxy、Logger 等基础模块 |
| `@spaceflow/cli` | CLI 入口,包含所有内置命令 |
| `@spaceflow/review` | AI 代码审查 Extension |
| `@spaceflow/publish` | 版本发布 Extension |
| `@spaceflow/ci-scripts` | 自定义脚本执行 Extension |
| `@spaceflow/ci-shell` | Shell 命令执行 Extension |
| `@spaceflow/period-summary` | 周期总结 Extension |
| 包名 | 说明 |
| --------------------------- | ----------------------------------------------------------- |
| `@spaceflow/core` | 核心能力库,提供 Git Provider、LLM Proxy、Logger 等基础模块 |
| `@spaceflow/cli` | CLI 入口,包含所有内置命令 |
| `@spaceflow/review` | AI 代码审查 Extension |
| `@spaceflow/publish` | 版本发布 Extension |
| `@spaceflow/scripts` | 自定义脚本执行 Extension |
| `@spaceflow/shell` | Shell 命令执行 Extension |
| `@spaceflow/review-summary` | 审查总结 Extension |
## 适用场景

View File

@@ -44,9 +44,9 @@ spaceflow/
├── extensions/ # 外部 Extension独立 npm 包)
│ ├── review/ # @spaceflow/review — AI 代码审查
│ ├── publish/ # @spaceflow/publish — 版本发布
│ ├── ci-scripts/ # @spaceflow/ci-scripts — 脚本执行
│ ├── ci-shell/ # @spaceflow/ci-shell — Shell 执行
│ └── period-summary/ # @spaceflow/period-summary — 周期总结
│ ├── scripts/ # @spaceflow/scripts — 脚本执行
│ ├── shell/ # @spaceflow/shell — Shell 执行
│ └── review-summary/ # @spaceflow/review-summary — 审查总结
├── actions/ # GitHub Actions
│ ├── src/

View File

@@ -4,13 +4,13 @@
## 全局选项
| 选项 | 简写 | 说明 |
|------|------|------|
| `--help` | `-h` | 显示帮助信息 |
| `--version` | `-V` | 显示版本号 |
| 选项 | 简写 | 说明 |
| ----------- | ---- | ----------------------------------------- |
| `--help` | `-h` | 显示帮助信息 |
| `--version` | `-V` | 显示版本号 |
| `--verbose` | `-v` | 详细日志(`-v` 基本日志,`-vv` 详细日志) |
| `--dry-run` | | 试运行,不实际执行 |
| `--ci` | | CI 模式 |
| `--dry-run` | | 试运行,不实际执行 |
| `--ci` | | CI 模式 |
## 内置命令
@@ -160,26 +160,26 @@ spaceflow review -b <base> --head <head> [-l <llm-mode>]
spaceflow publish [--dry-run]
```
### `ci-scripts`
### `scripts`
脚本执行。详见 [ci-scripts 命令](/guide/commands/ci-scripts)。
脚本执行。详见 [scripts 命令](/guide/commands/scripts)。
```bash
spaceflow ci-scripts --script <path>
spaceflow scripts --script <path>
```
### `ci-shell`
### `shell`
Shell 执行。详见 [ci-shell 命令](/guide/commands/ci-shell)。
Shell 执行。详见 [shell 命令](/guide/commands/shell)。
```bash
spaceflow ci-shell --command <cmd>
spaceflow shell --command <cmd>
```
### `period-summary`
### `review-summary`
周期总结。详见 [period-summary 命令](/guide/commands/period-summary)。
审查总结。详见 [review-summary 命令](/guide/commands/review-summary)。
```bash
spaceflow period-summary --period <week|month>
spaceflow review-summary --period <week|month>
```

View File

@@ -63,8 +63,8 @@
"dependencies": {
"@spaceflow/review": "link:./extensions/review",
"@spaceflow/publish": "link:./extensions/publish",
"@spaceflow/ci-shell": "link:./extensions/ci-shell",
"@spaceflow/ci-scripts": "link:./extensions/ci-scripts"
"@spaceflow/shell": "link:./extensions/shell",
"@spaceflow/scripts": "link:./extensions/scripts"
}
}
```

View File

@@ -1,11 +0,0 @@
import { addLocaleResources } from "@spaceflow/core";
import zhCN from "./zh-cn/ci-scripts.json";
import en from "./en/ci-scripts.json";
/** ci-scripts 命令 i18n 资源 */
export const ciScriptsLocales: Record<string, Record<string, string>> = {
"zh-CN": zhCN,
en,
};
addLocaleResources("ci-scripts", ciScriptsLocales);

View File

@@ -1,11 +0,0 @@
import { addLocaleResources } from "@spaceflow/core";
import zhCN from "./zh-cn/ci-shell.json";
import en from "./en/ci-shell.json";
/** ci-shell 命令 i18n 资源 */
export const ciShellLocales: Record<string, Record<string, string>> = {
"zh-CN": zhCN,
en,
};
addLocaleResources("ci-shell", ciShellLocales);

View File

@@ -1,11 +0,0 @@
import { addLocaleResources } from "@spaceflow/core";
import zhCN from "./zh-cn/period-summary.json";
import en from "./en/period-summary.json";
/** period-summary 命令 i18n 资源 */
export const periodSummaryLocales: Record<string, Record<string, string>> = {
"zh-CN": zhCN,
en,
};
addLocaleResources("period-summary", periodSummaryLocales);

View File

@@ -1,14 +1,14 @@
# @spaceflow/period-summary
# @spaceflow/review-summary
[![npm version](https://img.shields.io/npm/v/@spaceflow/period-summary?color=blue)](https://www.npmjs.com/package/@spaceflow/period-summary)
[![npm version](https://img.shields.io/npm/v/@spaceflow/review-summary?color=blue)](https://www.npmjs.com/package/@spaceflow/review-summary)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
> Spaceflow 周期统计扩展,根据时间范围统计 PR 贡献情况按人员汇总并排序。支持输出到控制台、GitHub Issue 或 Markdown 文件。
> Spaceflow 审查统计扩展,根据时间范围统计 PR 贡献情况按人员汇总并排序。支持输出到控制台、GitHub Issue 或 Markdown 文件。
## 安装
```bash
pnpm spaceflow install @spaceflow/period-summary
pnpm spaceflow install @spaceflow/review-summary
```
## 功能特性
@@ -23,16 +23,16 @@ pnpm spaceflow install @spaceflow/period-summary
```bash
# 使用时间预设 - 统计本周
spaceflow period-summary -p this-week
spaceflow review-summary -p this-week
# 使用时间预设 - 统计上月
spaceflow period-summary -p last-month
spaceflow review-summary -p last-month
# 自定义日期范围
spaceflow period-summary -s 2026-01-01 -u 2026-01-18
spaceflow review-summary -s 2026-01-01 -u 2026-01-18
# 输出到 GitHub Issue
spaceflow period-summary -p last-week -o issue -c
spaceflow review-summary -p last-week -o issue -c
```
## 命令行参数

View File

@@ -1,13 +1,13 @@
{
"name": "@spaceflow/period-summary",
"name": "@spaceflow/review-summary",
"version": "0.20.0",
"description": "Spaceflow 周期统计命令,根据时间范围统计 PR 贡献情况,按人员汇总并排序",
"description": "Spaceflow 审查统计命令,根据时间范围统计 PR 贡献情况,按人员汇总并排序",
"license": "MIT",
"author": "Lydanne",
"repository": {
"type": "git",
"url": "git+https://github.com/Lydanne/spaceflow.git",
"directory": "extensions/period-summary"
"directory": "extensions/review-summary"
},
"publishConfig": {
"access": "public"

View File

@@ -3,14 +3,14 @@ import { defineExtension } from "@spaceflow/core";
import { t } from "@spaceflow/core";
export const extension = defineExtension({
name: "period-summary",
name: "review-summary",
version: "1.0.0",
description: t("period-summary:extensionDescription"),
configKey: "period-summary",
description: t("review-summary:extensionDescription"),
configKey: "review-summary",
commands: [
{
name: "period-summary",
description: t("period-summary:description"),
name: "review-summary",
description: t("review-summary:description"),
options: [
{
flags: "-d, --days",
@@ -18,8 +18,8 @@ export const extension = defineExtension({
},
],
run: async (args, options, ctx) => {
ctx.output.info("period-summary 命令暂未实现");
// TODO: 实现 period-summary 命令逻辑
ctx.output.info("review-summary 命令暂未实现");
// TODO: 实现 review-summary 命令逻辑
},
},
],

View File

@@ -0,0 +1,11 @@
import { addLocaleResources } from "@spaceflow/core";
import zhCN from "./zh-cn/review-summary.json";
import en from "./en/review-summary.json";
/** review-summary 命令 i18n 资源 */
export const reviewSummaryLocales: Record<string, Record<string, string>> = {
"zh-CN": zhCN,
en,
};
addLocaleResources("review-summary", reviewSummaryLocales);

View File

@@ -1,27 +1,27 @@
# @spaceflow/ci-scripts
# @spaceflow/scripts
[![npm version](https://img.shields.io/npm/v/@spaceflow/ci-scripts?color=blue)](https://www.npmjs.com/package/@spaceflow/ci-scripts)
[![npm version](https://img.shields.io/npm/v/@spaceflow/scripts?color=blue)](https://www.npmjs.com/package/@spaceflow/scripts)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
> Spaceflow CI 脚本扩展,在分支锁定/解锁保护下执行 JavaScript 语句。适用于 CI 环境中需要原子性执行脚本的场景。
> Spaceflow 脚本扩展,在分支锁定/解锁保护下执行 JavaScript 语句。适用于 CI 环境中需要原子性执行脚本的场景。
## 安装
```bash
pnpm spaceflow install @spaceflow/ci-scripts
pnpm spaceflow install @spaceflow/scripts
```
## 使用
```bash
# 执行 JS 表达式
spaceflow ci-scripts -e "console.log('hello')"
spaceflow scripts -e "console.log('hello')"
# CI 模式
spaceflow ci-scripts --ci -e "await fetch('https://api.example.com/deploy')"
spaceflow scripts --ci -e "await fetch('https://api.example.com/deploy')"
# 仅预览,不实际执行
spaceflow ci-scripts --dry-run -e "console.log('test')"
spaceflow scripts --dry-run -e "console.log('test')"
```
## 命令行参数

View File

@@ -1,13 +1,13 @@
{
"name": "@spaceflow/ci-shell",
"name": "@spaceflow/scripts",
"version": "0.20.0",
"description": "Spaceflow CI Shell 插件,用于在分支锁定/解锁之间执行 Shell 命令",
"description": "Spaceflow 脚本插件,用于在分支锁定/解锁之间执行 JS 语句",
"license": "MIT",
"author": "Lydanne",
"repository": {
"type": "git",
"url": "git+https://github.com/Lydanne/spaceflow.git",
"directory": "extensions/ci-shell"
"directory": "extensions/scripts"
},
"publishConfig": {
"access": "public"

View File

@@ -1,17 +1,17 @@
import "./locales";
import { defineExtension, t } from "@spaceflow/core";
import type { GitProviderService } from "@spaceflow/core";
import { CiScriptsService } from "./ci-scripts.service";
import { ScriptsService } from "./scripts.service";
export const extension = defineExtension({
name: "ci-scripts",
name: "scripts",
version: "1.0.0",
description: t("ci-scripts:extensionDescription"),
configKey: "ci-scripts",
description: t("scripts:extensionDescription"),
configKey: "scripts",
commands: [
{
name: "ci-script",
description: t("ci-scripts:description"),
name: "script",
description: t("scripts:description"),
arguments: "<script>",
options: [
{
@@ -22,21 +22,21 @@ export const extension = defineExtension({
run: async (args, options, ctx) => {
const script = args[0];
if (!script) {
ctx.output.error(t("ci-scripts:noScript"));
ctx.output.error(t("scripts:noScript"));
process.exit(1);
}
const gitProvider = ctx.getService<GitProviderService>("gitProvider");
if (!gitProvider) {
ctx.output.error("ci-script 命令需要配置 Git Provider");
ctx.output.error("script 命令需要配置 Git Provider");
process.exit(1);
}
const ciScriptsService = new CiScriptsService(gitProvider, ctx.config);
const context = ciScriptsService.getContextFromEnv({
const scriptsService = new ScriptsService(gitProvider, ctx.config);
const context = scriptsService.getContextFromEnv({
dryRun: !!options?.dryRun,
});
await ciScriptsService.execute(context, script);
await scriptsService.execute(context, script);
},
},
],

View File

@@ -0,0 +1,11 @@
import { addLocaleResources } from "@spaceflow/core";
import zhCN from "./zh-cn/scripts.json";
import en from "./en/scripts.json";
/** scripts 命令 i18n 资源 */
export const scriptsLocales: Record<string, Record<string, string>> = {
"zh-CN": zhCN,
en,
};
addLocaleResources("scripts", scriptsLocales);

View File

@@ -1,31 +1,31 @@
import { GitProviderService, BranchProtection, CiConfig } from "@spaceflow/core";
import type { IConfigReader } from "@spaceflow/core";
export interface CiScriptsOptions {
export interface ScriptsOptions {
dryRun: boolean;
}
// 定义常量表示进程退出码
const PROCESS_EXIT_CODE_ERROR = 1;
export interface CiScriptsContext extends CiScriptsOptions {
export interface ScriptsContext extends ScriptsOptions {
owner: string;
repo: string;
branch: string;
}
export interface CiScriptsResult {
export interface ScriptsResult {
success: boolean;
message: string;
protection?: BranchProtection | null;
}
export class CiScriptsService {
export class ScriptsService {
constructor(
protected readonly gitProvider: GitProviderService,
protected readonly config: IConfigReader,
) {}
getContextFromEnv(options: CiScriptsOptions): CiScriptsContext {
getContextFromEnv(options: ScriptsOptions): ScriptsContext {
this.gitProvider.validateConfig();
const ciConf = this.config.get<CiConfig>("ci");
@@ -53,7 +53,7 @@ export class CiScriptsService {
};
}
async execute(context: CiScriptsContext, script: string): Promise<void> {
async execute(context: ScriptsContext, script: string): Promise<void> {
try {
// 1. 锁定分支
await this.handleBegin(context);
@@ -89,7 +89,7 @@ export class CiScriptsService {
}
}
protected async handleBegin(context: CiScriptsContext): Promise<CiScriptsResult> {
protected async handleBegin(context: ScriptsContext): Promise<ScriptsResult> {
const { owner, repo, branch, dryRun } = context;
if (dryRun) {
@@ -116,7 +116,7 @@ export class CiScriptsService {
};
}
protected async handleEnd(context: CiScriptsContext): Promise<CiScriptsResult> {
protected async handleEnd(context: ScriptsContext): Promise<ScriptsResult> {
const { owner, repo, branch, dryRun } = context;
if (dryRun) {

View File

@@ -1,27 +1,27 @@
# @spaceflow/ci-shell
# @spaceflow/shell
[![npm version](https://img.shields.io/npm/v/@spaceflow/ci-shell?color=blue)](https://www.npmjs.com/package/@spaceflow/ci-shell)
[![npm version](https://img.shields.io/npm/v/@spaceflow/shell?color=blue)](https://www.npmjs.com/package/@spaceflow/shell)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
> Spaceflow CI Shell 扩展,在分支锁定/解锁保护下执行 Shell 命令。适用于 CI 环境中需要原子性执行命令的场景。
> Spaceflow Shell 扩展,在分支锁定/解锁保护下执行 Shell 命令。适用于 CI 环境中需要原子性执行命令的场景。
## 安装
```bash
pnpm spaceflow install @spaceflow/ci-shell
pnpm spaceflow install @spaceflow/shell
```
## 使用
```bash
# 执行 Shell 命令
spaceflow ci-shell -e "npm run deploy"
spaceflow shell -e "npm run deploy"
# CI 模式
spaceflow ci-shell --ci -e "pnpm build && pnpm test"
spaceflow shell --ci -e "pnpm build && pnpm test"
# 仅预览,不实际执行
spaceflow ci-shell --dry-run -e "echo 'test'"
spaceflow shell --dry-run -e "echo 'test'"
```
## 命令行参数

View File

@@ -1,13 +1,13 @@
{
"name": "@spaceflow/ci-scripts",
"name": "@spaceflow/shell",
"version": "0.20.0",
"description": "Spaceflow CI 脚本插件,用于在分支锁定/解锁之间执行 JS 语句",
"description": "Spaceflow Shell 插件,用于在分支锁定/解锁之间执行 Shell 命令",
"license": "MIT",
"author": "Lydanne",
"repository": {
"type": "git",
"url": "git+https://github.com/Lydanne/spaceflow.git",
"directory": "extensions/ci-scripts"
"directory": "extensions/shell"
},
"publishConfig": {
"access": "public"

View File

@@ -1,17 +1,17 @@
import "./locales";
import { defineExtension, t } from "@spaceflow/core";
import type { GitProviderService } from "@spaceflow/core";
import { CiShellService } from "./ci-shell.service";
import { ShellService } from "./shell.service";
export const extension = defineExtension({
name: "ci-shell",
name: "shell",
version: "1.0.0",
description: t("ci-shell:extensionDescription"),
configKey: "ci-shell",
description: t("shell:extensionDescription"),
configKey: "shell",
commands: [
{
name: "ci-shell",
description: t("ci-shell:description"),
name: "shell",
description: t("shell:description"),
arguments: "<command>",
options: [
{
@@ -22,21 +22,21 @@ export const extension = defineExtension({
run: async (args, options, ctx) => {
const command = args[0];
if (!command) {
ctx.output.error(t("ci-shell:noCommand"));
ctx.output.error(t("shell:noCommand"));
process.exit(1);
}
const gitProvider = ctx.getService<GitProviderService>("gitProvider");
if (!gitProvider) {
ctx.output.error("ci-shell 命令需要配置 Git Provider");
ctx.output.error("shell 命令需要配置 Git Provider");
process.exit(1);
}
const ciShellService = new CiShellService(gitProvider, ctx.config);
const context = ciShellService.getContextFromEnv({
const shellService = new ShellService(gitProvider, ctx.config);
const context = shellService.getContextFromEnv({
dryRun: !!options?.dryRun,
});
await ciShellService.execute(context, command);
await shellService.execute(context, command);
},
},
],

View File

@@ -0,0 +1,11 @@
import { addLocaleResources } from "@spaceflow/core";
import zhCN from "./zh-cn/shell.json";
import en from "./en/shell.json";
/** shell 命令 i18n 资源 */
export const shellLocales: Record<string, Record<string, string>> = {
"zh-CN": zhCN,
en,
};
addLocaleResources("shell", shellLocales);

View File

@@ -2,29 +2,29 @@ import { GitProviderService, BranchProtection, CiConfig } from "@spaceflow/core"
import type { IConfigReader } from "@spaceflow/core";
import { execSync } from "child_process";
export interface CiShellOptions {
export interface ShellOptions {
dryRun: boolean;
}
export interface CiShellContext extends CiShellOptions {
export interface ShellContext extends ShellOptions {
owner: string;
repo: string;
branch: string;
}
export interface CiShellResult {
export interface ShellResult {
success: boolean;
message: string;
protection?: BranchProtection | null;
}
export class CiShellService {
export class ShellService {
constructor(
protected readonly gitProvider: GitProviderService,
protected readonly config: IConfigReader,
) {}
getContextFromEnv(options: CiShellOptions): CiShellContext {
getContextFromEnv(options: ShellOptions): ShellContext {
this.gitProvider.validateConfig();
const ciConf = this.config.get<CiConfig>("ci");
@@ -52,7 +52,7 @@ export class CiShellService {
};
}
async execute(context: CiShellContext, command: string): Promise<void> {
async execute(context: ShellContext, command: string): Promise<void> {
try {
// 1. 锁定分支
await this.handleBegin(context);
@@ -84,7 +84,7 @@ export class CiShellService {
}
}
protected async handleBegin(context: CiShellContext): Promise<CiShellResult> {
protected async handleBegin(context: ShellContext): Promise<ShellResult> {
const { owner, repo, branch, dryRun } = context;
if (dryRun) {
@@ -111,7 +111,7 @@ export class CiShellService {
};
}
protected async handleEnd(context: CiShellContext): Promise<CiShellResult> {
protected async handleEnd(context: ShellContext): Promise<ShellResult> {
const { owner, repo, branch, dryRun } = context;
if (dryRun) {

78
pnpm-lock.yaml generated
View File

@@ -106,45 +106,6 @@ importers:
specifier: ^3.5.13
version: 3.5.28(typescript@5.9.3)
extensions/ci-scripts:
dependencies:
'@spaceflow/core':
specifier: workspace:*
version: link:../../packages/core
devDependencies:
'@spaceflow/cli':
specifier: workspace:*
version: link:../../packages/cli
'@types/node':
specifier: 'catalog:'
version: 22.19.1
extensions/ci-shell:
dependencies:
'@spaceflow/core':
specifier: workspace:*
version: link:../../packages/core
devDependencies:
'@spaceflow/cli':
specifier: workspace:*
version: link:../../packages/cli
'@types/node':
specifier: 'catalog:'
version: 22.19.1
extensions/period-summary:
dependencies:
'@spaceflow/core':
specifier: workspace:*
version: link:../../packages/core
devDependencies:
'@spaceflow/cli':
specifier: workspace:*
version: link:../../packages/cli
'@types/node':
specifier: 'catalog:'
version: 22.19.1
extensions/publish:
dependencies:
'@release-it/conventional-changelog':
@@ -201,6 +162,45 @@ importers:
specifier: 'catalog:'
version: 4.0.18(@types/node@22.19.1)(jiti@2.6.1)(terser@5.44.1)
extensions/review-summary:
dependencies:
'@spaceflow/core':
specifier: workspace:*
version: link:../../packages/core
devDependencies:
'@spaceflow/cli':
specifier: workspace:*
version: link:../../packages/cli
'@types/node':
specifier: 'catalog:'
version: 22.19.1
extensions/scripts:
dependencies:
'@spaceflow/core':
specifier: workspace:*
version: link:../../packages/core
devDependencies:
'@spaceflow/cli':
specifier: workspace:*
version: link:../../packages/cli
'@types/node':
specifier: 'catalog:'
version: 22.19.1
extensions/shell:
dependencies:
'@spaceflow/core':
specifier: workspace:*
version: link:../../packages/core
devDependencies:
'@spaceflow/cli':
specifier: workspace:*
version: link:../../packages/cli
'@types/node':
specifier: 'catalog:'
version: 22.19.1
packages/cli:
dependencies:
'@modelcontextprotocol/sdk':