Files
autoAiWorkSys/_doc/发布的接口文档.md
张成 0e334116b6 1
2025-11-28 09:50:38 +08:00

15 KiB
Raw Blame History

发布脚本使用说明

📋 概述

发布脚本 (scripts/publish.js) 用于自动化应用的构建和发布流程,包括:

  1. 清理构建目录
  2. 构建应用NSIS 或便携版)
  3. 调用接口创建版本记录
  4. 上传压缩包到 OSS

🚀 快速开始

安装依赖

确保已安装 form-data 依赖:

npm install form-data --save-dev

基本使用

# 发布 NSIS 安装包(默认)
npm run publish

# 或直接运行脚本
node scripts/publish.js

📝 命令选项

构建类型

# 发布 NSIS 安装包
npm run publish:nsis
# 或
node scripts/publish.js --type nsis

# 发布便携版
npm run publish:portable
# 或
node scripts/publish.js --type portable

发布说明

node scripts/publish.js --notes "修复了若干bug优化了性能"

强制更新

node scripts/publish.js --force

跳过步骤

# 仅上传已构建的文件(跳过构建)
node scripts/publish.js --skip-build

# 仅构建不上传
node scripts/publish.js --skip-upload

查看帮助

node scripts/publish.js --help

🔧 配置要求

1. 配置文件

确保 config/appConfig.js 中包含有效的配置:

module.exports = {
  api_urls: {
    dev: "http://work.light120.com/api",
    prod: "http://work.light120.com/api"
  },
  token: "your-token-here",  // 必须配置有效的 token
  // ...
};

2. API 接口

脚本需要以下 API 接口:

