style(format): oxfmt 全量格式化 + 排除 vendored 技能,修复 format:check 门 #2
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: Build and Release | |
| permissions: | |
| contents: write | |
| issues: read | |
| pull-requests: read | |
| actions: write | |
| on: | |
| push: | |
| branches: [dev] | |
| tags: | |
| - '*' | |
| env: | |
| BUN_INSTALL_REGISTRY: 'https://registry.npmjs.org/' | |
| jobs: | |
| # 独立 code-quality job,供桌面构建和 web-cli 打包共用,避免重复跑 | |
| code-quality: | |
| name: Code Quality | |
| runs-on: ubuntu-latest | |
| if: github.ref == 'refs/heads/dev' || (startsWith(github.ref, 'refs/tags/') && !contains(github.ref, '-dev-')) | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22' | |
| - name: Setup bun | |
| uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install dependencies | |
| run: bun install --frozen-lockfile | |
| - name: Run postinstall | |
| run: bun run postinstall || true | |
| - name: Run ESLint | |
| run: bun run lint | |
| - name: Check Prettier formatting | |
| run: bun run format:check | |
| - name: TypeScript type check | |
| run: bunx tsc --noEmit | |
| - name: Run unit tests | |
| run: bunx vitest run | |
| build-pipeline: | |
| name: Build Pipeline | |
| uses: ./.github/workflows/_build-reusable.yml | |
| needs: code-quality | |
| # dev 分支或正式 tag 触发构建(排除 -dev- tag,避免重复构建) | |
| if: needs.code-quality.result == 'success' && (github.ref == 'refs/heads/dev' || (startsWith(github.ref, 'refs/tags/') && !contains(github.ref, '-dev-'))) | |
| with: | |
| skip_code_quality: true | |
| matrix: >- | |
| {"include":[ | |
| {"platform":"macos-arm64","os":"macos-14","command":"node scripts/build-with-builder.js arm64 --mac --arm64","artifact-name":"macos-build-arm64","arch":"arm64"}, | |
| {"platform":"macos-x64","os":"macos-14","command":"node scripts/build-with-builder.js x64 --mac --x64","artifact-name":"macos-build-x64","arch":"x64"}, | |
| {"platform":"windows-x64","os":"windows-2022","command":"node scripts/build-with-builder.js x64 --win --x64","artifact-name":"windows-build-x64","arch":"x64"}, | |
| {"platform":"windows-arm64","os":"windows-11-arm","command":"node scripts/build-with-builder.js arm64 --win --arm64","artifact-name":"windows-build-arm64","arch":"arm64"}, | |
| {"platform":"linux-x64","os":"ubuntu-latest","command":"node scripts/build-with-builder.js x64 --linux --x64","artifact-name":"linux-build-x64","arch":"x64"}, | |
| {"platform":"linux-arm64","os":"ubuntu-24.04-arm","command":"node scripts/build-with-builder.js arm64 --linux --arm64","artifact-name":"linux-build-arm64","arch":"arm64"} | |
| ]} | |
| secrets: inherit | |
| pack-web-cli: | |
| name: Pack Web CLI | |
| uses: ./.github/workflows/pack-web-cli.yml | |
| needs: code-quality | |
| # 与桌面构建同频触发:dev 分支或正式 tag(排除 -dev- tag) | |
| if: needs.code-quality.result == 'success' && (github.ref == 'refs/heads/dev' || (startsWith(github.ref, 'refs/tags/') && !contains(github.ref, '-dev-'))) | |
| with: | |
| ref: '' | |
| append_commit_hash: false | |
| skip_code_quality: true | |
| secrets: inherit | |
| # 自动重试 workflow(当构建失败时) | |
| auto-retry-workflow: | |
| name: Auto Retry on Build Failure | |
| runs-on: ubuntu-latest | |
| needs: build-pipeline | |
| # 关键:只在首次失败时触发,避免无限循环 | |
| if: | | |
| failure() && | |
| github.run_attempt == 1 && | |
| (github.event_name == 'push' || github.event_name == 'schedule') | |
| steps: | |
| - name: Log retry information | |
| run: | | |
| echo "==========================================" | |
| echo "🔄 Auto retry triggered (first failure)" | |
| echo "==========================================" | |
| echo "Build failed on first attempt, preparing auto retry..." | |
| echo "Current attempt: ${{ github.run_attempt }}" | |
| echo "Wait strategy: 5 minutes cooldown before retry" | |
| echo "==========================================" | |
| - name: Wait before retry (5 min cooldown) | |
| run: | | |
| echo "⏳ Waiting 5 minutes before retry..." | |
| echo "Start: $(date)" | |
| sleep 300 | |
| echo "End: $(date)" | |
| echo "Triggering retry..." | |
| - name: Trigger workflow rerun | |
| run: | | |
| echo "🔄 Triggering full workflow rerun (attempt 2)..." | |
| # Use re-run API (not rerun-failed-jobs, to avoid loops) | |
| response=$(curl -X POST \ | |
| -H "Accept: application/vnd.github.v3+json" \ | |
| -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \ | |
| -w "\n%{http_code}" \ | |
| https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/rerun) | |
| http_code=$(echo "$response" | tail -n1) | |
| if [ "$http_code" = "201" ]; then | |
| echo "" | |
| echo "✅ Retry triggered successfully" | |
| echo "This will be attempt 2" | |
| echo "Details: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| else | |
| echo "" | |
| echo "❌ Retry trigger failed, HTTP status: $http_code" | |
| echo "Response:" | |
| echo "$response" | head -n-1 | |
| exit 1 | |
| fi | |
| # 自动创建tag(仅 dev 分支推送时) | |
| create-tag: | |
| name: Create Tag from Branch | |
| runs-on: ubuntu-latest | |
| needs: [build-pipeline] | |
| if: success() && github.ref == 'refs/heads/dev' | |
| outputs: | |
| tag_name: ${{ steps.create_tag.outputs.tag_name }} | |
| is_dev: ${{ steps.create_tag.outputs.is_dev }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| with: | |
| # GH_TOKEN is a PAT with `repo` + `workflow` scopes — required because | |
| # tag pushes whose reachable history contains .github/workflows/ | |
| # changes are rejected for the built-in GITHUB_TOKEN (lacks the | |
| # `workflow` scope, which GITHUB_TOKEN can never grant). | |
| token: ${{ secrets.GH_TOKEN }} | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '22' | |
| - name: Setup bun | |
| uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Create and push tag | |
| id: create_tag | |
| run: | | |
| VERSION=$(node -p "require('./package.json').version") | |
| COMMIT_SHORT=$(git rev-parse --short HEAD) | |
| BRANCH_NAME=${GITHUB_REF#refs/heads/} | |
| # 根据分支确定 tag 格式 | |
| if [ "$BRANCH_NAME" = "dev" ]; then | |
| TAG_NAME="v${VERSION}-dev-${COMMIT_SHORT}" | |
| IS_DEV="true" | |
| echo "🔧 Development release: $TAG_NAME" | |
| else | |
| TAG_NAME="v$VERSION" | |
| IS_DEV="false" | |
| echo "🚀 Production release: $TAG_NAME" | |
| fi | |
| echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT | |
| echo "is_dev=$IS_DEV" >> $GITHUB_OUTPUT | |
| # 检查远程tag是否已存在 | |
| if git ls-remote --tags origin | grep -q "refs/tags/$TAG_NAME$"; then | |
| if [ "$IS_DEV" = "false" ]; then | |
| # Main 分支:需要递增版本并修改 package.json | |
| echo "⚠️ Tag $TAG_NAME already exists, auto-incrementing version..." | |
| if [[ $VERSION =~ ^([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then | |
| MAJOR=${BASH_REMATCH[1]} | |
| MINOR=${BASH_REMATCH[2]} | |
| PATCH=${BASH_REMATCH[3]} | |
| NEW_PATCH=$((PATCH + 1)) | |
| NEW_VERSION="${MAJOR}.${MINOR}.${NEW_PATCH}" | |
| echo "📝 Updating package.json version to $NEW_VERSION" | |
| # 更新 package.json 版本号 | |
| bun pm version $NEW_VERSION | |
| # 配置git用户信息 | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| # 提交版本更新 | |
| git add package.json bun.lock | |
| git commit -m "chore: bump version to $NEW_VERSION" | |
| git remote set-url origin https://x-access-token:${{ secrets.GH_TOKEN }}@github.com/${{ github.repository }}.git | |
| git push origin $BRANCH_NAME | |
| # 获取新的 commit ID | |
| COMMIT_SHORT=$(git rev-parse --short HEAD) | |
| TAG_NAME="v${NEW_VERSION}-${COMMIT_SHORT}" | |
| echo "🚀 New tag with updated version: $TAG_NAME" | |
| echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT | |
| else | |
| TAG_NAME="v${VERSION}-${COMMIT_SHORT}" | |
| echo "⚠️ Fallback: creating tag with commit ID: $TAG_NAME" | |
| echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT | |
| fi | |
| else | |
| # Dev 分支 tag 已存在则失败(不应该发生) | |
| echo "⚠️ Dev tag $TAG_NAME already exists, this shouldn't happen" | |
| exit 1 | |
| fi | |
| fi | |
| # 配置git用户信息(如果前面没配置) | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| # 创建并推送tag | |
| echo "Creating tag: $TAG_NAME" | |
| git tag $TAG_NAME | |
| git remote set-url origin https://x-access-token:${{ secrets.GH_TOKEN }}@github.com/${{ github.repository }}.git | |
| git push origin $TAG_NAME | |
| echo "✅ Successfully created and pushed tag: $TAG_NAME" | |
| env: | |
| GH_TOKEN: ${{ secrets.GH_TOKEN }} | |
| # 发布到 GitHub Releases | |
| release: | |
| name: Create Release | |
| runs-on: ubuntu-latest | |
| needs: [build-pipeline, create-tag, pack-web-cli] | |
| # Tag 推送时 create-tag 会被跳过,所以需要检查两种情况(排除 -dev- tag 避免重复) | |
| if: always() && needs.build-pipeline.result == 'success' && needs.pack-web-cli.result == 'success' && (needs.create-tag.result == 'success' || (startsWith(github.ref, 'refs/tags/') && !contains(github.ref, '-dev-'))) | |
| # dev 分支使用 dev-release 环境,正式 tag 使用 release 环境 | |
| environment: ${{ needs.create-tag.outputs.is_dev == 'true' && 'dev-release' || 'release' }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Get version for release | |
| id: version | |
| run: | | |
| # 判断触发来源:正式 tag 推送 or dev 分支 | |
| if [[ "$GITHUB_REF" == refs/tags/* ]]; then | |
| # 正式 Tag 推送触发(-dev- tag 已被排除,不会到达这里) | |
| TAG_NAME="${GITHUB_REF#refs/tags/}" | |
| IS_DEV="false" | |
| echo "🚀 Creating stable release from tag: $TAG_NAME" | |
| else | |
| # dev 分支触发,使用 create-tag job 的输出 | |
| TAG_NAME="${{ needs.create-tag.outputs.tag_name }}" | |
| IS_DEV="${{ needs.create-tag.outputs.is_dev }}" | |
| echo "🔧 Creating development release: $TAG_NAME" | |
| fi | |
| echo "tag_name=$TAG_NAME" >> $GITHUB_OUTPUT | |
| echo "is_dev=$IS_DEV" >> $GITHUB_OUTPUT | |
| - name: Download all build artifacts | |
| uses: actions/download-artifact@v7 | |
| with: | |
| path: build-artifacts | |
| - name: Prepare release assets (normalize updater metadata) | |
| shell: bash | |
| run: bash scripts/prepare-release-assets.sh build-artifacts release-assets | |
| - name: Create Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.version.outputs.tag_name }} | |
| name: ${{ steps.version.outputs.is_dev == 'true' && format('Development Build {0}', steps.version.outputs.tag_name) || steps.version.outputs.tag_name }} | |
| files: | | |
| release-assets/**/*.exe | |
| release-assets/**/*.msi | |
| release-assets/**/*.dmg | |
| release-assets/**/*.deb | |
| release-assets/**/*.zip | |
| release-assets/**/*.yml | |
| release-assets/**/*.tar.gz | |
| release-assets/**/*.sha256 | |
| release-assets/install-web.sh | |
| generate_release_notes: true | |
| draft: true | |
| prerelease: ${{ steps.version.outputs.is_dev == 'true' || contains(steps.version.outputs.tag_name, 'beta') || contains(steps.version.outputs.tag_name, 'alpha') || contains(steps.version.outputs.tag_name, 'rc') }} | |
| env: | |
| GH_TOKEN: ${{ secrets.GH_TOKEN }} |