UNPKG

@winner-fed/deploy-cli

Version:

CLI tool for deploy.

721 lines (603 loc) 19 kB
# @winner-fed/deploy-cli > 一站式前端项目部署命令行工具 ## 简介 `@winner-fed/deploy-cli` 是一个集成了 SEE 平台部署包生成和 FTP/SFTP 文件上传功能的命令行工具。它简化了前端项目的部署流程,支持多种配置方式和部署场景,完美支持 monorepo 环境,让部署变得更加简单高效。 ## 特性 - 🚀 **一键部署**: 支持 SEE 包生成和 FTP 上传的一体化部署 - 📦 **SEE 平台集成**: 完整支持 SEE 平台的部署包规范 - 🌐 **FTP/SFTP 支持**: 灵活的文件传输协议支持 - 🏗️ **Monorepo 支持**: 智能识别 monorepo 环境,自动向上查找 git 仓库根目录 - ⚙️ **多配置格式**: 支持 JS、TS、JSON 等多种配置文件格式 - 🎯 **TypeScript 支持**: 完整的类型定义和智能提示 - 🔧 **灵活配置**: 支持环境变量、命令行参数等多种配置方式 - 📊 **详细日志**: 提供详细的部署过程日志和错误信息 ## 安装 ### 全局安装(推荐) ```bash npm install -g @winner-fed/deploy-cli # 或 yarn global add @winner-fed/deploy-cli # 或 pnpm add -g @winner-fed/deploy-cli ``` ### 项目内安装 ```bash npm install @winner-fed/deploy-cli --save-dev # 或 yarn add @winner-fed/deploy-cli --dev # 或 pnpm add @winner-fed/deploy-cli -D ``` ## 快速开始 ### 1. 生成 SEE 部署包 ```bash # 全局安装后 deploy-cli see # 项目内安装 npx deploy-cli see # 或 yarn deploy-cli see # 在 monorepo 子包中使用 cd packages/my-app npx deploy-cli see ``` ### 2. FTP 文件上传 ```bash # 全局安装后 deploy-cli ftp # 项目内安装 npx deploy-cli ftp # 或 yarn deploy-cli ftp # 在 monorepo 子包中使用 cd packages/my-app npx deploy-cli ftp ``` ### 3. 一键部署(SEE + FTP) ```bash deploy-cli deploy # 在 monorepo 环境中,工具会自动识别并向上查找 git 仓库根目录 # 无需额外配置即可获取正确的 git 信息 ``` ## 命令行选项 ### 通用选项 ```bash deploy-cli [command] [options] Options: --config <path> 指定配置文件路径 --help 显示帮助信息 --version 显示版本信息 ``` ### SEE 包生成 ```bash deploy-cli see [options] Options: --config <path> 指定配置文件路径 --output <dir> 指定输出目录 --type <type> 应用类型 (bizframe|subsystem) --docker 生成 Docker 容器化包 ``` ### FTP 上传 ```bash deploy-cli ftp [options] Options: --config <path> 指定配置文件路径 --host <host> FTP 服务器地址 --port <port> FTP 服务器端口 --sftp 使用 SFTP 协议 ``` ## 配置文件 `deploy-cli` 支持多种配置文件格式,会按以下优先级查找配置: 1. `deploy.config.ts` 2. `deploy.config.js` 3. `deploy.config.cjs` 4. `deploy.config.mjs` 5. `deploy.config.json` 6. `package.json` 中的 `deploy` 属性 ### 基础配置示例 ```javascript // deploy.config.js module.exports = { // 项目源码路径 source: process.cwd(), // SEE 包配置 seeConfig: { system: 'my-system', type: 'subsystem', name: 'my-app', version: '1.0.0', description: '我的应用', outputName: 'dist' }, // FTP 配置 ftpConfig: { user: 'deploy-user', password: 'your-password', host: 'your-server.com', port: 22, localPath: './dist', remotePath: '/var/www/html', include: ['*', '**/*'], exclude: ['**/*.map'], sftp: true } }; ``` ### TypeScript 配置示例 ```typescript // deploy.config.ts import type { UserConfig } from '@winner-fed/deploy-cli'; const config: UserConfig = { source: process.cwd(), seeConfig: { system: 'winner-front', type: 'bizframe', name: 'main-app', version: '2.0.0', description: '主框架应用', variables: [ { type: 'input', label: 'API 基础路径', name: 'API_BASE_URL', required: true, tooltip: '后端 API 服务地址', default: 'https://api.example.com' }, { type: 'switch', label: '启用调试模式', name: 'DEBUG_MODE', options: 'true:是;false:否', required: false, tooltip: '是否启用调试模式', default: 'false' }, { type: 'password', label: '数据库密码', name: 'DB_PASSWORD', required: true, tooltip: '数据库连接密码', default: '' }, { type: 'hidden', label: '应用版本号', name: 'APP_VERSION', required: false, tooltip: '应用内部版本号,用于系统识别', default: '1.0.0' } ], isProduction: process.env.NODE_ENV === 'production', dockerImage: 'my-app:latest' }, ftpConfig: { user: process.env.FTP_USER!, password: process.env.FTP_PASSWORD!, host: process.env.FTP_HOST!, port: parseInt(process.env.FTP_PORT || '22'), localPath: './dist', remotePath: '/usr/local/nginx/html/my-app', include: ['*', '**/*'], exclude: ['**/*.map', '**/*.log', '.DS_Store', 'Thumbs.db'], deleteRemote: true, sftp: true } }; export default config; ``` ## 配置项详细说明 ### UserConfig 接口 | 参数 | 类型 | 必填 | 默认值 | 说明 | | --------- | --------- | ---- | ------------- | ------------------ | | source | string | 否 | process.cwd() | 项目源码路径 | | seeConfig | SeeConfig | 否 | - | SEE 包配置 | | ftpConfig | FtpConfig | 否 | - | FTP 配置 | | config | string | 否 | - | 自定义配置文件路径 | ### SeeConfig 配置 | 参数 | 类型 | 必填 | 默认值 | 说明 | | -------------- | ------------------------- | ---- | ------------------------------ | -------------------------- | | system | string | 否 | 'winner-front' | 系统类型,SEE 平台分组维度 | | type | 'bizframe' \| 'subsystem' | 否 | 'bizframe' | 应用类型 | | name | string | 否 | package.json.name | 发布物名称 | | version | string | 否 | package.json.version | 发布包版本 | | description | string | 否 | package.json.description | 发布包描述 | | appType | string | 否 | name | 发布物类型 | | group | string | 否 | 'bizframe' | 应用分组 | | configName | string | 否 | 'config.local' | 配置文件名称(不含.js) | | outputName | string | 否 | 'dist' | 输出目录名称 | | templateFunc | function | 否 | - | 自定义变量配置文件生成函数 | | variables | Array<variables> | 否 | [] | deploy.xml 模板变量 | | copyFiles | string[] | 否 | [] | 需要直接拷贝的文件列表 | | seePackageName | string | 否 | `${system}-${name}-${version}` | SEE 包名称 | | seePackageType | 'web' \| 'docker' | 否 | 'web' | SEE 包类型 | | isDocker | boolean | 否 | false | 是否为 Docker 包 | | dockerImage | string | 否 | - | Docker 镜像名 | | scriptsType | 'python' \| 'bash' | 否 | 'python' | 脚本类型 | | buildVersion | string | 否 | - | 构建版本 | | isProduction | boolean | 否 | false | 是否为生产包 | ### FtpConfig 配置 | 参数 | 类型 | 必填 | 默认值 | 说明 | | ------------ | -------- | ---- | ------ | ---------------------- | | user | string | 是 | - | 服务器登录用户名 | | password | string | 是 | - | 服务器登录密码 | | host | string | 是 | - | 服务器主机地址 | | port | number | 是 | - | 服务器端口 | | localPath | string | 是 | - | 本地文件路径 | | remotePath | string | 是 | - | 远程服务器路径 | | include | string[] | 是 | - | 包含的文件模式 | | exclude | string[] | 否 | [] | 排除的文件模式 | | deleteRemote | boolean | 否 | false | 上传前是否删除远程文件 | | forcePasv | boolean | 否 | true | 是否强制被动模式 | | sftp | boolean | 否 | false | 是否使用 SFTP | ### 模板变量配置 ```typescript interface variables { type: | 'input' | 'select' | 'editor' | 'switch' | 'smallfile' | 'table' | 'mselect' | 'switchForm' | 'complexSelect' | 'division' | 'password' | 'hidden'; label: string; // 控件标签 name: string; // 变量名称 options?: string; // 选项配置(select 类型使用) required: boolean; // 是否必填 fold?: boolean; // 是否可折叠 children?: variables[]; // 子控件 tooltip: string; // 提示信息 default: string; // 默认值 } ``` ## 使用场景 ### 1. 前端项目完整部署 ```javascript // deploy.config.js module.exports = { seeConfig: { system: 'my-system', type: 'subsystem', name: 'user-management', version: '1.0.0', description: '用户管理系统', variables: [ { type: 'input', label: 'API 地址', name: 'API_URL', required: true, tooltip: '后端 API 服务地址', default: 'https://api.example.com' }, { type: 'password', label: '数据库密码', name: 'DB_PASSWORD', required: true, tooltip: '数据库连接密码', default: '' }, { type: 'hidden', label: '应用版本号', name: 'APP_VERSION', required: false, tooltip: '应用内部版本号,用于系统识别', default: '1.0.0' } ], isProduction: true }, ftpConfig: { user: 'deploy', password: process.env.DEPLOY_PASSWORD, host: 'prod.example.com', port: 22, localPath: './dist', remotePath: '/var/www/html/user-management', include: ['*', '**/*'], exclude: ['**/*.map', '**/*.log'], deleteRemote: true, sftp: true } }; ``` ### 2. 多环境部署配置 ```javascript // deploy.config.js const env = process.env.NODE_ENV || 'development'; const environments = { development: { host: 'dev.example.com', remotePath: '/var/www/dev' }, staging: { host: 'staging.example.com', remotePath: '/var/www/staging' }, production: { host: 'prod.example.com', remotePath: '/var/www/prod' } }; module.exports = { seeConfig: { system: 'my-system', type: 'subsystem', isProduction: env === 'production' }, ftpConfig: { user: 'deploy', password: process.env.DEPLOY_PASSWORD, host: environments[env].host, port: 22, localPath: './dist', remotePath: environments[env].remotePath, include: ['*', '**/*'], exclude: ['**/*.map'], deleteRemote: true, sftp: true } }; ``` ### 3. Docker 容器化部署 ```javascript // deploy.config.js module.exports = { seeConfig: { system: 'container-system', type: 'subsystem', name: 'my-app', version: '1.0.0', seePackageType: 'docker', isDocker: true, dockerImage: 'my-app:1.0.0', scriptsType: 'bash' } }; ``` ### 4. Monorepo 环境部署 ```javascript // packages/my-app/deploy.config.js module.exports = { // 工具会自动从子包目录向上查找 git 仓库根目录 // 例如:从 /monorepo/packages/my-app 向上查找到 /monorepo/.git source: __dirname, // 子包目录 seeConfig: { system: 'monorepo-system', type: 'subsystem', name: 'my-app', version: '1.0.0', description: 'Monorepo 中的子应用', outputName: 'dist', // 工具会自动获取正确的 git hash,即使在子包中运行 isProduction: process.env.NODE_ENV === 'production' }, ftpConfig: { user: process.env.FTP_USER, password: process.env.FTP_PASSWORD, host: 'example.com', port: 22, localPath: './dist', remotePath: '/var/www/html/my-app', include: ['*', '**/*'], exclude: ['**/*.map'], sftp: true } }; ``` ## 在 package.json 中配置 ```json { "name": "my-app", "version": "1.0.0", "scripts": { "build": "npm run build:prod", "deploy:see": "deploy-cli see", "deploy:ftp": "deploy-cli ftp", "deploy": "npm run build && deploy-cli see && deploy-cli ftp" }, "deploy": { "seeConfig": { "system": "my-system", "type": "subsystem", "outputName": "dist" }, "ftpConfig": { "user": "deploy", "host": "example.com", "port": 22, "localPath": "./dist", "remotePath": "/var/www/html", "include": ["*", "**/*"], "exclude": ["**/*.map"], "sftp": true } } } ``` ## 环境变量配置 为了安全起见,建议将敏感信息通过环境变量配置: ```bash # .env 文件 FTP_USER=deploy-user FTP_PASSWORD=your-secure-password FTP_HOST=your-server.com FTP_PORT=22 NODE_ENV=production ``` ```javascript // deploy.config.js require('dotenv').config(); module.exports = { ftpConfig: { user: process.env.FTP_USER, password: process.env.FTP_PASSWORD, host: process.env.FTP_HOST // ... 其他配置 } }; ``` ## 自定义配置文件路径 ```bash # 使用自定义配置文件 deploy-cli see --config ./build/deploy.config.js deploy-cli ftp --config ./config/production.js # 使用相对路径 deploy-cli see --config ../shared/deploy.config.js ``` ## 错误处理和调试 ### 常见错误及解决方案 1. **配置文件未找到** ```bash Error: Configuration file not found ``` 解决方案:确保配置文件存在且路径正确 2. **SEE 包生成失败** ```bash Error: Failed to generate SEE package ``` 解决方案:检查 `outputName` 目录是否存在,确保有足够的磁盘空间 3. **FTP 连接失败** ```bash Error: FTP connection failed ``` 解决方案:检查网络连接、服务器地址、端口和凭据 ### 调试模式 ```bash # 启用详细日志 DEBUG=deploy-cli* deploy-cli see DEBUG=deploy-cli* deploy-cli ftp ``` ## 最佳实践 ### 1. 配置管理 ```javascript // 使用配置工厂函数 function createConfig(env) { const baseConfig = { seeConfig: { system: 'my-system', type: 'subsystem' } }; const envConfigs = { development: { ftpConfig: { host: 'dev.example.com', deleteRemote: false } }, production: { ftpConfig: { host: 'prod.example.com', deleteRemote: true } } }; return { ...baseConfig, ...envConfigs[env] }; } module.exports = createConfig(process.env.NODE_ENV || 'development'); ``` ### 2. 安全配置 ```javascript // 使用环境变量和配置验证 const requiredEnvVars = ['FTP_USER', 'FTP_PASSWORD', 'FTP_HOST']; const missingVars = requiredEnvVars.filter((varName) => !process.env[varName]); if (missingVars.length > 0) { throw new Error(`Missing required environment variables: ${missingVars.join(', ')}`); } module.exports = { ftpConfig: { user: process.env.FTP_USER, password: process.env.FTP_PASSWORD, host: process.env.FTP_HOST // ... 其他配置 } }; ``` ### 3. 脚本集成 ```json { "scripts": { "build": "npm run build:prod", "deploy:dev": "NODE_ENV=development deploy-cli deploy", "deploy:staging": "NODE_ENV=staging deploy-cli deploy", "deploy:prod": "NODE_ENV=production deploy-cli deploy", "deploy": "npm run build && npm run deploy:prod" } } ``` ### 4. Monorepo 环境最佳实践 ```json // packages/my-app/package.json { "name": "@my-org/my-app", "version": "1.0.0", "scripts": { "build": "vite build", "deploy:dev": "NODE_ENV=development deploy-cli deploy", "deploy:prod": "NODE_ENV=production deploy-cli deploy" } } ``` ```javascript // packages/my-app/deploy.config.js module.exports = { // 当前子包目录 source: __dirname, seeConfig: { system: 'my-system', type: 'subsystem', name: 'my-app', version: require('./package.json').version, description: require('./package.json').description, outputName: 'dist', // 工具会自动向上查找 git 仓库,获取正确的 git hash isProduction: process.env.NODE_ENV === 'production' }, ftpConfig: { // 使用环境变量配置敏感信息 user: process.env.FTP_USER, password: process.env.FTP_PASSWORD, host: process.env.FTP_HOST, port: parseInt(process.env.FTP_PORT || '22'), localPath: './dist', remotePath: `/var/www/html/${require('./package.json').name}`, include: ['*', '**/*'], exclude: ['**/*.map', '**/*.log'], sftp: true } }; ``` ## 注意事项 1. **配置文件优先级**: 命令行 `--config` 参数 > 项目根目录配置文件 > package.json 2. **环境变量**: 建议使用环境变量管理敏感信息 3. **路径处理**: 所有路径都相对于 `source` 配置的目录 4. **Monorepo 支持**: 工具会自动向上查找 `.git` 目录,支持在子包中运行并正确获取 git 信息 5. **Docker 部署**: 使用 Docker 模式时,确保镜像已构建并推送到仓库 6. **网络连接**: FTP/SFTP 部署需要确保网络连接和防火墙配置正确 ## 更新日志 ### 最新更新 - **Monorepo 支持增强**: 新增智能 git 目录查找功能,支持在 monorepo 子包中正确获取 git 信息 - **类型安全改进**: 修复了 TypeScript 类型错误,提供更好的类型支持 - **API 改进**: 将部分内部工具函数暴露为公共 API,方便扩展使用 详细的更新日志请查看 [CHANGELOG.md](./CHANGELOG.md)。 ## 许可证 ISC License ## 贡献 欢迎提交 Issue 和 Pull Request 来改进这个项目。 ## 相关项目 - [@winner-fed/winner-deploy](../see-deploy/README.md) - SEE 平台部署包生成工具 - [@winner-fed/ftp-deploy](../ftp-deploy/README.md) - FTP/SFTP 文件上传工具