@sokeai/cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -0
- package/package.json +32 -0
- package/scripts/build-binaries.sh +88 -0
- package/scripts/install.js +127 -0
- package/scripts/release.sh +216 -0
- package/scripts/run.js +53 -0
package/README.md
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# 授客AI官方CLI工具 (soke-cli)
|
|
2
|
+
|
|
3
|
+
`soke-cli` 是授客AI官方提供的命令行工具,旨在帮助开发者和系统管理员更便捷地通过命令行与授客AI开放平台进行交互。该工具使用 Go 语言开发,支持多平台,并提供了 NPM 包的安装方式。
|
|
4
|
+
|
|
5
|
+
## 核心能力
|
|
6
|
+
|
|
7
|
+
`soke-cli` 提供了以下核心能力:
|
|
8
|
+
|
|
9
|
+
1. **认证与配置管理**
|
|
10
|
+
- 支持通过 OAuth 设备码授权流程(Device Flow)进行快速登录。
|
|
11
|
+
- 灵活的配置管理,支持多租户、多环境(AppKey, AppSecret, API地址, CorpID等)。
|
|
12
|
+
|
|
13
|
+
2. **通用 API 调用**
|
|
14
|
+
- 提供 `api` 基础命令,支持直接发起任意 GET、POST、PUT、DELETE 等 HTTP 请求到开放平台接口。
|
|
15
|
+
|
|
16
|
+
3. **业务模块快捷命令**
|
|
17
|
+
- 针对授客AI核心业务场景提供了丰富的快捷命令集:
|
|
18
|
+
- **通讯录 (contact)**: 部门与用户查询、管理等。
|
|
19
|
+
- **课程 (course)**: 课程列表、分类、学习记录、人脸识别记录等。
|
|
20
|
+
- **考试 (exam)**: 考试列表、分类、考试成绩与记录查询。
|
|
21
|
+
- **学习地图 (learning-map)**: 学习地图、阶段、任务查询与分配。
|
|
22
|
+
- **证书 (certificate)**: 证书发放记录、分类等。
|
|
23
|
+
- **学分 (credit) & 积分 (point)**: 学分/积分日志及用户情况查询。
|
|
24
|
+
- **培训 (training)**: 线下培训查询与分配。
|
|
25
|
+
- **新闻公告 (news)**: 资讯列表与详情。
|
|
26
|
+
|
|
27
|
+
## 安装方法
|
|
28
|
+
|
|
29
|
+
### 方式一:通过 NPM 安装 (推荐)
|
|
30
|
+
如果你本地已安装 Node.js,可以直接使用 npm 全局安装:
|
|
31
|
+
```bash
|
|
32
|
+
npm install -g @sokeai/cli
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### 方式二:通过源码编译安装 (需要 Go 环境)
|
|
36
|
+
```bash
|
|
37
|
+
# 1. 克隆/下载本仓库代码
|
|
38
|
+
git clone <repository_url>
|
|
39
|
+
cd soke-cli
|
|
40
|
+
|
|
41
|
+
# 2. 编译并安装到 /usr/local/bin
|
|
42
|
+
make install
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## 快速开始
|
|
46
|
+
|
|
47
|
+
### 1. 初始化配置
|
|
48
|
+
首次使用前,需要配置你的开放平台凭证:
|
|
49
|
+
```bash
|
|
50
|
+
soke-cli config init
|
|
51
|
+
```
|
|
52
|
+
根据提示输入 `app_key`, `app_secret`, API地址(默认: `https://opendev.soke.cn`), `corpid` 和 `dept_user_id`。
|
|
53
|
+
|
|
54
|
+
可以使用 `soke-cli config show` 来查看当前配置。
|
|
55
|
+
|
|
56
|
+
### 2. 用户登录授权
|
|
57
|
+
配置完成后,进行设备授权登录:
|
|
58
|
+
```bash
|
|
59
|
+
soke-cli auth login
|
|
60
|
+
```
|
|
61
|
+
命令会返回一个设备码和链接,请在浏览器中打开链接并输入设备码完成授权。成功后即可调用需要用户授权的接口。
|
|
62
|
+
如果需要退出登录,可以执行 `soke-cli auth logout`。
|
|
63
|
+
|
|
64
|
+
## 使用示例
|
|
65
|
+
|
|
66
|
+
### 调用快捷业务命令
|
|
67
|
+
以课程模块为例,你可以使用以下命令获取课程列表:
|
|
68
|
+
```bash
|
|
69
|
+
# 查看 course 模块的帮助和可用命令
|
|
70
|
+
soke-cli course --help
|
|
71
|
+
|
|
72
|
+
# 获取课程列表 (使用必要的参数)
|
|
73
|
+
soke-cli course +list-courses --start-time 1672502400000 --end-time 1704038400000 --page 1 --page-size 10
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 使用通用 API 命令
|
|
77
|
+
如果你需要调用的接口尚未包含在快捷命令中,可以直接使用 `api` 命令:
|
|
78
|
+
```bash
|
|
79
|
+
# 发起 GET 请求
|
|
80
|
+
soke-cli api GET /users/me
|
|
81
|
+
|
|
82
|
+
# 发起 POST 请求,携带 JSON 参数
|
|
83
|
+
soke-cli api POST /some/endpoint --data '{"key": "value"}'
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## 项目结构说明
|
|
87
|
+
|
|
88
|
+
- `cmd/`: 存放所有 CLI 子命令的定义(按业务模块划分,如 `auth`, `course`, `exam` 等)。
|
|
89
|
+
- `internal/`: 存放核心逻辑,包括认证 (`auth`)、API 客户端封装 (`client`)、配置管理 (`core`) 以及输出格式化 (`output`) 等。
|
|
90
|
+
- `shortcuts/`: 定义了各个业务模块的快捷命令元数据(API路径、参数、默认值等),供 `cmd/` 动态注册命令使用。
|
|
91
|
+
- `scripts/`: NPM 包相关的安装与运行脚本。
|
|
92
|
+
- `main.go`: CLI 的主入口文件。
|
|
93
|
+
|
|
94
|
+
## 开发与贡献
|
|
95
|
+
|
|
96
|
+
1. 依赖管理:项目使用 Go Modules,可以运行 `go mod tidy` 整理依赖。
|
|
97
|
+
2. 添加新命令:
|
|
98
|
+
- 业务接口建议在 `shortcuts/` 目录下添加对应的结构定义。
|
|
99
|
+
- 基础功能可在 `cmd/` 下新建对应包并在 `cmd/root.go` 中注册。
|
|
100
|
+
3. 测试:运行 `make test` 进行单元测试。
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sokeai/cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "授客AI官方CLI工具",
|
|
5
|
+
"bin": {
|
|
6
|
+
"soke-cli": "scripts/run.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"postinstall": "node scripts/install.js",
|
|
10
|
+
"build": "./scripts/build-binaries.sh",
|
|
11
|
+
"release": "./scripts/release.sh"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"scripts/"
|
|
15
|
+
],
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "https://codeup.aliyun.com/5edbc121d1d1abe63b55f1c7/soke/soke-cli.git"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"soke",
|
|
22
|
+
"cli",
|
|
23
|
+
"授客AI",
|
|
24
|
+
"shouke",
|
|
25
|
+
"command-line"
|
|
26
|
+
],
|
|
27
|
+
"author": "授客AI",
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=14.0.0"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# 多平台编译脚本
|
|
4
|
+
# 用于编译 soke-cli 的所有平台二进制文件
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
# 颜色输出
|
|
9
|
+
RED='\033[0;31m'
|
|
10
|
+
GREEN='\033[0;32m'
|
|
11
|
+
YELLOW='\033[1;33m'
|
|
12
|
+
NC='\033[0m' # No Color
|
|
13
|
+
|
|
14
|
+
# 获取版本号
|
|
15
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
16
|
+
echo -e "${GREEN}开始编译 soke-cli v${VERSION}${NC}"
|
|
17
|
+
|
|
18
|
+
# 编译参数
|
|
19
|
+
LDFLAGS="-s -w -X main.Version=${VERSION}"
|
|
20
|
+
|
|
21
|
+
# 创建输出目录
|
|
22
|
+
BIN_DIR="bin"
|
|
23
|
+
mkdir -p ${BIN_DIR}
|
|
24
|
+
|
|
25
|
+
# 清理旧文件
|
|
26
|
+
echo -e "${YELLOW}清理旧的编译文件...${NC}"
|
|
27
|
+
rm -f ${BIN_DIR}/soke-cli-*
|
|
28
|
+
|
|
29
|
+
# 编译函数
|
|
30
|
+
build() {
|
|
31
|
+
local GOOS=$1
|
|
32
|
+
local GOARCH=$2
|
|
33
|
+
local OUTPUT=$3
|
|
34
|
+
|
|
35
|
+
echo -e "${YELLOW}编译 ${GOOS}-${GOARCH}...${NC}"
|
|
36
|
+
|
|
37
|
+
GOOS=${GOOS} GOARCH=${GOARCH} go build \
|
|
38
|
+
-ldflags "${LDFLAGS}" \
|
|
39
|
+
-o ${BIN_DIR}/${OUTPUT} \
|
|
40
|
+
.
|
|
41
|
+
|
|
42
|
+
if [ $? -eq 0 ]; then
|
|
43
|
+
local SIZE=$(du -h ${BIN_DIR}/${OUTPUT} | cut -f1)
|
|
44
|
+
echo -e "${GREEN}✓ ${OUTPUT} (${SIZE})${NC}"
|
|
45
|
+
else
|
|
46
|
+
echo -e "${RED}✗ ${OUTPUT} 编译失败${NC}"
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# 编译所有平台
|
|
52
|
+
echo ""
|
|
53
|
+
echo "编译目标平台:"
|
|
54
|
+
|
|
55
|
+
# macOS Intel
|
|
56
|
+
build "darwin" "amd64" "soke-cli-darwin-amd64"
|
|
57
|
+
|
|
58
|
+
# macOS Apple Silicon
|
|
59
|
+
build "darwin" "arm64" "soke-cli-darwin-arm64"
|
|
60
|
+
|
|
61
|
+
# Linux x64
|
|
62
|
+
build "linux" "amd64" "soke-cli-linux-amd64"
|
|
63
|
+
|
|
64
|
+
# Linux ARM64 (可选)
|
|
65
|
+
# build "linux" "arm64" "soke-cli-linux-arm64"
|
|
66
|
+
|
|
67
|
+
# Windows x64
|
|
68
|
+
build "windows" "amd64" "soke-cli-windows-amd64.exe"
|
|
69
|
+
|
|
70
|
+
echo ""
|
|
71
|
+
echo -e "${GREEN}所有平台编译完成!${NC}"
|
|
72
|
+
echo ""
|
|
73
|
+
echo "编译产物:"
|
|
74
|
+
ls -lh ${BIN_DIR}/soke-cli-*
|
|
75
|
+
|
|
76
|
+
echo ""
|
|
77
|
+
echo -e "${YELLOW}下一步:${NC}"
|
|
78
|
+
echo "1. 创建 Git 标签: git tag v${VERSION}"
|
|
79
|
+
echo "2. 推送标签: git push origin v${VERSION}"
|
|
80
|
+
echo "3. 上传到 GitHub Releases:"
|
|
81
|
+
echo " gh release create v${VERSION} \\"
|
|
82
|
+
echo " ${BIN_DIR}/soke-cli-darwin-amd64 \\"
|
|
83
|
+
echo " ${BIN_DIR}/soke-cli-darwin-arm64 \\"
|
|
84
|
+
echo " ${BIN_DIR}/soke-cli-linux-amd64 \\"
|
|
85
|
+
echo " ${BIN_DIR}/soke-cli-windows-amd64.exe \\"
|
|
86
|
+
echo " --title \"v${VERSION}\" \\"
|
|
87
|
+
echo " --notes \"Release v${VERSION}\""
|
|
88
|
+
echo "4. 发布到 NPM: npm publish --access public"
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
const os = require('os');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const https = require('https');
|
|
5
|
+
const { execSync } = require('child_process');
|
|
6
|
+
|
|
7
|
+
const platform = os.platform();
|
|
8
|
+
const arch = os.arch();
|
|
9
|
+
const version = require('../package.json').version;
|
|
10
|
+
|
|
11
|
+
// 平台映射
|
|
12
|
+
const platformMap = {
|
|
13
|
+
'darwin': 'darwin',
|
|
14
|
+
'linux': 'linux',
|
|
15
|
+
'win32': 'windows'
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
const archMap = {
|
|
19
|
+
'x64': 'amd64',
|
|
20
|
+
'arm64': 'arm64'
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const mappedPlatform = platformMap[platform];
|
|
24
|
+
const mappedArch = archMap[arch];
|
|
25
|
+
|
|
26
|
+
if (!mappedPlatform || !mappedArch) {
|
|
27
|
+
console.error(`不支持的平台: ${platform}-${arch}`);
|
|
28
|
+
console.error('支持的平台: darwin-x64, darwin-arm64, linux-x64, windows-x64');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const binaryName = platform === 'win32' ? 'soke-cli.exe' : 'soke-cli';
|
|
33
|
+
const binaryFileName = `soke-cli-${mappedPlatform}-${mappedArch}${platform === 'win32' ? '.exe' : ''}`;
|
|
34
|
+
|
|
35
|
+
// GitHub Releases 下载地址
|
|
36
|
+
const downloadURL = `https://github.com/liuchenlong1111/soke-cli/releases/download/v${version}/${binaryFileName}`;
|
|
37
|
+
|
|
38
|
+
const binDir = path.join(__dirname, '..', 'bin');
|
|
39
|
+
const binaryPath = path.join(binDir, binaryName);
|
|
40
|
+
|
|
41
|
+
console.log(`正在为 ${mappedPlatform}-${mappedArch} 下载 soke-cli v${version}...`);
|
|
42
|
+
console.log(`下载地址: ${downloadURL}`);
|
|
43
|
+
|
|
44
|
+
// 创建 bin 目录
|
|
45
|
+
if (!fs.existsSync(binDir)) {
|
|
46
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// 下载文件
|
|
50
|
+
function downloadFile(url, dest) {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
const file = fs.createWriteStream(dest);
|
|
53
|
+
|
|
54
|
+
https.get(url, (response) => {
|
|
55
|
+
// 处理重定向
|
|
56
|
+
if (response.statusCode === 301 || response.statusCode === 302) {
|
|
57
|
+
file.close();
|
|
58
|
+
fs.unlinkSync(dest);
|
|
59
|
+
return downloadFile(response.headers.location, dest)
|
|
60
|
+
.then(resolve)
|
|
61
|
+
.catch(reject);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (response.statusCode !== 200) {
|
|
65
|
+
file.close();
|
|
66
|
+
fs.unlinkSync(dest);
|
|
67
|
+
return reject(new Error(`下载失败,HTTP 状态码: ${response.statusCode}`));
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const totalSize = parseInt(response.headers['content-length'], 10);
|
|
71
|
+
let downloadedSize = 0;
|
|
72
|
+
let lastPercent = 0;
|
|
73
|
+
|
|
74
|
+
response.on('data', (chunk) => {
|
|
75
|
+
downloadedSize += chunk.length;
|
|
76
|
+
const percent = Math.floor((downloadedSize / totalSize) * 100);
|
|
77
|
+
if (percent !== lastPercent && percent % 10 === 0) {
|
|
78
|
+
process.stdout.write(`\r下载进度: ${percent}%`);
|
|
79
|
+
lastPercent = percent;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
response.pipe(file);
|
|
84
|
+
|
|
85
|
+
file.on('finish', () => {
|
|
86
|
+
file.close();
|
|
87
|
+
console.log('\r下载完成! ');
|
|
88
|
+
resolve();
|
|
89
|
+
});
|
|
90
|
+
}).on('error', (err) => {
|
|
91
|
+
file.close();
|
|
92
|
+
fs.unlinkSync(dest);
|
|
93
|
+
reject(err);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 执行下载
|
|
99
|
+
downloadFile(downloadURL, binaryPath)
|
|
100
|
+
.then(() => {
|
|
101
|
+
// 设置可执行权限(非 Windows 平台)
|
|
102
|
+
if (platform !== 'win32') {
|
|
103
|
+
try {
|
|
104
|
+
fs.chmodSync(binaryPath, 0o755);
|
|
105
|
+
console.log('已设置可执行权限');
|
|
106
|
+
} catch (err) {
|
|
107
|
+
console.error('设置可执行权限失败:', err.message);
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
console.log('soke-cli 安装成功!');
|
|
113
|
+
console.log(`二进制文件位置: ${binaryPath}`);
|
|
114
|
+
console.log('\n使用方法:');
|
|
115
|
+
console.log(' soke-cli --help');
|
|
116
|
+
console.log(' soke-cli config init');
|
|
117
|
+
console.log(' soke-cli auth login');
|
|
118
|
+
})
|
|
119
|
+
.catch((err) => {
|
|
120
|
+
console.error('\n安装失败:', err.message);
|
|
121
|
+
console.error('\n可能的原因:');
|
|
122
|
+
console.error('1. 网络连接问题');
|
|
123
|
+
console.error('2. GitHub Releases 中不存在该版本的二进制文件');
|
|
124
|
+
console.error('3. 不支持当前平台');
|
|
125
|
+
console.error('\n请访问 https://github.com/sokeai/soke-cli/releases 手动下载');
|
|
126
|
+
process.exit(1);
|
|
127
|
+
});
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
# soke-cli 自动化发布脚本
|
|
4
|
+
# 完整流程: 编译 -> 创建标签 -> 上传 GitHub Releases -> 发布 NPM
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
# 颜色输出
|
|
9
|
+
RED='\033[0;31m'
|
|
10
|
+
GREEN='\033[0;32m'
|
|
11
|
+
YELLOW='\033[1;33m'
|
|
12
|
+
BLUE='\033[0;34m'
|
|
13
|
+
NC='\033[0m'
|
|
14
|
+
|
|
15
|
+
# 获取版本号
|
|
16
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
17
|
+
|
|
18
|
+
echo -e "${BLUE}========================================${NC}"
|
|
19
|
+
echo -e "${BLUE} soke-cli 发布脚本 v${VERSION}${NC}"
|
|
20
|
+
echo -e "${BLUE}========================================${NC}"
|
|
21
|
+
echo ""
|
|
22
|
+
|
|
23
|
+
# 检查必要的工具
|
|
24
|
+
check_tools() {
|
|
25
|
+
echo -e "${YELLOW}检查必要工具...${NC}"
|
|
26
|
+
|
|
27
|
+
if ! command -v go &> /dev/null; then
|
|
28
|
+
echo -e "${RED}错误: 未安装 Go${NC}"
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
if ! command -v gh &> /dev/null; then
|
|
33
|
+
echo -e "${RED}错误: 未安装 GitHub CLI (gh)${NC}"
|
|
34
|
+
echo "安装方法: brew install gh"
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
if ! command -v npm &> /dev/null; then
|
|
39
|
+
echo -e "${RED}错误: 未安装 npm${NC}"
|
|
40
|
+
exit 1
|
|
41
|
+
fi
|
|
42
|
+
|
|
43
|
+
echo -e "${GREEN}✓ 所有工具已就绪${NC}"
|
|
44
|
+
echo ""
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# 检查 Git 状态
|
|
48
|
+
check_git_status() {
|
|
49
|
+
echo -e "${YELLOW}检查 Git 状态...${NC}"
|
|
50
|
+
|
|
51
|
+
if [ -n "$(git status --porcelain)" ]; then
|
|
52
|
+
echo -e "${RED}错误: 工作目录有未提交的更改${NC}"
|
|
53
|
+
echo "请先提交或暂存所有更改"
|
|
54
|
+
git status --short
|
|
55
|
+
exit 1
|
|
56
|
+
fi
|
|
57
|
+
|
|
58
|
+
echo -e "${GREEN}✓ 工作目录干净${NC}"
|
|
59
|
+
echo ""
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
# 检查标签是否已存在
|
|
63
|
+
check_tag() {
|
|
64
|
+
echo -e "${YELLOW}检查标签 v${VERSION}...${NC}"
|
|
65
|
+
|
|
66
|
+
if git rev-parse "v${VERSION}" >/dev/null 2>&1; then
|
|
67
|
+
echo -e "${RED}错误: 标签 v${VERSION} 已存在${NC}"
|
|
68
|
+
echo "请更新 package.json 中的版本号"
|
|
69
|
+
exit 1
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
echo -e "${GREEN}✓ 标签不存在,可以继续${NC}"
|
|
73
|
+
echo ""
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
# 运行测试
|
|
77
|
+
run_tests() {
|
|
78
|
+
echo -e "${YELLOW}运行测试...${NC}"
|
|
79
|
+
|
|
80
|
+
if ! go test ./...; then
|
|
81
|
+
echo -e "${RED}错误: 测试失败${NC}"
|
|
82
|
+
exit 1
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
echo -e "${GREEN}✓ 测试通过${NC}"
|
|
86
|
+
echo ""
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
# 编译所有平台
|
|
90
|
+
build_binaries() {
|
|
91
|
+
echo -e "${YELLOW}编译所有平台...${NC}"
|
|
92
|
+
|
|
93
|
+
if ! ./scripts/build-binaries.sh; then
|
|
94
|
+
echo -e "${RED}错误: 编译失败${NC}"
|
|
95
|
+
exit 1
|
|
96
|
+
fi
|
|
97
|
+
|
|
98
|
+
echo -e "${GREEN}✓ 编译完成${NC}"
|
|
99
|
+
echo ""
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
# 创建并推送标签
|
|
103
|
+
create_tag() {
|
|
104
|
+
echo -e "${YELLOW}创建 Git 标签 v${VERSION}...${NC}"
|
|
105
|
+
|
|
106
|
+
git tag -a "v${VERSION}" -m "Release v${VERSION}"
|
|
107
|
+
git push github "v${VERSION}"
|
|
108
|
+
|
|
109
|
+
echo -e "${GREEN}✓ 标签已创建并推送${NC}"
|
|
110
|
+
echo ""
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
# 上传到 GitHub Releases
|
|
114
|
+
upload_github_release() {
|
|
115
|
+
echo -e "${YELLOW}上传到 GitHub Releases...${NC}"
|
|
116
|
+
|
|
117
|
+
# 生成 Release Notes(可以自定义)
|
|
118
|
+
RELEASE_NOTES="Release v${VERSION}
|
|
119
|
+
|
|
120
|
+
## 安装方法
|
|
121
|
+
|
|
122
|
+
\`\`\`bash
|
|
123
|
+
npm install -g @sokeai/cli
|
|
124
|
+
\`\`\`
|
|
125
|
+
|
|
126
|
+
## 更新日志
|
|
127
|
+
|
|
128
|
+
请查看 commit 历史了解详细更改。
|
|
129
|
+
"
|
|
130
|
+
|
|
131
|
+
gh release create "v${VERSION}" \
|
|
132
|
+
bin/soke-cli-darwin-amd64 \
|
|
133
|
+
bin/soke-cli-darwin-arm64 \
|
|
134
|
+
bin/soke-cli-linux-amd64 \
|
|
135
|
+
bin/soke-cli-windows-amd64.exe \
|
|
136
|
+
--title "v${VERSION}" \
|
|
137
|
+
--notes "${RELEASE_NOTES}"
|
|
138
|
+
|
|
139
|
+
echo -e "${GREEN}✓ GitHub Release 创建成功${NC}"
|
|
140
|
+
echo ""
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
# 发布到 NPM
|
|
144
|
+
publish_npm() {
|
|
145
|
+
echo -e "${YELLOW}发布到 NPM...${NC}"
|
|
146
|
+
|
|
147
|
+
# 检查是否已登录
|
|
148
|
+
if ! npm whoami &> /dev/null; then
|
|
149
|
+
echo -e "${RED}错误: 未登录 NPM${NC}"
|
|
150
|
+
echo "请先运行: npm login"
|
|
151
|
+
exit 1
|
|
152
|
+
fi
|
|
153
|
+
|
|
154
|
+
# 发布
|
|
155
|
+
npm publish --access public
|
|
156
|
+
|
|
157
|
+
echo -e "${GREEN}✓ NPM 包发布成功${NC}"
|
|
158
|
+
echo ""
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
# 清理编译产物
|
|
162
|
+
cleanup() {
|
|
163
|
+
echo -e "${YELLOW}清理编译产物...${NC}"
|
|
164
|
+
rm -rf bin/
|
|
165
|
+
echo -e "${GREEN}✓ 清理完成${NC}"
|
|
166
|
+
echo ""
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
# 主流程
|
|
170
|
+
main() {
|
|
171
|
+
echo -e "${BLUE}开始发布流程...${NC}"
|
|
172
|
+
echo ""
|
|
173
|
+
|
|
174
|
+
check_tools
|
|
175
|
+
check_git_status
|
|
176
|
+
check_tag
|
|
177
|
+
run_tests
|
|
178
|
+
build_binaries
|
|
179
|
+
create_tag
|
|
180
|
+
upload_github_release
|
|
181
|
+
publish_npm
|
|
182
|
+
cleanup
|
|
183
|
+
|
|
184
|
+
echo -e "${GREEN}========================================${NC}"
|
|
185
|
+
echo -e "${GREEN} 发布成功! 🎉${NC}"
|
|
186
|
+
echo -e "${GREEN}========================================${NC}"
|
|
187
|
+
echo ""
|
|
188
|
+
echo -e "版本: ${GREEN}v${VERSION}${NC}"
|
|
189
|
+
echo -e "NPM: ${BLUE}https://www.npmjs.com/package/@sokeai/cli${NC}"
|
|
190
|
+
echo -e "GitHub: ${BLUE}https://github.com/sokeai/soke-cli/releases/tag/v${VERSION}${NC}"
|
|
191
|
+
echo ""
|
|
192
|
+
echo "用户可以通过以下命令安装:"
|
|
193
|
+
echo -e "${YELLOW}npm install -g @sokeai/cli${NC}"
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
# 确认发布
|
|
197
|
+
echo -e "${YELLOW}即将发布 soke-cli v${VERSION}${NC}"
|
|
198
|
+
echo ""
|
|
199
|
+
echo "发布流程包括:"
|
|
200
|
+
echo " 1. 检查工具和 Git 状态"
|
|
201
|
+
echo " 2. 运行测试"
|
|
202
|
+
echo " 3. 编译所有平台二进制文件"
|
|
203
|
+
echo " 4. 创建 Git 标签并推送"
|
|
204
|
+
echo " 5. 上传到 GitHub Releases"
|
|
205
|
+
echo " 6. 发布到 NPM"
|
|
206
|
+
echo ""
|
|
207
|
+
read -p "确认继续? (y/N) " -n 1 -r
|
|
208
|
+
echo ""
|
|
209
|
+
|
|
210
|
+
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
211
|
+
echo "已取消发布"
|
|
212
|
+
exit 0
|
|
213
|
+
fi
|
|
214
|
+
|
|
215
|
+
echo ""
|
|
216
|
+
main
|
package/scripts/run.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
|
|
7
|
+
// 获取二进制文件路径
|
|
8
|
+
const platform = process.platform;
|
|
9
|
+
const binaryName = platform === 'win32' ? 'soke-cli.exe' : 'soke-cli';
|
|
10
|
+
const binaryPath = path.join(__dirname, '..', 'bin', binaryName);
|
|
11
|
+
|
|
12
|
+
// 检查二进制文件是否存在
|
|
13
|
+
if (!fs.existsSync(binaryPath)) {
|
|
14
|
+
console.error('错误: 未找到 soke-cli 二进制文件');
|
|
15
|
+
console.error('请尝试重新安装: npm install -g @sokeai/cli');
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// 检查二进制文件是否可执行
|
|
20
|
+
try {
|
|
21
|
+
fs.accessSync(binaryPath, fs.constants.X_OK);
|
|
22
|
+
} catch (err) {
|
|
23
|
+
// 如果不可执行,尝试设置权限
|
|
24
|
+
if (platform !== 'win32') {
|
|
25
|
+
try {
|
|
26
|
+
fs.chmodSync(binaryPath, 0o755);
|
|
27
|
+
} catch (chmodErr) {
|
|
28
|
+
console.error('错误: 无法设置二进制文件执行权限');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// 执行二进制文件,传递所有命令行参数
|
|
35
|
+
const child = spawn(binaryPath, process.argv.slice(2), {
|
|
36
|
+
stdio: 'inherit',
|
|
37
|
+
env: process.env
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// 处理子进程退出
|
|
41
|
+
child.on('exit', (code, signal) => {
|
|
42
|
+
if (signal) {
|
|
43
|
+
process.kill(process.pid, signal);
|
|
44
|
+
} else {
|
|
45
|
+
process.exit(code);
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// 处理错误
|
|
50
|
+
child.on('error', (err) => {
|
|
51
|
+
console.error('执行 soke-cli 时出错:', err.message);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
});
|