Repository navigation
v0.1.0 #1
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Generate Tag Release | |
| run-name: ${{ github.ref_name }} | |
| on: | |
| push: | |
| tags: | |
| - 'v[0-9]+.[0-9]+.[0-9]+*' | |
| - 'V[0-9]+.[0-9]+.[0-9]+*' | |
| permissions: | |
| contents: write | |
| pull-requests: read | |
| jobs: | |
| release: | |
| name: Generate Release & Package Mod | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout Code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Determine Git Range | |
| id: git-range | |
| run: | | |
| CURRENT_TAG="${{ github.ref_name }}" | |
| PREVIOUS_TAG=$(git describe --tags --abbrev=0 "${CURRENT_TAG}^" 2>/dev/null || echo "") | |
| echo "::group::[Debug] Tag 计算结果" | |
| echo "当前 Tag: $CURRENT_TAG" | |
| if [ -z "$PREVIOUS_TAG" ]; then | |
| echo "未找到上一个 Tag,将获取全部历史" | |
| else | |
| echo "上一个 Tag: $PREVIOUS_TAG" | |
| echo "对比区间: ${PREVIOUS_TAG}...${CURRENT_TAG}" | |
| fi | |
| echo "::endgroup::" | |
| echo "current=$CURRENT_TAG" >> $GITHUB_OUTPUT | |
| echo "base=$PREVIOUS_TAG" >> $GITHUB_OUTPUT | |
| - name: Collect Raw Commits | |
| run: | | |
| BASE="${{ steps.git-range.outputs.base }}" | |
| HEAD="${{ steps.git-range.outputs.current }}" | |
| if [ -z "$BASE" ]; then | |
| git log --pretty=format:"* %h - %s (%an)" "$HEAD" > /tmp/commits.txt | |
| else | |
| git log --pretty=format:"* %h - %s (%an)" "${BASE}..${HEAD}" > /tmp/commits.txt | |
| fi | |
| echo "::group::[Debug] 原始 Commit 列表" | |
| cat /tmp/commits.txt | |
| echo "::endgroup::" | |
| - name: Collect PR Data | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const base = '${{ steps.git-range.outputs.base }}'; | |
| const head = '${{ steps.git-range.outputs.current }}'; | |
| const compareOptions = { | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| head: head | |
| }; | |
| if (base) compareOptions.base = base; | |
| const { data: compare } = await github.rest.repos.compareCommits(compareOptions); | |
| console.log(`::notice::共检测到 ${compare.commits.length} 个 Commits`); | |
| const prNumbers = new Set(); | |
| for (const commit of compare.commits) { | |
| const message = commit.commit.message; | |
| const mergeMatch = message.match(/Merge pull request #(\d+)/); | |
| if (mergeMatch) prNumbers.add(parseInt(mergeMatch[1])); | |
| const suffixMatch = message.match(/\(#(\d+)\)$/); | |
| if (suffixMatch) prNumbers.add(parseInt(suffixMatch[1])); | |
| const fixMatch = message.match(/(?:fixes|closes|resolves) #(\d+)/i); | |
| if (fixMatch) prNumbers.add(parseInt(fixMatch[1])); | |
| } | |
| const prDetails = []; | |
| for (const num of prNumbers) { | |
| try { | |
| const { data: pr } = await github.rest.pulls.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: num | |
| }); | |
| prDetails.push({ | |
| number: pr.number, | |
| title: pr.title, | |
| body: pr.body, | |
| author: pr.user.login, | |
| labels: pr.labels.map(l => l.name) | |
| }); | |
| } catch (e) { | |
| console.log(`::warning::获取 PR #${num} 失败: ${e.message}`); | |
| } | |
| } | |
| const fs = require('fs'); | |
| fs.writeFileSync('/tmp/prs.json', JSON.stringify(prDetails, null, 2)); | |
| - name: Setup Python | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.11' | |
| - name: Install Dependencies | |
| run: pip install openai | |
| - name: Generate AI Release Notes | |
| env: | |
| DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }} | |
| DEEPSEEK_BASE_URL: ${{ secrets.DEEPSEEK_BASE_URL || 'https://api.deepseek.com' }} | |
| run: | | |
| python .github/scripts/analyze_release.py \ | |
| --tag "${{ steps.git-range.outputs.current }}" \ | |
| --prs-file /tmp/prs.json \ | |
| --commits-txt /tmp/commits.txt | |
| - name: Package Mod | |
| id: package | |
| run: | | |
| TAG="${{ steps.git-range.outputs.current }}" | |
| if [ -f "About/About.xml" ]; then | |
| MOD_NAME=$(grep -oP '(?<=<name>)[^<]+' About/About.xml | head -1) | |
| MOD_SAFE=$(echo "$MOD_NAME" | sed 's/[^a-zA-Z0-9 ]//g' | sed 's/ /-/g' | sed 's/-\+/-/g') | |
| else | |
| MOD_SAFE="${{ github.event.repository.name }}" | |
| fi | |
| [ -z "$MOD_SAFE" ] && MOD_SAFE="mod" | |
| echo "mod_safe=$MOD_SAFE" >> $GITHUB_OUTPUT | |
| # 打包:排除开发相关文件,只保留玩家需要的内容 | |
| mkdir -p "/tmp/${MOD_SAFE}" | |
| rsync -av --delete \ | |
| --exclude='.git/' \ | |
| --exclude='.github/' \ | |
| --exclude='Source/' \ | |
| --exclude='Tests/' \ | |
| --exclude='.claude/' \ | |
| --exclude='.trae/' \ | |
| --exclude='docs/' \ | |
| --exclude='*.csproj' \ | |
| --exclude='*.sln' \ | |
| --exclude='.gitignore' \ | |
| --exclude='.gitattributes' \ | |
| --exclude='*.md' \ | |
| "./" "/tmp/${MOD_SAFE}/" | |
| cd /tmp | |
| zip -r "${MOD_SAFE}-${TAG}.zip" "${MOD_SAFE}/" | |
| echo "::notice::打包完成: ${MOD_SAFE}-${TAG}.zip" | |
| - name: Check Prerelease | |
| id: prerelease | |
| run: | | |
| TAG="${{ steps.git-range.outputs.current }}" | |
| if echo "$TAG" | grep -qiE 'alpha|beta|rc|preview'; then | |
| echo "is_prerelease=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "is_prerelease=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Publish GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.git-range.outputs.current }} | |
| name: Release ${{ steps.git-range.outputs.current }} | |
| body_path: /tmp/release_notes.md | |
| prerelease: ${{ steps.prerelease.outputs.is_prerelease == 'true' }} | |
| files: /tmp/${{ steps.package.outputs.mod_safe }}-${{ steps.git-range.outputs.current }}.zip | |
| generate_release_notes: false | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |