feat: SEO优化及多语言sitemap生成 #6
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: Release on Version Change | |
| on: | |
| push: | |
| branches: | |
| - frontend-remake | |
| paths: | |
| - 'package.json' | |
| - 'public/config/version.json' | |
| - '.github/workflows/release-on-version-change.yml' | |
| workflow_dispatch: # 允许手动触发 | |
| jobs: | |
| release: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write # 需要权限来创建release和tag | |
| id-token: write | |
| # 版本检测在步骤中完成,避免重复release | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 # 获取完整历史记录用于生成changelog | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v2 | |
| with: | |
| version: 9 | |
| - name: Setup Node.js | |
| id: setup-node | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20.x' | |
| check-latest: true | |
| - name: Verify installation | |
| shell: bash | |
| run: | | |
| echo "Checking installations..." | |
| node --version | |
| npm --version | |
| pnpm --version || echo "pnpm not required for release workflow" | |
| echo "Installations verified." | |
| - name: Check if version actually changed | |
| id: check-version | |
| shell: bash | |
| run: | | |
| # 检查触发事件类型 | |
| echo "Event name: $GITHUB_EVENT_NAME" | |
| # 如果是手动触发,总是发布 | |
| if [[ "$GITHUB_EVENT_NAME" == "workflow_dispatch" ]]; then | |
| echo "Manual trigger detected. Will proceed with release." | |
| echo "should_release=true" >> $GITHUB_OUTPUT | |
| exit 0 | |
| fi | |
| # 获取当前版本信息 | |
| CURRENT_PACKAGE_VERSION=$(jq -r .version package.json) | |
| CURRENT_POLICY_VERSION=$(jq -r .policyVersion public/config/version.json) | |
| CURRENT_APP_VERSION=$(jq -r .appVersion public/config/version.json) | |
| # 获取上一个提交的版本信息(如果存在) | |
| if git log -n 1 --oneline > /dev/null 2>&1; then | |
| PREV_PACKAGE_VERSION=$(git show HEAD~1:package.json 2>/dev/null | jq -r .version 2>/dev/null || echo "none") | |
| PREV_POLICY_VERSION=$(git show HEAD~1:public/config/version.json 2>/dev/null | jq -r .policyVersion 2>/dev/null || echo "none") | |
| PREV_APP_VERSION=$(git show HEAD~1:public/config/version.json 2>/dev/null | jq -r .appVersion 2>/dev/null || echo "none") | |
| else | |
| PREV_PACKAGE_VERSION="none" | |
| PREV_POLICY_VERSION="none" | |
| PREV_APP_VERSION="none" | |
| fi | |
| echo "Previous versions:" | |
| echo " Package: $PREV_PACKAGE_VERSION" | |
| echo " Policy: $PREV_POLICY_VERSION" | |
| echo " App: $PREV_APP_VERSION" | |
| echo "Current versions:" | |
| echo " Package: $CURRENT_PACKAGE_VERSION" | |
| echo " Policy: $CURRENT_POLICY_VERSION" | |
| echo " App: $CURRENT_APP_VERSION" | |
| # 检查是否有版本变化 | |
| VERSION_CHANGED=false | |
| if [[ "$CURRENT_PACKAGE_VERSION" != "$PREV_PACKAGE_VERSION" ]]; then | |
| echo "Package version changed from $PREV_PACKAGE_VERSION to $CURRENT_PACKAGE_VERSION" | |
| VERSION_CHANGED=true | |
| fi | |
| if [[ "$CURRENT_POLICY_VERSION" != "$PREV_POLICY_VERSION" ]]; then | |
| echo "Policy version changed from $PREV_POLICY_VERSION to $CURRENT_POLICY_VERSION" | |
| VERSION_CHANGED=true | |
| fi | |
| if [[ "$CURRENT_APP_VERSION" != "$PREV_APP_VERSION" ]]; then | |
| echo "App version changed from $PREV_APP_VERSION to $CURRENT_APP_VERSION" | |
| VERSION_CHANGED=true | |
| fi | |
| if [[ "$VERSION_CHANGED" == "true" ]]; then | |
| echo "Version change detected, will proceed with release." | |
| echo "should_release=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "No version change detected. Skipping release." | |
| echo "should_release=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Determine release version | |
| id: determine-version | |
| if: steps.check-version.outputs.should_release == 'true' | |
| shell: bash | |
| run: | | |
| # 优先使用package.json的version作为release版本 | |
| RELEASE_VERSION=$(jq -r .version package.json) | |
| echo "Using package.json version: $RELEASE_VERSION" | |
| # 验证版本格式(应该符合语义化版本) | |
| if [[ ! "$RELEASE_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]]; then | |
| echo "Warning: Version format may not be standard semantic versioning" | |
| fi | |
| echo "release_version=$RELEASE_VERSION" >> $GITHUB_OUTPUT | |
| echo "tag_name=v$RELEASE_VERSION" >> $GITHUB_OUTPUT | |
| # 获取版本描述 | |
| POLICY_VERSION=$(jq -r .policyVersion public/config/version.json) | |
| APP_VERSION=$(jq -r .appVersion public/config/version.json) | |
| echo "policy_version=$POLICY_VERSION" >> $GITHUB_OUTPUT | |
| echo "app_version=$APP_VERSION" >> $GITHUB_OUTPUT | |
| - name: Generate changelog | |
| id: changelog | |
| if: steps.check-version.outputs.should_release == 'true' | |
| shell: bash | |
| run: | | |
| # 获取当前tag名 | |
| TAG_NAME="${{ steps.determine-version.outputs.tag_name }}" | |
| # 查找上一个tag | |
| PREV_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "") | |
| if [[ -z "$PREV_TAG" ]]; then | |
| echo "No previous tag found. Generating changelog from first commit." | |
| # 获取所有提交信息 | |
| COMMITS=$(git log --oneline --pretty=format:"- %s" --reverse) | |
| CHANGELOG_HEADER="## 初始版本 v${{ steps.determine-version.outputs.release_version }}\n\n首次发布。包含以下提交:\n\n" | |
| else | |
| echo "Previous tag found: $PREV_TAG" | |
| # 获取从上个tag到现在的提交信息 | |
| COMMITS=$(git log --oneline --pretty=format:"- %s" "${PREV_TAG}..HEAD") | |
| CHANGELOG_HEADER="## v${{ steps.determine-version.outputs.release_version }} ($(date '+%Y-%m-%d'))\n\n自 ${PREV_TAG} 以来的变更:\n\n" | |
| fi | |
| # 如果COMMITS为空(可能没有新提交) | |
| if [[ -z "$COMMITS" ]]; then | |
| COMMITS="- 无具体提交信息(版本号变更)" | |
| fi | |
| # 构建完整的发布说明 | |
| RELEASE_BODY="${CHANGELOG_HEADER}${COMMITS}\n\n### 版本信息\n- 应用版本: ${{ steps.determine-version.outputs.release_version }}\n- 用户协议版本: ${{ steps.determine-version.outputs.policy_version }}\n- 内部版本: ${{ steps.determine-version.outputs.app_version }}\n\n*自动生成于 $(date '+%Y-%m-%d %H:%M:%S')*" | |
| # 输出到GITHUB_OUTPUT(需要处理多行文本) | |
| EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64) | |
| echo "release_body<<$EOF" >> $GITHUB_OUTPUT | |
| echo "$RELEASE_BODY" >> $GITHUB_OUTPUT | |
| echo "$EOF" >> $GITHUB_OUTPUT | |
| echo "Generated changelog with $(echo "$COMMITS" | wc -l) commits" | |
| - name: Create GitHub Release | |
| id: create-release | |
| if: steps.check-version.outputs.should_release == 'true' | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.determine-version.outputs.tag_name }} | |
| name: v${{ steps.determine-version.outputs.release_version }} | |
| body: ${{ steps.changelog.outputs.release_body }} | |
| draft: false | |
| prerelease: false | |
| generate_release_notes: false # 不使用GitHub自动生成,使用我们自己的changelog | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Output release info | |
| if: steps.check-version.outputs.should_release == 'true' | |
| shell: bash | |
| run: | | |
| echo "Release created successfully!" | |
| echo "Version: v${{ steps.determine-version.outputs.release_version }}" | |
| echo "Tag: ${{ steps.determine-version.outputs.tag_name }}" | |
| echo "Release URL: ${{ steps.create-release.outputs.html_url }}" |