name: Release (Windows) on: push: tags: - "v*" permissions: contents: write jobs: build-windows-installer: runs-on: windows-latest steps: - name: Checkout uses: actions/checkout@v4 with: fetch-depth: 0 - name: Derive version from tag shell: pwsh run: | $tag = "${{ github.ref_name }}" $version = $tag -replace '^v', '' if ([string]::IsNullOrWhiteSpace($version)) { throw "Invalid tag: '$tag' (expected like v1.0.0)" } "TAG_NAME=$tag" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 "VERSION=$version" | Out-File -FilePath $env:GITHUB_ENV -Append -Encoding utf8 - name: Generate release notes from commits shell: pwsh run: | git fetch --force --tags $tag = $env:TAG_NAME if ([string]::IsNullOrWhiteSpace($tag)) { throw "TAG_NAME is empty" } $repo = "${{ github.repository }}" $prev = "" try { $commit = (git rev-list -n 1 $tag).Trim() if (-not [string]::IsNullOrWhiteSpace($commit)) { $prev = (git describe --tags --abbrev=0 "$commit^" 2>$null).Trim() } } catch {} if ([string]::IsNullOrWhiteSpace($prev)) { # Fallback: best-effort previous version tag by semver-ish sorting. $prev = (git tag --list "v*" --sort=-v:refname | Where-Object { $_ -ne $tag } | Select-Object -First 1) } $range = "" if (-not [string]::IsNullOrWhiteSpace($prev)) { $range = "$prev..$tag" } $lines = @() if (-not [string]::IsNullOrWhiteSpace($range)) { $lines = @(git log --no-merges --pretty=format:"- %s (%h)" --reverse $range) } else { # First release tag / missing history: include a small recent window. $lines = @(git log --no-merges --pretty=format:"- %s (%h)" --reverse -n 50) } if (-not $lines -or $lines.Count -eq 0) { $lines = @("- 修复了一些已知问题,提升了稳定性。") } $max = 60 if ($lines.Count -gt $max) { $total = $lines.Count $lines = @($lines | Select-Object -First $max) $lines += "- ...(共 $total 条提交,更多请查看完整变更链接)" } $body = @() $body += "## 更新内容 ($tag)" $body += "" $body += $lines if (-not [string]::IsNullOrWhiteSpace($prev)) { $body += "" $body += "完整变更: https://github.com/$repo/compare/$prev...$tag" } ($body -join "`n") | Out-File -FilePath release-notes.md -Encoding utf8 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: "20" cache: "npm" cache-dependency-path: | frontend/package-lock.json desktop/package-lock.json - name: Setup Python uses: actions/setup-python@v5 with: python-version-file: ".python-version" - name: Install uv shell: pwsh run: | python -m pip install --upgrade pip python -m pip install uv - name: Install frontend deps working-directory: frontend run: npm ci - name: Install desktop deps working-directory: desktop run: npm ci - name: Set desktop app version (electron-builder) working-directory: desktop shell: pwsh run: | npm version $env:VERSION --no-git-tag-version --allow-same-version - name: Build Windows installer working-directory: desktop run: npm run dist - name: Create GitHub Release and upload installer uses: softprops/action-gh-release@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ env.TAG_NAME }} name: ${{ env.TAG_NAME }} body_path: release-notes.md files: | desktop/dist/*Setup*.exe desktop/dist/*Setup*.exe.blockmap desktop/dist/latest.yml