Files
claude-relay-service/.github/workflows/auto-release-pipeline.yml
shaw 7b81106949 feat: 将admin-spa构建迁移到GitHub Actions workflow
🔄 主要改进:
- 在自动发布流程中添加admin-spa前端构建步骤
- 仅在web/admin-spa目录有改动时才触发构建
- 构建后的dist目录会自动包含在版本发布中
- 移除手动提交的dist目录,避免安全风险

🐛 修复:
- 修复登录后用户名显示为默认"Admin"的问题
- 现在会正确从服务器获取并显示实际用户名

🔒 安全优化:
- 防止恶意代码通过dist目录注入
- 所有前端代码都会在CI环境中重新构建

现在开发者无需手动构建前端,workflow会自动处理

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-07-29 13:45:11 +08:00

312 lines
12 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

name: Auto Release Pipeline
on:
push:
branches:
- main
permissions:
contents: write
packages: write
jobs:
release-pipeline:
runs-on: ubuntu-latest
# 跳过由GitHub Actions创建的提交避免死循环
if: github.event.pusher.name != 'github-actions[bot]' && !contains(github.event.head_commit.message, '[skip ci]')
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Check if version bump is needed
id: check
run: |
# 获取当前提交的文件变更
CHANGED_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null || git diff --name-only $(git rev-list --max-parents=0 HEAD)..HEAD)
echo "Changed files:"
echo "$CHANGED_FILES"
# 检查是否只有无关文件(.md, docs/, .github/等)
SIGNIFICANT_CHANGES=false
while IFS= read -r file; do
# 跳过空行
[ -z "$file" ] && continue
# 检查是否是需要忽略的文件
if [[ ! "$file" =~ \.(md|txt)$ ]] &&
[[ ! "$file" =~ ^docs/ ]] &&
[[ ! "$file" =~ ^\.github/ ]] &&
[[ "$file" != "VERSION" ]] &&
[[ "$file" != ".gitignore" ]] &&
[[ "$file" != "LICENSE" ]]; then
echo "Found significant change in: $file"
SIGNIFICANT_CHANGES=true
break
fi
done <<< "$CHANGED_FILES"
if [ "$SIGNIFICANT_CHANGES" = true ]; then
echo "Significant changes detected, version bump needed"
echo "needs_bump=true" >> $GITHUB_OUTPUT
else
echo "No significant changes, skipping version bump"
echo "needs_bump=false" >> $GITHUB_OUTPUT
fi
- name: Get current version
if: steps.check.outputs.needs_bump == 'true'
id: get_version
run: |
# 获取最新的tag版本
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
echo "Latest tag: $LATEST_TAG"
TAG_VERSION=${LATEST_TAG#v}
# 获取VERSION文件中的版本
FILE_VERSION=$(cat VERSION | tr -d '[:space:]')
echo "VERSION file: $FILE_VERSION"
# 比较tag版本和文件版本取较大值
function version_gt() { test "$(printf '%s\n' "$@" | sort -V | head -n 1)" != "$1"; }
if version_gt "$FILE_VERSION" "$TAG_VERSION"; then
VERSION="$FILE_VERSION"
echo "Using VERSION file: $VERSION (newer than tag)"
else
VERSION="$TAG_VERSION"
echo "Using tag version: $VERSION (newer or equal to file)"
fi
echo "Current version: $VERSION"
echo "current_version=$VERSION" >> $GITHUB_OUTPUT
- name: Calculate next version
if: steps.check.outputs.needs_bump == 'true'
id: next_version
run: |
VERSION="${{ steps.get_version.outputs.current_version }}"
# 分割版本号
IFS='.' read -r -a version_parts <<< "$VERSION"
MAJOR="${version_parts[0]:-0}"
MINOR="${version_parts[1]:-0}"
PATCH="${version_parts[2]:-0}"
# 默认递增patch版本
NEW_PATCH=$((PATCH + 1))
NEW_VERSION="${MAJOR}.${MINOR}.${NEW_PATCH}"
echo "New version: $NEW_VERSION"
echo "new_version=$NEW_VERSION" >> $GITHUB_OUTPUT
echo "new_tag=v$NEW_VERSION" >> $GITHUB_OUTPUT
- name: Check if frontend build is needed
id: check_frontend
if: steps.check.outputs.needs_bump == 'true'
run: |
# 检查 web/admin-spa 目录是否有变更
FRONTEND_CHANGES=false
CHANGED_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null || git diff --name-only $(git rev-list --max-parents=0 HEAD)..HEAD)
while IFS= read -r file; do
if [[ "$file" =~ ^web/admin-spa/ ]] &&
[[ ! "$file" =~ ^web/admin-spa/dist/ ]] &&
[[ ! "$file" =~ \.(md|txt)$ ]] &&
[[ "$file" != "web/admin-spa/.gitignore" ]]; then
echo "Found frontend change in: $file"
FRONTEND_CHANGES=true
break
fi
done <<< "$CHANGED_FILES"
echo "needs_build=$FRONTEND_CHANGES" >> $GITHUB_OUTPUT
- name: Setup Node.js
if: steps.check.outputs.needs_bump == 'true' && steps.check_frontend.outputs.needs_build == 'true'
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
cache-dependency-path: web/admin-spa/package-lock.json
- name: Build admin-spa
if: steps.check.outputs.needs_bump == 'true' && steps.check_frontend.outputs.needs_build == 'true'
run: |
echo "Building admin-spa frontend..."
cd web/admin-spa
npm ci
npm run build
cd ../..
# 确认 dist 目录已创建
if [ -d "web/admin-spa/dist" ]; then
echo "✅ Frontend build successful"
ls -la web/admin-spa/dist/
else
echo "❌ Frontend build failed - dist directory not found"
exit 1
fi
- name: Update VERSION file
if: steps.check.outputs.needs_bump == 'true'
run: |
echo "${{ steps.next_version.outputs.new_version }}" > VERSION
# 配置git
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
# 检查是否需要添加 dist 目录
if [ "${{ steps.check_frontend.outputs.needs_build }}" = "true" ] && [ -d "web/admin-spa/dist" ]; then
git add -f web/admin-spa/dist/
echo "Added frontend dist directory to commit"
fi
# 提交VERSION文件和可能的dist目录 - 添加 [skip ci] 以避免再次触发
git add VERSION
if [ "${{ steps.check_frontend.outputs.needs_build }}" = "true" ]; then
git commit -m "chore: sync VERSION file with release ${{ steps.next_version.outputs.new_tag }} and rebuild frontend [skip ci]"
else
git commit -m "chore: sync VERSION file with release ${{ steps.next_version.outputs.new_tag }} [skip ci]"
fi
- name: Install git-cliff
if: steps.check.outputs.needs_bump == 'true'
run: |
wget -q https://github.com/orhun/git-cliff/releases/download/v1.4.0/git-cliff-1.4.0-x86_64-unknown-linux-gnu.tar.gz
tar -xzf git-cliff-1.4.0-x86_64-unknown-linux-gnu.tar.gz
chmod +x git-cliff-1.4.0/git-cliff
sudo mv git-cliff-1.4.0/git-cliff /usr/local/bin/
- name: Generate changelog
if: steps.check.outputs.needs_bump == 'true'
id: changelog
run: |
# 获取上一个tag以来的更新日志
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "")
if [ -n "$LATEST_TAG" ]; then
# 排除VERSION文件的提交
CHANGELOG=$(git-cliff --config .github/cliff.toml $LATEST_TAG..HEAD --strip header | grep -v "bump version" | sed '/^$/d' || echo "- 代码优化和改进")
else
CHANGELOG=$(git-cliff --config .github/cliff.toml --strip header || echo "- 初始版本发布")
fi
echo "content<<EOF" >> $GITHUB_OUTPUT
echo "$CHANGELOG" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT
- name: Create and push tag
if: steps.check.outputs.needs_bump == 'true'
run: |
NEW_TAG="${{ steps.next_version.outputs.new_tag }}"
git tag -a "$NEW_TAG" -m "Release $NEW_TAG"
git push origin HEAD:main "$NEW_TAG"
- name: Create GitHub Release
if: steps.check.outputs.needs_bump == 'true'
uses: softprops/action-gh-release@v1
with:
tag_name: ${{ steps.next_version.outputs.new_tag }}
name: Release ${{ steps.next_version.outputs.new_version }}
body: |
## 🐳 Docker 镜像
```bash
docker pull ${{ secrets.DOCKERHUB_USERNAME || 'weishaw' }}/claude-relay-service:${{ steps.next_version.outputs.new_tag }}
docker pull ${{ secrets.DOCKERHUB_USERNAME || 'weishaw' }}/claude-relay-service:latest
```
## 📦 主要更新
${{ steps.changelog.outputs.content }}
## 📋 完整更新日志
查看 [所有版本](https://github.com/${{ github.repository }}/releases)
draft: false
prerelease: false
generate_release_notes: true
# Docker构建步骤
- name: Set up QEMU
if: steps.check.outputs.needs_bump == 'true'
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
if: steps.check.outputs.needs_bump == 'true'
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
if: steps.check.outputs.needs_bump == 'true'
uses: docker/login-action@v3
with:
registry: docker.io
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push Docker image
if: steps.check.outputs.needs_bump == 'true'
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: |
${{ secrets.DOCKERHUB_USERNAME }}/claude-relay-service:${{ steps.next_version.outputs.new_tag }}
${{ secrets.DOCKERHUB_USERNAME }}/claude-relay-service:latest
${{ secrets.DOCKERHUB_USERNAME }}/claude-relay-service:${{ steps.next_version.outputs.new_version }}
labels: |
org.opencontainers.image.version=${{ steps.next_version.outputs.new_version }}
org.opencontainers.image.revision=${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Send Telegram Notification
if: steps.check.outputs.needs_bump == 'true' && env.TELEGRAM_BOT_TOKEN != '' && env.TELEGRAM_CHAT_ID != ''
env:
TELEGRAM_BOT_TOKEN: ${{ secrets.TELEGRAM_BOT_TOKEN }}
TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }}
continue-on-error: true
run: |
VERSION="${{ steps.next_version.outputs.new_version }}"
TAG="${{ steps.next_version.outputs.new_tag }}"
REPO="${{ github.repository }}"
# 获取更新内容并限制长度
CHANGELOG="${{ steps.changelog.outputs.content }}"
CHANGELOG_TRUNCATED=$(echo "$CHANGELOG" | head -c 1000)
if [ ${#CHANGELOG} -gt 1000 ]; then
CHANGELOG_TRUNCATED="${CHANGELOG_TRUNCATED}..."
fi
# 构建消息内容
MESSAGE="🚀 *Claude Relay Service 新版本发布!*"$'\n'$'\n'
MESSAGE+="📦 版本号: \`${VERSION}\`"$'\n'$'\n'
MESSAGE+="📝 *更新内容:*"$'\n'
MESSAGE+="${CHANGELOG_TRUNCATED}"$'\n'$'\n'
MESSAGE+="🐳 *Docker 部署:*"$'\n'
MESSAGE+="\`\`\`bash"$'\n'
MESSAGE+="docker pull weishaw/claude-relay-service:${TAG}"$'\n'
MESSAGE+="docker pull weishaw/claude-relay-service:latest"$'\n'
MESSAGE+="\`\`\`"$'\n'$'\n'
MESSAGE+="🔗 *相关链接:*"$'\n'
MESSAGE+="• [GitHub Release](https://github.com/${REPO}/releases/tag/${TAG})"$'\n'
MESSAGE+="• [完整更新日志](https://github.com/${REPO}/releases)"$'\n'
MESSAGE+="• [Docker Hub](https://hub.docker.com/r/weishaw/claude-relay-service)"$'\n'$'\n'
MESSAGE+="#ClaudeRelay #Update #v${VERSION//./_}"
# 使用 jq 构建 JSON 并发送
jq -n \
--arg chat_id "${TELEGRAM_CHAT_ID}" \
--arg text "${MESSAGE}" \
'{
chat_id: $chat_id,
text: $text,
parse_mode: "Markdown",
disable_web_page_preview: false
}' | \
curl -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
-H "Content-Type: application/json" \
-d @-