Files
claude-relay-service/.github/workflows/auto-release-pipeline.yml
shaw 8ece285f5f fix: 修复 GitHub Actions 版本检测对合并提交的处理
问题:
- 之前的版本检测逻辑使用 HEAD~1..HEAD 只能获取直接的父提交变更
- 对于合并提交,这会导致忽略所有合并进来的实际代码变更
- 导致明明有重要代码更新却显示 "No significant changes"

解决方案:
- 添加合并提交检测逻辑
- 对于合并提交,获取从合并基准点到 HEAD 的所有变更
- 确保所有合并进来的文件变更都被正确检测

这样可以确保版本自动发布工作流正确识别所有代码变更。

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-08-04 17:48:44 +08:00

277 lines
10 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
# 前端构建已移至 Docker 构建流程中
- 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]"
- 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 @-