Files
claude-relay-service/.github/workflows/auto-release-pipeline.yml
shaw 616079b16b fix: 修复 web-dist 分支 README 文件日期变量替换问题
- 移除 heredoc 的单引号,允许变量和命令替换
- 确保 Build Date 能正确显示实际构建时间
- 同时修复了 workflow 和测试脚本中的相同问题

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-06 10:27:05 +08:00

346 lines
13 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: |
# 检测是否是合并提交
PARENT_COUNT=$(git rev-list --parents -n 1 HEAD | wc -w)
PARENT_COUNT=$((PARENT_COUNT - 1))
echo "Parent count: $PARENT_COUNT"
if [ "$PARENT_COUNT" -gt 1 ]; then
# 合并提交:获取合并进来的所有文件变更
echo "Detected merge commit, getting all merged changes"
# 获取合并基准点
MERGE_BASE=$(git merge-base HEAD^1 HEAD^2 2>/dev/null || echo "")
if [ -n "$MERGE_BASE" ]; then
# 获取从合并基准到 HEAD 的所有变更
CHANGED_FILES=$(git diff --name-only $MERGE_BASE..HEAD)
else
# 如果无法获取合并基准,使用第二个父提交
CHANGED_FILES=$(git diff --name-only HEAD^2..HEAD)
fi
else
# 普通提交:获取相对于上一个提交的变更
CHANGED_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null || git diff --name-only $(git rev-list --max-parents=0 HEAD)..HEAD)
fi
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: 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"
# 提交VERSION文件 - 添加 [skip ci] 以避免再次触发
git add VERSION
git commit -m "chore: sync VERSION file with release ${{ steps.next_version.outputs.new_tag }} [skip ci]"
# 构建前端并推送到 web-dist 分支
- name: Setup Node.js
if: steps.check.outputs.needs_bump == 'true'
uses: actions/setup-node@v4
with:
node-version: '18'
cache: 'npm'
cache-dependency-path: web/admin-spa/package-lock.json
- name: Build Frontend
if: steps.check.outputs.needs_bump == 'true'
run: |
echo "Building frontend for version ${{ steps.next_version.outputs.new_version }}..."
cd web/admin-spa
npm ci
npm run build
echo "Frontend build completed"
- name: Push Frontend Build to web-dist Branch
if: steps.check.outputs.needs_bump == 'true'
run: |
# 创建临时目录
TEMP_DIR=$(mktemp -d)
echo "Using temp directory: $TEMP_DIR"
# 复制构建产物到临时目录
cp -r web/admin-spa/dist/* "$TEMP_DIR/"
# 检查 web-dist 分支是否存在
if git ls-remote --heads origin web-dist | grep -q web-dist; then
echo "Checking out existing web-dist branch"
git fetch origin web-dist:web-dist
git checkout web-dist
else
echo "Creating new web-dist branch"
git checkout --orphan web-dist
fi
# 清空当前目录(保留 .git
git rm -rf . 2>/dev/null || true
# 复制构建产物
cp -r "$TEMP_DIR"/* .
# 添加 README
cat > README.md << EOF
# Claude Relay Service - Web Frontend Build
This branch contains the pre-built frontend assets for Claude Relay Service.
**DO NOT EDIT FILES IN THIS BRANCH DIRECTLY**
These files are automatically generated by the CI/CD pipeline.
Version: ${{ steps.next_version.outputs.new_version }}
Build Date: $(date -u +"%Y-%m-%d %H:%M:%S UTC")
EOF
# 提交并推送
git add -A
git commit -m "chore: update frontend build for v${{ steps.next_version.outputs.new_version }} [skip ci]"
git push origin web-dist --force
# 切换回主分支
git checkout main
# 清理临时目录
rm -rf "$TEMP_DIR"
echo "Frontend build pushed to web-dist branch successfully"
- 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 @-