接口 1创建版本记录

  • 接口地址: POST /api/version/create
  • 请求头:
    Content-Type: application/json
    Authorization: Bearer ${token}
    
  • 请求参数:
    {
      "version": "1.0.0",              // 必填版本号x.y.z 格式)
      "platform": "win32",             // 必填平台类型win32/darwin/linux
      "arch": "x64",                   // 必填架构类型x64/ia32/arm64
      "download_url": "https://...",   // 必填:下载地址(上传后更新)
      "file_path": "/path/to/file",    // 必填:服务器文件路径
      "file_size": 12345678,           // 可选:文件大小(字节),不提供会自动计算
      "file_hash": "sha256-hash",      // 可选SHA256 哈希值,不提供会自动计算
      "release_notes": "发布说明",      // 可选:更新日志
      "force_update": 0,                // 可选是否强制更新1:是 0:否),默认 0
      "status": 1                       // 可选状态1:启用 0:禁用),默认 1
    }
    
  • 响应示例:
    {
      "code": 0,
      "message": "版本创建成功",
      "data": {
        "id": 123,
        "version": "1.0.0",
        "platform": "win32",
        "arch": "x64",
        "download_url": "https://oss.example.com/path/to/file.exe",
        "file_path": "/path/to/file.exe",
        "file_size": 12345678,
        "file_hash": "sha256-hash-value",
        "release_notes": "发布说明",
        "force_update": 0,
        "status": 1,
        "create_time": "2024-01-01 12:00:00"
      }
    }
    
  • 错误响应:
    {
      "code": 400,
      "message": "版本号不能为空"  // 或其他错误信息
    }
    
  • 注意事项:
    • 版本号格式必须为 x.y.z1.0.0
    • 平台类型必须为:win32darwinlinux
    • 架构类型必须为:x64ia32arm64
    • 如果版本已存在(相同 version + platform + arch会返回错误
    • 如果提供了 file_path 但未提供 file_sizefile_hash,接口会自动计算

接口 2上传文件到 OSS

  • 接口地址: POST /api/file/upload_version
  • 请求头:
    Content-Type: multipart/form-data
    Authorization: Bearer ${token}
    
  • 请求参数Form Data:
    参数名 类型 必填 说明
    file File 文件内容(二进制)
    version String 版本号1.0.0
    platform String 平台类型win32/darwin/linux
    arch String 架构类型x64/ia32/arm64
    file_hash String SHA256 哈希值
    file_size Number 文件大小(字节)
    version_id Number 版本记录 ID如果已创建版本记录
    build_type String 构建类型nsis/portable
  • 请求示例(使用 form-data:
    const FormData = require('form-data');
    const fs = require('fs');
    
    const form = new FormData();
    form.append('file', fs.createReadStream('./dist/app.exe'));
    form.append('version', '1.0.0');
    form.append('platform', 'win32');
    form.append('arch', 'x64');
    form.append('file_hash', 'sha256-hash-value');
    form.append('file_size', 12345678);
    form.append('version_id', 123);  // 可选
    
    // 发送请求
    form.submit('http://api.example.com/api/file/upload_version', {
      headers: {
        'Authorization': `Bearer ${token}`
      }
    }, callback);
    
  • 响应示例:
    {
      "code": 0,
      "message": "文件上传成功",
      "data": {
        "download_url": "https://oss.example.com/versions/win32/x64/app-1.0.0.exe",
        "file_path": "versions/win32/x64/app-1.0.0.exe",
        "oss_path": "https://oss.example.com/versions/win32/x64/app-1.0.0.exe",
        "file_size": 12345678,
        "file_hash": "sha256-hash-value"
      }
    }
    
  • 错误响应:
    {
      "code": 400,
      "message": "文件上传失败:文件大小不匹配"  // 或其他错误信息
    }
    
  • 注意事项:
    • 文件会按照 versions/{platform}/{arch}/{filename} 的路径结构上传到 OSS
    • 上传前会验证文件哈希值,确保文件完整性
    • 上传成功后,建议调用 /version/update 接口更新版本记录的下载地址
    • 大文件上传建议设置较长的超时时间(建议 10 分钟以上)

接口 3更新版本下载地址可选

  • 接口地址: POST /api/version/update
  • 请求头:
    Content-Type: application/json
    Authorization: Bearer ${token}
    
  • 请求参数:
    {
      "id": 123,                        // 必填:版本记录 ID
      "download_url": "https://...",    // 可选:下载地址
      "file_path": "/path/to/file",    // 可选:文件路径
      "file_hash": "sha256-hash",       // 可选:文件哈希值
      "file_size": 12345678,            // 可选:文件大小
      "release_notes": "更新说明",      // 可选:更新日志
      "force_update": 1,                // 可选:是否强制更新
      "status": 1                       // 可选:状态
    }
    
  • 响应示例:
    {
      "code": 0,
      "message": "版本更新成功",
      "data": {
        "id": 123,
        "version": "1.0.0",
        "download_url": "https://oss.example.com/path/to/file.exe",
        // ... 其他字段
      }
    }
    
  • 使用场景:
    • 文件上传成功后,更新版本记录的下载地址
    • 修改版本的发布说明或强制更新标志
    • 启用或禁用某个版本

📦 发布流程

  1. 清理构建目录

    • 删除 dist 目录及其所有内容
  2. 构建应用

    • 根据构建类型执行 electron-builder
    • NSIS: electron-builder --win nsis
    • Portable: electron-builder --win portable
  3. 查找构建产物

    • dist 目录中查找 .exe 文件
    • 按文件大小排序,优先处理主安装包
  4. 创建版本记录

    • 调用 POST /api/version/create 接口
    • 传递版本信息、平台、架构等
    • 获取版本记录 ID用于后续更新
  5. 上传文件到 OSS

    • 计算文件 SHA256 哈希值
    • 使用 multipart/form-data 格式调用 POST /api/file/upload_version 接口
    • 传递文件、版本信息、哈希值等参数
    • 获取上传后的下载地址
  6. 更新版本记录

    • 使用获取到的下载地址调用 POST /api/version/update 接口
    • 更新版本记录的 download_urlfile_path 字段

⚠️ 注意事项

  1. Token 配置

    • 确保 config/appConfig.js 中有有效的 token
    • Token 用于 API 认证,格式为 Bearer ${token}
    • 所有接口请求都需要在请求头中包含 Authorization: Bearer ${token}
  2. 接口路径

    • 所有接口路径前缀为 /api
    • 完整路径示例:
      • 创建版本:POST http://api.example.com/api/version/create
      • 上传文件:POST http://api.example.com/api/file/upload_version
      • 更新版本:POST http://api.example.com/api/version/update
  3. 文件大小

    • 大文件上传可能需要较长时间
    • 脚本默认超时时间为 10 分钟600000ms
    • 建议大文件(>100MB增加超时时间到 30 分钟
  4. 网络连接

    • 确保能够访问 API 服务器和 OSS
    • 上传大文件时建议使用稳定的网络连接
    • 建议在网络稳定的环境下执行发布流程
  5. 版本号

    • 版本号从 package.jsonversion 字段读取
    • 发布前确保版本号已更新
    • 版本号格式必须符合 x.y.z 格式1.0.0
  6. 构建产物

    • 脚本会自动查找 dist 目录中的 .exe 文件
    • 排除 builderhelper 相关的辅助文件
    • 确保构建产物文件名清晰,便于识别
  7. 文件哈希验证

    • 上传前必须计算文件的 SHA256 哈希值
    • 上传接口会验证文件哈希,确保文件完整性
    • 哈希值不匹配会导致上传失败
  8. 接口调用顺序

    • 建议先创建版本记录(获取 version_id
    • 然后上传文件(可传递 version_id
    • 最后更新版本记录的下载地址
    • 也可以先上传文件,再创建版本记录并更新下载地址

🔍 故障排查

问题:上传失败

可能原因:

  • Token 无效或过期
  • API 接口地址不正确
  • 网络连接问题
  • 文件过大,超时

解决方法:

  1. 检查 config/appConfig.js 中的 token 是否有效
  2. 检查 API 地址是否正确
  3. 检查网络连接
  4. 如果文件很大,可以增加超时时间

问题:构建失败

可能原因:

  • 缺少依赖
  • electron-builder 配置错误
  • 磁盘空间不足

解决方法:

  1. 运行 npm install 安装所有依赖
  2. 检查 package.json 中的 build 配置
  3. 确保有足够的磁盘空间

问题:找不到构建产物

可能原因:

  • 构建未成功完成
  • 构建产物在其他位置

解决方法:

  1. 检查构建日志,确认构建成功
  2. 手动检查 dist 目录
  3. 使用 --skip-build 选项,手动指定文件路径(需要修改脚本)

📝 示例

完整发布流程

# 1. 更新版本号(在 package.json 中)
# "version": "1.0.1"

# 2. 发布
npm run publish -- --notes "新功能:支持自动投递简历" --force

仅上传已构建的文件

# 1. 手动构建
npm run build:nsis

# 2. 仅上传
node scripts/publish.js --skip-build

测试发布(不上传)

# 构建并创建版本记录,但不上传文件
node scripts/publish.js --skip-upload

💻 接口调用示例

Node.js 示例代码

1. 创建版本记录

const axios = require('axios');
const crypto = require('crypto');
const fs = require('fs');

async function createVersion() {
  const filePath = './dist/app-1.0.0.exe';
  const stats = fs.statSync(filePath);
  const fileSize = stats.size;
  
  // 计算文件哈希
  const fileBuffer = fs.readFileSync(filePath);
  const fileHash = crypto.createHash('sha256').update(fileBuffer).digest('hex');
  
  const response = await axios.post('http://api.example.com/api/version/create', {
    version: '1.0.0',
    platform: 'win32',
    arch: 'x64',
    download_url: '',  // 上传后更新
    file_path: filePath,
    file_size: fileSize,
    file_hash: fileHash,
    release_notes: '修复了若干bug优化了性能',
    force_update: 0,
    status: 1
  }, {
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    }
  });
  
  return response.data.data;  // 返回版本记录,包含 id
}

2. 上传文件到 OSS

const FormData = require('form-data');
const axios = require('axios');
const fs = require('fs');
const crypto = require('crypto');

async function uploadVersionFile(versionId) {
  const filePath = './dist/app-1.0.0.exe';
  const stats = fs.statSync(filePath);
  const fileSize = stats.size;
  
  // 计算文件哈希
  const fileBuffer = fs.readFileSync(filePath);
  const fileHash = crypto.createHash('sha256').update(fileBuffer).digest('hex');
  
  // 创建 FormData
  const form = new FormData();
  form.append('file', fs.createReadStream(filePath));
  form.append('version', '1.0.0');
  form.append('platform', 'win32');
  form.append('arch', 'x64');
  form.append('file_hash', fileHash);
  form.append('file_size', fileSize);
  if (versionId) {
    form.append('version_id', versionId);
  }
  
  const response = await axios.post('http://api.example.com/api/file/upload_version', form, {
    headers: {
      'Authorization': `Bearer ${token}`,
      ...form.getHeaders()
    },
    maxContentLength: Infinity,
    maxBodyLength: Infinity,
    timeout: 600000  // 10 分钟超时
  });
  
  return response.data.data;  // 返回上传结果,包含 download_url
}

3. 更新版本下载地址

async function updateVersionDownloadUrl(versionId, downloadUrl, fileHash) {
  const response = await axios.post('http://api.example.com/api/version/update', {
    id: versionId,
    download_url: downloadUrl,
    file_hash: fileHash
  }, {
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    }
  });
  
  return response.data.data;
}

4. 完整发布流程示例

async function publishVersion() {
  try {
    // 1. 创建版本记录
    console.log('创建版本记录...');
    const version = await createVersion();
    console.log('版本记录创建成功ID:', version.id);
    
    // 2. 上传文件
    console.log('上传文件到 OSS...');
    const uploadResult = await uploadVersionFile(version.id);
    console.log('文件上传成功,下载地址:', uploadResult.download_url);
    
    // 3. 更新版本下载地址
    console.log('更新版本下载地址...');
    await updateVersionDownloadUrl(version.id, uploadResult.download_url, uploadResult.file_hash);
    console.log('版本发布完成!');
    
  } catch (error) {
    console.error('发布失败:', error.response?.data || error.message);
    throw error;
  }
}

cURL 示例

创建版本记录

curl -X POST http://api.example.com/api/version/create \
  -H "Authorization: Bearer your-token-here" \
  -H "Content-Type: application/json" \
  -d '{
    "version": "1.0.0",
    "platform": "win32",
    "arch": "x64",
    "download_url": "",
    "file_path": "/path/to/file.exe",
    "file_size": 12345678,
    "file_hash": "sha256-hash-value",
    "release_notes": "发布说明",
    "force_update": 0,
    "status": 1
  }'

上传文件

curl -X POST http://api.example.com/api/file/upload_version \
  -H "Authorization: Bearer your-token-here" \
  -F "file=@./dist/app-1.0.0.exe" \
  -F "version=1.0.0" \
  -F "platform=win32" \
  -F "arch=x64" \
  -F "file_hash=sha256-hash-value" \
  -F "file_size=12345678" \
  -F "version_id=123"

🔗 相关文档