name: Build and Release on: push: tags: - 'v*' permissions: contents: write jobs: build: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup JDK 21 uses: actions/setup-java@v4 with: java-version: '21' distribution: 'temurin' - name: Make gradlew executable run: chmod +x ./gradlew - name: Build with Gradle run: ./gradlew build - name: Prepare release files run: | mkdir -p release-files cp build/libs/*.jar release-files/ 2>/dev/null || true echo "准备发布的文件:" ls -la release-files/ - name: Upload release artifacts uses: actions/upload-artifact@v4 with: name: release-files path: release-files/ retention-days: 7 release: runs-on: ubuntu-latest needs: build if: startsWith(github.ref, 'refs/tags/v') steps: - name: Checkout with full history uses: actions/checkout@v4 with: fetch-depth: 0 - name: Download artifacts uses: actions/download-artifact@v4 with: name: release-files path: ./dist - name: Generate CZ-compliant changelog id: generate_changelog run: | CURRENT_TAG="${{ github.ref_name }}" PREV_TAG=$(git describe --tags --abbrev=0 $(git rev-list --tags --skip=1 --max-count=1) 2>/dev/null || echo "") # 创建临时文件 TEMP_FILE=$(mktemp) echo "# 🚀 版本 $CURRENT_TAG 发布" > $TEMP_FILE echo "" >> $TEMP_FILE echo "## 📋 变更摘要" >> $TEMP_FILE echo "" >> $TEMP_FILE if [ -z "$PREV_TAG" ]; then echo "### 初始版本发布" >> $TEMP_FILE echo "" >> $TEMP_FILE echo "这是项目的第一个正式版本。" >> $TEMP_FILE echo "" >> $TEMP_FILE # 获取所有提交并按类型分组 git log --pretty=format:"%s" --reverse | while read -r line; do echo "- $line" >> $TEMP_FILE done else echo "### 从 $PREV_TAG 到 $CURRENT_TAG 的变更" >> $TEMP_FILE echo "" >> $TEMP_FILE # 定义符合CZ规范的提交类型映射 declare -A commit_types commit_types=( ["✨ 新功能"]="^(feat|feature)(\(.*\))?:" ["🐛 修复"]="^(fix|bugfix)(\(.*\))?:" ["📝 文档"]="^(docs|documentation)(\(.*\))?:" ["🎨 样式"]="^(style)(\(.*\))?:" ["🔨 重构"]="^(refactor)(\(.*\))?:" ["⚡️ 性能"]="^(perf|performance)(\(.*\))?:" ["✅ 测试"]="^(test)(\(.*\))?:" ["🔧 构建"]="^(build)(\(.*\))?:" ["👷 CI"]="^(ci)(\(.*\))?:" ["📦 依赖"]="^(chore|deps)(\(.*\))?:" ["⏪ 回退"]="^(revert)(\(.*\))?:" ) # 获取所有提交 COMMITS=$(git log --pretty=format:"%s" $PREV_TAG..HEAD) # 处理每种类型的提交 for type_name in "${!commit_types[@]}"; do pattern="${commit_types[$type_name]}" # 提取匹配的提交 matched_commits=$(echo "$COMMITS" | grep -E "$pattern" || true) if [ -n "$matched_commits" ]; then echo "#### $type_name" >> $TEMP_FILE echo "" >> $TEMP_FILE # 处理每条提交,提取scope和subject echo "$matched_commits" | while read -r commit; do # 解析scope和subject if [[ $commit =~ ^[a-z]+\((.*)\):\ (.*) ]]; then scope="${BASH_REMATCH[1]}" subject="${BASH_REMATCH[2]}" echo "- **$scope**: $subject" >> $TEMP_FILE elif [[ $commit =~ ^[a-z]+:\ (.*) ]]; then subject="${BASH_REMATCH[1]}" echo "- $subject" >> $TEMP_FILE else echo "- $commit" >> $TEMP_FILE fi done echo "" >> $TEMP_FILE fi done # 处理破坏性变更(BREAKING CHANGE) breaking_changes=$(git log --pretty=format:"%b" $PREV_TAG..HEAD | grep -i "BREAKING CHANGE" || true) if [ -n "$breaking_changes" ]; then echo "#### ⚠️ 破坏性变更" >> $TEMP_FILE echo "" >> $TEMP_FILE echo "$breaking_changes" | while read -r line; do echo "- $line" >> $TEMP_FILE done echo "" >> $TEMP_FILE fi # 处理未分类的提交 uncategorized="$COMMITS" for pattern in "${commit_types[@]}"; do uncategorized=$(echo "$uncategorized" | grep -v -E "$pattern" || true) done if [ -n "$uncategorized" ]; then echo "#### 📝 其他更改" >> $TEMP_FILE echo "" >> $TEMP_FILE echo "$uncategorized" | while read -r commit; do echo "- $commit" >> $TEMP_FILE done echo "" >> $TEMP_FILE fi fi echo "## 📊 统计信息" >> $TEMP_FILE echo "" >> $TEMP_FILE if [ -z "$PREV_TAG" ]; then TOTAL_COMMITS=$(git rev-list --count HEAD) echo "- 总提交数: $TOTAL_COMMITS" >> $TEMP_FILE echo "- 首次发布" >> $TEMP_FILE else COMMITS=$(git rev-list --count $PREV_TAG..HEAD) echo "- 本次发布提交数: $COMMITS" >> $TEMP_FILE echo "- 上一个版本: $PREV_TAG" >> $TEMP_FILE fi echo "- 发布日期: $(date '+%Y年%m月%d日')" >> $TEMP_FILE echo "- 当前版本: $CURRENT_TAG" >> $TEMP_FILE echo "" >> $TEMP_FILE echo "---" >> $TEMP_FILE echo "" >> $TEMP_FILE echo "### 📜 详细提交历史" >> $TEMP_FILE echo "" >> $TEMP_FILE # 显示所有提交的详细列表,包含scope信息 if [ -z "$PREV_TAG" ]; then git log --pretty=format:"- **%h** %s - %an (%ad)" --date=short --reverse | head -100 >> $TEMP_FILE else git log --pretty=format:"- **%h** %s - %an (%ad)" --date=short $PREV_TAG..HEAD | head -100 >> $TEMP_FILE fi # 将文件内容输出到变量 CHANGELOG_CONTENT=$(cat $TEMP_FILE) echo "changelog<> $GITHUB_OUTPUT echo "$CHANGELOG_CONTENT" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT - name: Create Release uses: ncipollo/release-action@v1 with: artifacts: "dist/*.jar" tag: ${{ github.ref_name }} name: "版本 ${{ github.ref_name }}" body: ${{ steps.generate_changelog.outputs.changelog }} draft: false prerelease: false