mirror of
https://git.bjxgj.com/xgj/xgj-actions.git
synced 2025-10-14 06:33:37 +08:00
525 lines
14 KiB
Markdown
525 lines
14 KiB
Markdown
# Web 项目发布构建 Action
|
||
|
||
[](https://github.com/features/actions)
|
||
|
||
自动化 Web 项目发布流程的 GitHub Action,专注于版本管理和发布核心功能,智能处理各种版本格式。
|
||
|
||
## 功能特性
|
||
|
||
- 🚀 **自动化发布**: 支持任意发布命令进行版本管理和发布
|
||
- 🌍 **环境变量支持**: 支持传递任意数量的环境变量给发布命令
|
||
- 📦 **智能版本处理**: 自动获取版本号,确保输出格式一致(无 `v` 前缀)
|
||
- 📊 **状态监控**: 实时监控发布状态,支持成功/失败状态输出和退出码
|
||
- 🔧 **简洁配置**: 最小化配置,专注于发布核心功能
|
||
- ✅ **灵活使用**: 可配置发布命令,适应不同项目需求
|
||
- 🛡️ **错误控制**: 可配置发布失败时的行为(中断或继续)
|
||
|
||
## 快速开始
|
||
|
||
### 基础用法
|
||
|
||
```yaml
|
||
- name: 发布Web项目
|
||
uses: actions/xgj/release-web@main
|
||
env:
|
||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||
```
|
||
|
||
### 使用环境变量
|
||
|
||
```yaml
|
||
- name: 发布Web项目
|
||
uses: actions/xgj/release-web@main
|
||
env:
|
||
# 🌍 可以传递任意数量的环境变量给发布命令
|
||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||
APP_ENV: production
|
||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||
SENTRY_DSN: ${{ vars.SENTRY_DSN }}
|
||
SENTRY_VITE: true
|
||
BUILD_NUMBER: ${{ github.run_number }}
|
||
CUSTOM_CONFIG: "your-value"
|
||
FEATURE_FLAG: ${{ github.ref == 'refs/heads/main' }}
|
||
# ... 更多任意环境变量
|
||
```
|
||
|
||
### 完整示例
|
||
|
||
```yaml
|
||
- name: 发布Web项目
|
||
uses: actions/xgj/release-web@main
|
||
with:
|
||
release-command: "npm run release -- --release -V"
|
||
env:
|
||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||
APP_ENV: "production"
|
||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||
SENTRY_DSN: ${{ vars.SENTRY_DSN }}
|
||
SENTRY_VITE: "true"
|
||
```
|
||
|
||
### 自定义版本文件路径
|
||
|
||
```yaml
|
||
- name: 发布Web项目
|
||
uses: actions/xgj/release-web@main
|
||
with:
|
||
version-file: "./dist/version.txt" # 自定义版本文件位置
|
||
env:
|
||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||
```
|
||
|
||
### 版本格式处理
|
||
|
||
Action 自动处理各种版本格式,确保输出一致:
|
||
|
||
```yaml
|
||
# 输入可能的格式:
|
||
# - 版本文件: "v1.2.3" 或 "1.2.3"
|
||
# - Git tag: "v1.2.3" 或 "1.2.3"
|
||
# - package.json: "v1.2.3" 或 "1.2.3"
|
||
# - 提交信息: "release: v1.2.3" 或 "release: 1.2.3"
|
||
|
||
# 输出始终为: "v1.2.3" (统一添加 v 前缀)
|
||
# 带横线版本: "v1-2-3" (保持 v 前缀)
|
||
```
|
||
|
||
## 输入参数
|
||
|
||
| 参数名 | 描述 | 必需 | 默认值 |
|
||
| ----------------- | ---------------------------- | ---- | --------------------------------- |
|
||
| `release-command` | 发布命令 | ❌ | `npm run release -- --release -V` |
|
||
| `node-debug` | 是否启用 Node.js 调试模式 | ❌ | `false` |
|
||
| `version-file` | 自定义版本文件路径 | ❌ | `/tmp/last-version` |
|
||
| `fail-on-error` | 发布失败时是否让 action 失败 | ❌ | `true` |
|
||
|
||
## 环境变量支持
|
||
|
||
Action 支持通过 `env` 传递**任意数量**的环境变量给发布命令,这些环境变量会自动传递给 `npm run release` 或其他发布命令:
|
||
|
||
```yaml
|
||
- uses: actions/xgj/release-web@main
|
||
env:
|
||
# 🌍 任意环境变量都会自动传递给发布命令
|
||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||
APP_ENV: production
|
||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_TOKEN }}
|
||
CUSTOM_VAR: "your-value"
|
||
BUILD_NUMBER: ${{ github.run_number }}
|
||
FEATURE_FLAG: ${{ github.ref == 'refs/heads/main' }}
|
||
# ... 更多任意变量
|
||
```
|
||
|
||
### 常用环境变量示例
|
||
|
||
| 环境变量名 | 描述 | 示例值 |
|
||
| ------------------- | ---------------- | ----------------------------- |
|
||
| `GITEA_TOKEN` | Gitea 访问令牌 | `${{ secrets.GITEA_TOKEN }}` |
|
||
| `APP_ENV` | 应用环境 | `production` |
|
||
| `SENTRY_AUTH_TOKEN` | Sentry 认证令牌 | `${{ secrets.SENTRY_TOKEN }}` |
|
||
| `SENTRY_DSN` | Sentry DSN 配置 | `${{ vars.SENTRY_DSN }}` |
|
||
| `SENTRY_VITE` | 是否启用 Sentry | `true` |
|
||
| `NODE_DEBUG` | Node.js 调试模式 | `release-it:*` |
|
||
| `BUILD_NUMBER` | 构建编号 | `${{ github.run_number }}` |
|
||
|
||
## 输出参数
|
||
|
||
| 参数名 | 描述 |
|
||
| ------------------- | -------------------------------------- |
|
||
| `version` | 发布的版本号(带 v 前缀) |
|
||
| `version-with-dash` | 版本号(带 v 前缀,点号替换为横线) |
|
||
| `release-status` | 发布命令执行状态 (`success`/`failure`) |
|
||
| `exit-code` | 发布命令退出码(仅在失败时有值) |
|
||
|
||
## 使用场景
|
||
|
||
### 1. 基础发布流程
|
||
|
||
适用于简单的 Web 项目发布:
|
||
|
||
```yaml
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: 设置环境
|
||
uses: actions/xgj/setup-env@main
|
||
with:
|
||
docker-password: ${{ secrets.DOCKER_PASSWORD }}
|
||
|
||
- name: 安装依赖
|
||
uses: actions/xgj/npm-install@main
|
||
|
||
- name: 发布项目
|
||
uses: actions/xgj/release-web@main
|
||
env:
|
||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||
```
|
||
|
||
### 2. 完整 CI/CD 流程
|
||
|
||
包含完整的构建、测试、发布流程:
|
||
|
||
```yaml
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: 设置构建环境
|
||
uses: actions/xgj/setup-env@main
|
||
with:
|
||
docker-password: ${{ secrets.DOCKER_PASSWORD }}
|
||
kube-config: ${{ secrets.KUBE_CONFIG }}
|
||
|
||
- name: 安装依赖
|
||
uses: actions/xgj/npm-install@main
|
||
with:
|
||
package-manager: "pnpm"
|
||
|
||
- name: 运行测试
|
||
run: npm run test
|
||
|
||
- name: 发布构建
|
||
id: release
|
||
uses: actions/xgj/release-web@main
|
||
env:
|
||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||
APP_ENV: ${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}
|
||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||
SENTRY_DSN: ${{ vars.SENTRY_DSN }}
|
||
SENTRY_VITE: "true"
|
||
|
||
- name: 部署到Kubernetes
|
||
run: |
|
||
kubectl set image deployment/web-app web-app=docker-registry.bjxgj.com/${{ github.event.repository.name }}:${{ steps.release.outputs.version }}
|
||
```
|
||
|
||
### 3. 多环境发布
|
||
|
||
支持不同环境的差异化配置:
|
||
|
||
```yaml
|
||
strategy:
|
||
matrix:
|
||
environment: [staging, production]
|
||
include:
|
||
- environment: staging
|
||
dockerfile: "./container/dev/Dockerfile"
|
||
app-env: "staging"
|
||
- environment: production
|
||
dockerfile: "./container/prod/Dockerfile"
|
||
app-env: "production"
|
||
|
||
steps:
|
||
- name: 发布到 ${{ matrix.environment }}
|
||
uses: actions/xgj/release-web@main
|
||
env:
|
||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||
APP_ENV: ${{ matrix.app_env }}
|
||
```
|
||
|
||
### 4. 状态检查和错误处理
|
||
|
||
演示如何处理发布状态和错误:
|
||
|
||
```yaml
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: 发布项目
|
||
id: release
|
||
uses: actions/xgj/release-web@main
|
||
with:
|
||
fail-on-error: false # 发布失败时不中断 workflow
|
||
env:
|
||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||
|
||
# 总是执行的清理步骤
|
||
- name: 清理临时文件
|
||
if: always()
|
||
run: |
|
||
echo "清理临时文件..."
|
||
rm -rf temp/ dist/temp/
|
||
|
||
# 根据发布状态执行不同操作
|
||
- name: 处理发布结果
|
||
if: always()
|
||
run: |
|
||
echo "发布状态: ${{ steps.release.outputs.release-status }}"
|
||
|
||
if [[ "${{ steps.release.outputs.release-status }}" == "success" ]]; then
|
||
echo "✅ 发布成功,版本: ${{ steps.release.outputs.version }}"
|
||
echo "开始部署流程..."
|
||
else
|
||
echo "❌ 发布失败,退出码: ${{ steps.release.outputs.exit-code }}"
|
||
echo "发送失败通知..."
|
||
# 这里可以添加通知逻辑
|
||
fi
|
||
|
||
# 只在成功时执行的部署步骤
|
||
- name: 部署到生产环境
|
||
if: steps.release.outputs.release-status == 'success'
|
||
run: |
|
||
echo "部署版本 ${{ steps.release.outputs.version }} 到生产环境"
|
||
kubectl set image deployment/app app=registry.com/app:${{ steps.release.outputs.version }}
|
||
|
||
# 失败时的回退操作
|
||
- name: 回退操作
|
||
if: steps.release.outputs.release-status == 'failure'
|
||
run: |
|
||
echo "执行回退操作..."
|
||
# 回退到上一个稳定版本的逻辑
|
||
```
|
||
|
||
### 5. 严格模式发布(默认行为)
|
||
|
||
适用于生产环境,发布失败时立即停止:
|
||
|
||
```yaml
|
||
steps:
|
||
- uses: actions/checkout@v4
|
||
|
||
- name: 发布项目
|
||
id: release
|
||
uses: actions/xgj/release-web@main
|
||
with:
|
||
fail-on-error: true # 默认值,发布失败时中断 workflow
|
||
env:
|
||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||
APP_ENV: "production"
|
||
|
||
# 这个步骤只有在发布成功时才会执行
|
||
- name: 部署到生产环境
|
||
run: |
|
||
echo "部署版本 ${{ steps.release.outputs.version }}"
|
||
kubectl apply -f k8s/
|
||
```
|
||
|
||
## 工作流程
|
||
|
||
1. **发布构建**: 执行指定的发布命令进行版本发布
|
||
|
||
- 捕获命令执行状态和退出码
|
||
- 设置 `release-status` 输出(`success`/`failure`)
|
||
- 失败时记录 `exit-code` 输出
|
||
|
||
2. **智能版本获取**: 只在发布成功时执行,通过多种方法自动获取版本号
|
||
|
||
- 优先从版本文件读取(`/tmp/last-version` 或自定义路径)
|
||
- 回退到最新 git tag(保持原始格式)
|
||
- 回退到 `package.json` 中的版本
|
||
- 最后尝试从提交信息解析(支持 `v1.2.3` 和 `1.2.3` 格式)
|
||
- **所有方法都确保输出统一包含 `v` 前缀**
|
||
|
||
3. **发布总结**: 显示详细的发布状态信息
|
||
|
||
- 成功时:显示版本号和发布信息
|
||
- 失败时:显示错误状态和退出码
|
||
|
||
4. **状态检查**: 根据 `fail-on-error` 参数决定最终行为
|
||
- `true`(默认):发布失败时让 action 失败,中断 workflow
|
||
- `false`:发布失败时继续完成,允许后续步骤执行
|
||
|
||
## 依赖要求
|
||
|
||
### 项目要求
|
||
|
||
- 包含 `package.json` 文件(用于版本回退)
|
||
- 配置了发布工具(如 `release-it`)
|
||
- 包含发布脚本(如 `npm run release`)
|
||
- 推荐发布命令生成版本文件到 `/tmp/last-version`(或自定义路径)
|
||
|
||
### 环境依赖
|
||
|
||
- Node.js 环境
|
||
- npm/pnpm/yarn 包管理器
|
||
- 配置好的 Gitea 访问权限
|
||
|
||
## 配置示例
|
||
|
||
### release-it 配置
|
||
|
||
确保项目中有类似的 `.release-it.js` 配置:
|
||
|
||
```javascript
|
||
module.exports = {
|
||
hooks: {
|
||
"before:release": [
|
||
"echo 'v${version}' > /tmp/last-version",
|
||
"npm run build",
|
||
],
|
||
},
|
||
git: {
|
||
tagName: "v${version}",
|
||
commitMessage: "chore: released version v${version} [no ci]",
|
||
},
|
||
npm: {
|
||
publish: false,
|
||
},
|
||
};
|
||
```
|
||
|
||
### Docker 多阶段构建
|
||
|
||
推荐使用多阶段构建优化镜像大小:
|
||
|
||
```dockerfile
|
||
# 构建阶段
|
||
FROM node:18-alpine AS builder
|
||
WORKDIR /app
|
||
COPY package*.json ./
|
||
RUN npm ci --only=production
|
||
|
||
# 运行阶段
|
||
FROM node:18-alpine
|
||
WORKDIR /app
|
||
COPY --from=builder /app/node_modules ./node_modules
|
||
COPY dist ./dist
|
||
EXPOSE 3000
|
||
CMD ["npm", "start"]
|
||
```
|
||
|
||
## 错误处理
|
||
|
||
### 发布失败处理
|
||
|
||
Action 提供灵活的错误处理机制:
|
||
|
||
**严格模式** (`fail-on-error: true` - 默认):
|
||
|
||
- 发布命令失败时,action 立即失败并中断 workflow
|
||
- 适用于生产环境,确保发布质量
|
||
|
||
**宽松模式** (`fail-on-error: false`):
|
||
|
||
- 发布命令失败时,action 继续完成并返回状态信息
|
||
- 允许执行清理、通知等后续操作
|
||
- 可通过 `outputs.release-status` 检查发布结果
|
||
|
||
### 常见错误情况
|
||
|
||
Action 会在以下情况报错:
|
||
|
||
- 发布命令执行失败(返回非零退出码)
|
||
- 无法获取版本信息(所有版本获取方法都失败)
|
||
- 版本文件不存在且无其他版本源
|
||
|
||
## 安全注意事项
|
||
|
||
- 🔒 始终通过 `secrets` 传递敏感令牌
|
||
- 🔍 定期检查和轮换访问令牌
|
||
- 📋 限制 Docker 仓库访问权限
|
||
- 🚫 避免在日志中暴露敏感信息
|
||
|
||
## 故障排除
|
||
|
||
### 常见问题
|
||
|
||
### Q: 如何处理发布失败的情况?
|
||
|
||
A: Action 提供了多种方式处理发布失败:
|
||
|
||
1. **检查发布状态**:
|
||
|
||
```yaml
|
||
- name: 发布项目
|
||
id: release
|
||
uses: actions/xgj/release-web@main
|
||
|
||
- name: 检查发布结果
|
||
run: |
|
||
if [[ "${{ steps.release.outputs.release-status }}" == "failure" ]]; then
|
||
echo "发布失败,退出码: ${{ steps.release.outputs.exit-code }}"
|
||
# 执行失败处理逻辑
|
||
fi
|
||
```
|
||
|
||
2. **宽松模式处理**:
|
||
|
||
```yaml
|
||
- name: 发布项目
|
||
uses: actions/xgj/release-web@main
|
||
with:
|
||
fail-on-error: false # 失败时不中断
|
||
|
||
- name: 清理操作
|
||
if: always()
|
||
run: echo "总是执行清理"
|
||
```
|
||
|
||
### Q: 如何获取发布失败的详细信息?
|
||
|
||
A: 通过输出参数获取:
|
||
|
||
- `release-status`: `success` 或 `failure`
|
||
- `exit-code`: 失败时的命令退出码
|
||
- 检查 action 日志中的详细错误信息
|
||
|
||
### Q: 无法获取版本信息
|
||
|
||
```bash
|
||
❌ 错误: 无法获取版本信息
|
||
```
|
||
|
||
A: Action 会按优先级尝试多种方法获取版本:
|
||
|
||
1. **版本文件** (推荐):确保发布命令创建版本文件
|
||
|
||
```javascript
|
||
// .release-it.js
|
||
hooks: {
|
||
'before:release': ['echo \'v${version}\' > /tmp/last-version']
|
||
}
|
||
```
|
||
|
||
2. **Git Tags**:确保发布过程创建了 git tag
|
||
|
||
```bash
|
||
git tag v1.2.3
|
||
```
|
||
|
||
3. **package.json**:确保 package.json 包含有效的 version 字段
|
||
|
||
```json
|
||
{
|
||
"version": "1.2.3"
|
||
}
|
||
```
|
||
|
||
4. **提交信息**:在提交信息中包含版本号
|
||
|
||
```bash
|
||
git commit -m "release: v1.2.3"
|
||
# 或者
|
||
git commit -m "release: 1.2.3"
|
||
```
|
||
|
||
### Q: Gitea Token 权限不足
|
||
|
||
A: 确保 token 具有以下权限:
|
||
|
||
- Repository 写权限
|
||
- Releases 创建权限
|
||
|
||
### 调试模式
|
||
|
||
启用详细调试信息:
|
||
|
||
```yaml
|
||
- uses: actions/xgj/release-web@main
|
||
with:
|
||
node-debug: "true"
|
||
env:
|
||
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
||
```
|
||
|
||
## 更新日志
|
||
|
||
查看 [Releases](https://github.com/your-org/actions/releases) 获取详细的更新历史。
|
||
|
||
## 贡献
|
||
|
||
欢迎提交 Issue 和 Pull Request 来改进这个 Action!
|
||
|
||
## 许可证
|
||
|
||
MIT License - 详见 [LICENSE](../LICENSE) 文件。
|