ci: fix partially missing release body #53
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: Release | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| workflow_dispatch: | |
| inputs: | |
| tag_name: | |
| description: 'Release tag name (e.g.: v1.0.0)' | |
| required: true | |
| type: string | |
| prerelease: | |
| description: 'Mark as pre-release' | |
| required: false | |
| default: false | |
| type: boolean | |
| jobs: | |
| prepare: | |
| name: Prepare Release | |
| runs-on: ubuntu-latest | |
| outputs: | |
| changelog: ${{ steps.changelog.outputs.CHANGELOG_CONTENT }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Extract changelog for current version | |
| id: changelog | |
| shell: bash | |
| run: | | |
| VERSION=$(node -p "require('./package.json').version") | |
| echo "Looking for version: $VERSION" | |
| CHANGELOG_FILE=$(mktemp) | |
| awk "/^## \\[?v?${VERSION//./\\.}\]?/ {flag=1; next} /^## / && flag {flag=0} flag {print}" CHANGELOG.md > "$CHANGELOG_FILE" | |
| if [ -s "$CHANGELOG_FILE" ]; then | |
| { | |
| echo "CHANGELOG_CONTENT<<EOF" | |
| cat "$CHANGELOG_FILE" | |
| echo "EOF" | |
| } >> $GITHUB_OUTPUT | |
| echo "Found changelog content" | |
| else | |
| echo "CHANGELOG_CONTENT=See the assets to download and install this version." >> $GITHUB_OUTPUT | |
| echo "No matching changelog found for version $VERSION" | |
| fi | |
| rm -f "$CHANGELOG_FILE" | |
| build-linux: | |
| name: Build Linux | |
| runs-on: ${{ matrix.os }} | |
| needs: prepare | |
| strategy: | |
| matrix: | |
| include: | |
| - os: ubuntu-22.04 | |
| rust_target: x86_64-unknown-linux-gnu | |
| - os: ubuntu-22.04-arm | |
| rust_target: aarch64-unknown-linux-gnu | |
| environment: TAURI_KEY | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Install Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10 | |
| run_install: false | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.rust_target }} | |
| - name: Rust cache | |
| uses: swatinem/rust-cache@v2 | |
| with: | |
| workspaces: "./src-tauri -> target" | |
| key: ${{ matrix.rust_target }} | |
| shared-key: "reina-manager-build" | |
| - name: Install Mold | |
| uses: rui314/setup-mold@v1 | |
| - name: Install system dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y libgtk-3-dev libsoup-3.0-dev libwebkit2gtk-4.0-dev libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf clang | |
| - name: Install dependencies | |
| run: pnpm install | |
| - name: Build and Upload to Draft Release | |
| uses: tauri-apps/tauri-action@v0 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} | |
| TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} | |
| TAURI_UPDATER_ACTIVE: true | |
| with: | |
| tagName: ${{ github.ref_name }} | |
| releaseName: ${{ github.ref_name }} | |
| releaseBody: ${{ needs.prepare.outputs.changelog }} | |
| releaseDraft: true | |
| prerelease: false | |
| includeUpdaterJson: true | |
| includeRelease: true | |
| tauriScript: pnpm tauri | |
| args: --target ${{ matrix.rust_target }} | |
| build-windows: | |
| name: Build Windows | |
| runs-on: windows-latest | |
| needs: prepare | |
| strategy: | |
| matrix: | |
| rust_target: [ x86_64-pc-windows-msvc, aarch64-pc-windows-msvc ] | |
| environment: TAURI_KEY | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Install Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 24 | |
| - name: Install pnpm | |
| uses: pnpm/action-setup@v4 | |
| with: | |
| version: 10 | |
| run_install: false | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.rust_target }} | |
| - name: Rust cache | |
| uses: swatinem/rust-cache@v2 | |
| with: | |
| workspaces: "./src-tauri -> target" | |
| shared-key: ${{ matrix.rust_target }} | |
| save-if: false | |
| - name: Configure Rust linker (Windows lld) | |
| shell: bash | |
| run: | | |
| mkdir -p .cargo | |
| echo "Configuring lld for Windows..." | |
| cat >> .cargo/config.toml <<EOF | |
| [target.x86_64-pc-windows-msvc] | |
| linker = "lld-link" | |
| [target.aarch64-pc-windows-msvc] | |
| linker = "lld-link" | |
| EOF | |
| - name: Install dependencies | |
| run: pnpm install | |
| - name: Get version | |
| id: get_version | |
| shell: bash | |
| run: | | |
| VERSION=$(node -p "require('./package.json').version") | |
| echo "VERSION=$VERSION" >> $GITHUB_OUTPUT | |
| echo "Version is $VERSION" | |
| - name: Compute short target name | |
| id: short | |
| shell: bash | |
| run: | | |
| case "${{ matrix.rust_target }}" in | |
| *x86_64-pc-windows*) SHORT=win_x64 ;; | |
| *aarch64-pc-windows*) SHORT=win_arm64 ;; | |
| *) SHORT=unknown ;; | |
| esac | |
| echo "SHORT=$SHORT" >> $GITHUB_OUTPUT | |
| - name: Build and Upload to Draft Release | |
| uses: tauri-apps/tauri-action@v0 | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} | |
| TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} | |
| TAURI_UPDATER_ACTIVE: true | |
| with: | |
| tagName: ${{ github.ref_name }} | |
| releaseName: ${{ github.ref_name }} | |
| releaseBody: ${{ needs.prepare.outputs.changelog }} | |
| releaseDraft: true | |
| prerelease: false | |
| includeUpdaterJson: true | |
| includeRelease: true | |
| tauriScript: pnpm tauri | |
| args: --target ${{ matrix.rust_target }} | |
| - name: Prepare portable package (Windows) | |
| shell: pwsh | |
| run: | | |
| $version = "${{ steps.get_version.outputs.VERSION }}" | |
| $short = "${{ steps.short.outputs.SHORT }}" | |
| $target = "${{ matrix.rust_target }}" | |
| $portableRoot = "src-tauri/target/$target/release/portable/ReinaManager_${version}_${short}" | |
| $resourcesDataDir = Join-Path $portableRoot "resources/data" | |
| $zipPath = "src-tauri/target/$target/release/ReinaManager_${version}_${short}-portable.zip" | |
| if (Test-Path $portableRoot) { | |
| Remove-Item $portableRoot -Recurse -Force | |
| } | |
| if (Test-Path $zipPath) { | |
| Remove-Item $zipPath -Force | |
| } | |
| New-Item -ItemType Directory -Path $resourcesDataDir -Force | Out-Null | |
| @" | |
| 该文件夹为数据库文件夹,删除该文件夹则退出便携模式,反之则保持便携模式。 | |
| This folder stores the database. Deleting this folder exits portable mode; keeping it preserves portable mode. | |
| "@ | Set-Content -Path (Join-Path $resourcesDataDir "readme.txt") -Encoding UTF8 | |
| Copy-Item "src-tauri/target/$target/release/ReinaManager.exe" "$portableRoot/ReinaManager.exe" | |
| Compress-Archive -Path "$portableRoot/*" -DestinationPath $zipPath | |
| - name: Upload portable package to Draft Release | |
| shell: bash | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| gh release upload "${{ github.ref_name }}" \ | |
| "src-tauri/target/${{ matrix.rust_target }}/release/ReinaManager_${{ steps.get_version.outputs.VERSION }}_${{ steps.short.outputs.SHORT }}-portable.zip" \ | |
| --clobber | |
| finalize-release: | |
| name: Finalize Release | |
| runs-on: ubuntu-latest | |
| needs: [prepare, build-linux, build-windows] | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Determine release type | |
| id: release-type | |
| shell: bash | |
| run: | | |
| if [[ "${{ github.ref_name }}" == *"alpha"* ]] || [[ "${{ github.ref_name }}" == *"beta"* ]] || [[ "${{ github.ref_name }}" == *"rc"* ]] || [[ "${{ github.ref_name }}" == *"pre"* ]] || [[ "${{ github.event.inputs.prerelease }}" == "true" ]]; then | |
| echo "IS_PRERELEASE=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "IS_PRERELEASE=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Prepare Release Body | |
| shell: bash | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| TAG_NAME="${{ github.ref_name }}" | |
| # 从 GitHub API 获取草稿 release 的所有资源文件名 | |
| ASSETS_JSON=$(gh release view "$TAG_NAME" --json assets --jq '.assets | .[] | .name') | |
| # 解析 Windows 产物 | |
| X64_MSI=$(echo "$ASSETS_JSON" | grep -E "_x64_.*\.msi$" || echo "") | |
| ARM64_MSI=$(echo "$ASSETS_JSON" | grep -E "_arm64_.*\.msi$" || echo "") | |
| X64_PORTABLE=$(echo "$ASSETS_JSON" | grep -E "_win_x64-portable\.zip$" || echo "") | |
| ARM64_PORTABLE=$(echo "$ASSETS_JSON" | grep -E "_win_arm64-portable\.zip$" || echo "") | |
| # 解析 Linux 产物 (AppImage & deb) | |
| X64_APPIMAGE=$(echo "$ASSETS_JSON" | grep -E "amd64.*\.AppImage$" || echo "") | |
| X64_DEB=$(echo "$ASSETS_JSON" | grep -E "amd64.*\.deb$" || echo "") | |
| ARM64_APPIMAGE=$(echo "$ASSETS_JSON" | grep -E "aarch64.*\.AppImage$" || echo "") | |
| ARM64_DEB=$(echo "$ASSETS_JSON" | grep -E "arm64.*\.deb$" || echo "") | |
| CHANGELOG="${{ needs.prepare.outputs.changelog }}" | |
| # 构建下载链接 | |
| BASE_URL="https://github.com/${{ github.repository }}/releases/download/$TAG_NAME" | |
| DOWNLOAD_SECTION=$(cat <<EOF | |
| --- | |
| ### 📥 下载地址 (Download) | |
|  | |
| **Windows** (不支持 Win7) | |
| - [**64位 (x64)**]($BASE_URL/$X64_MSI) | |
| - [**ARM64**]($BASE_URL/$ARM64_MSI) | |
| - [**便携版 (x64)**]($BASE_URL/$X64_PORTABLE) | |
| - [**便携版 (ARM64)**]($BASE_URL/$ARM64_PORTABLE) | |
| **Linux** | |
| - [**AppImage (x64)**]($BASE_URL/$X64_APPIMAGE) | |
| - [**Debian/Ubuntu (.deb x64)**]($BASE_URL/$X64_DEB) | |
| - [**AppImage (ARM64)**]($BASE_URL/$ARM64_APPIMAGE) | |
| - [**Debian/Ubuntu (.deb ARM64)**]($BASE_URL/$ARM64_DEB) | |
| EOF | |
| ) | |
| FINAL_BODY=$(cat <<EOF | |
| $CHANGELOG | |
| $DOWNLOAD_SECTION | |
| EOF | |
| ) | |
| { | |
| echo "body<<EOF" | |
| echo "$FINAL_BODY" | |
| echo "EOF" | |
| } >> $GITHUB_OUTPUT | |
| - name: Publish Final Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ github.ref_name }} | |
| body: ${{ steps.release_body.outputs.body }} | |
| draft: false | |
| prerelease: ${{ steps.release-type.outputs.IS_PRERELEASE }} | |
| update_cdn_urls: | |
| name: Update CDN URLs in latest.json | |
| runs-on: ubuntu-latest | |
| needs: finalize-release # 等待 release 正式发布 | |
| if: startsWith(github.ref, 'refs/tags/') | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6 | |
| - name: Update latest.json with CDN URLs | |
| shell: bash | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| TAG_NAME="${{ github.ref_name }}" | |
| URL="https://github.com/${{ github.repository }}/releases/download/$TAG_NAME/latest.json" | |
| n=0 | |
| until [ "$n" -ge 5 ]; do | |
| curl -L -f -o latest.json "$URL" && break | |
| n=$((n+1)) | |
| sleep 5 | |
| done | |
| if [ ! -f "latest.json" ]; then | |
| echo "Error: Could not download latest.json after several retries." | |
| exit 1 | |
| fi | |
| jq '.platforms |= with_entries(.value.url |= "https://gh.huoshen80.top/\(.)")' latest.json > latest_modified.json | |
| mv -f latest_modified.json latest.json | |
| gh release upload $TAG_NAME "latest.json" --clobber | |
| echo "Successfully updated latest.json with CDN URLs" |