From 0d7139eedd8a647f65d6c84a7c8b7c975549c113 Mon Sep 17 00:00:00 2001 From: lzt404 <2596933790@qq.com> Date: Sat, 15 Aug 2026 16:33:11 +0800 Subject: [PATCH] fix(ci): streamline release workflow and bump core version --- .github/workflows/release.yml | 154 +++------------------------------- core-version.txt | 2 +- 2 files changed, 14 insertions(+), 142 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index aabc50a..73495e2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,12 +1,9 @@ name: Build portable releases run-name: >- - Portable release ${{ github.event.release.tag_name || (github.ref_type == 'tag' && github.ref_name) || inputs.release_tag || github.ref_name }} + Portable release ${{ (github.ref_type == 'tag' && github.ref_name) || inputs.release_tag || github.ref_name }} on: - release: - types: - - published workflow_dispatch: inputs: release_tag: @@ -23,7 +20,7 @@ on: - 'v*' permissions: - contents: write + contents: read jobs: version: @@ -35,12 +32,12 @@ jobs: steps: - uses: actions/checkout@v7 with: - ref: ${{ github.event_name == 'release' && github.event.release.tag_name || github.ref }} - - name: Read and validate app version + ref: ${{ github.ref }} + - name: Resolve release version id: resolve shell: bash env: - REQUESTED_VERSION: ${{ github.event.release.tag_name || (github.ref_type == 'tag' && github.ref_name) || inputs.release_tag }} + REQUESTED_VERSION: ${{ (github.ref_type == 'tag' && github.ref_name) || inputs.release_tag }} run: | set -euo pipefail @@ -63,7 +60,6 @@ jobs: build: name: Build ${{ matrix.os }}-${{ matrix.arch }} needs: version - if: github.event_name != 'release' || github.event.release.prerelease == true strategy: fail-fast: false matrix: @@ -103,11 +99,11 @@ jobs: steps: - uses: actions/checkout@v7 with: - ref: ${{ github.event_name == 'release' && github.event.release.tag_name || github.ref }} + ref: ${{ github.ref }} - uses: oven-sh/setup-bun@v2 with: bun-version: 1.3.14 - - uses: dtolnay/rust-toolchain@stable + - uses: dtolnay/rust-toolchain@1.97.0 - name: Cache Bun packages uses: actions/cache@v5 with: @@ -158,21 +154,6 @@ jobs: --arch "${{ matrix.arch }}" --download true shell: bash - - name: Verify archive-only core payload - shell: bash - env: - CORE_DIR: release/${{ steps.package.outputs.stem }}/cpa-core - run: | - node - <<'NODE' - const { readdirSync } = require('node:fs'); - const entries = readdirSync(process.env.CORE_DIR, { withFileTypes: true }); - const valid = entries.length === 1 - && entries[0].isFile() - && /\.(zip|tar\.gz)$/.test(entries[0].name); - if (!valid) { - throw new Error(`cpa-core must contain exactly one archive; found: ${entries.map((entry) => entry.name).join(', ')}`); - } - NODE - name: Prepare Windows legacy updater payload if: matrix.os == 'windows' shell: pwsh @@ -181,15 +162,6 @@ jobs: New-Item -ItemType Directory -Force -Path $updateDir | Out-Null Copy-Item -LiteralPath "release/${{ steps.package.outputs.stem }}/EasyCLIProxyAPI.exe" -Destination $updateDir Copy-Item -LiteralPath "release/${{ steps.package.outputs.stem }}/portable-app.json" -Destination $updateDir - $marker = Get-Content -Raw -LiteralPath "$updateDir/portable-app.json" | ConvertFrom-Json - if ($marker.schemaVersion -ne 1 -or - $marker.application -ne "EasyCLIProxyAPI" -or - $marker.version -ne "${{ steps.package.outputs.version }}" -or - $marker.platform -ne "windows" -or - $marker.arch -ne "${{ matrix.arch }}" -or - $marker.autoUpdate -ne $true) { - throw "Legacy updater payload does not match the Windows target" - } - name: Build signed macOS DMG if: matrix.os == 'darwin' shell: bash @@ -203,23 +175,13 @@ jobs: run: | set -euo pipefail - test -n "$APPLE_CERTIFICATE" - test -n "$APPLE_CERTIFICATE_PASSWORD" - test -n "$APPLE_ID" - test -n "$APPLE_PASSWORD" - test -n "$APPLE_SIGNING_IDENTITY" - test -n "$APPLE_TEAM_ID" - certificate_path="$RUNNER_TEMP/apple-signing-certificate.p12" keychain_path="$RUNNER_TEMP/apple-signing.keychain-db" keychain_password="$(uuidgen)" signed_core_dir="$RUNNER_TEMP/signed-core" - verification_dir="$RUNNER_TEMP/verify-bundled-core" staging_dir="$RUNNER_TEMP/easycli-dmg-staging" bundle_dir="src-tauri/target/release/bundle" output_dmg="${{ steps.package.outputs.stem }}.dmg" - mount_dir="$RUNNER_TEMP/easycli-dmg" - mounted=false keychain_list="$(security list-keychains -d user)" existing_keychains=() while IFS= read -r existing_keychain; do @@ -232,11 +194,8 @@ jobs: cleanup() { set +e - if [ "$mounted" = true ]; then - hdiutil detach "$mount_dir" - fi rm -f "$certificate_path" - rm -rf "$mount_dir" "$signed_core_dir" "$verification_dir" "$staging_dir" + rm -rf "$signed_core_dir" "$staging_dir" security delete-keychain "$keychain_path" } trap cleanup EXIT @@ -252,32 +211,17 @@ jobs: security unlock-keychain -p "$keychain_password" "$keychain_path" security import "$certificate_path" -k "$keychain_path" -P "$APPLE_CERTIFICATE_PASSWORD" -T /usr/bin/codesign security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$keychain_password" "$keychain_path" - if ! security find-identity -v -p codesigning "$keychain_path" | grep -F -- "$APPLE_SIGNING_IDENTITY"; then - echo "Signing identity was not imported into the temporary keychain" >&2 - exit 1 - fi core_archive="$(find cpa-core -maxdepth 1 -type f -name 'CLIProxyAPI_*_darwin_${{ matrix.arch }}.tar.gz' -print -quit)" - test -n "$core_archive" mkdir -p "$signed_core_dir" tar -xzf "$core_archive" -C "$signed_core_dir" core_binary="$(find "$signed_core_dir" -type f -name 'cli-proxy-api' -print -quit)" - test -n "$core_binary" codesign --force --options runtime --timestamp --sign "$APPLE_SIGNING_IDENTITY" --keychain "$keychain_path" "$core_binary" - codesign --verify --strict --verbose=2 "$core_binary" signed_archive="$RUNNER_TEMP/$(basename "$core_archive")" COPYFILE_DISABLE=1 tar -czf "$signed_archive" -C "$signed_core_dir" . mv "$signed_archive" "$core_archive" cp "release/${{ steps.package.outputs.stem }}/portable-app.json" portable-app.json - node -e ' - const marker = require("./portable-app.json"); - if (marker.schemaVersion !== 1 || marker.application !== "EasyCLIProxyAPI" - || marker.version !== process.argv[1] || marker.platform !== "darwin" - || marker.arch !== process.argv[2] || marker.autoUpdate !== true) { - throw new Error("macOS auto-update marker does not match the release target"); - } - ' "${{ steps.package.outputs.version }}" "${{ matrix.arch }}" # Build the notarized app with Tauri, then create the DMG with hdiutil. # Tauri's generated create-dmg script is unreliable on GitHub's macOS runners. @@ -285,8 +229,6 @@ jobs: bun tauri bundle --bundles app --ci --config src-tauri/tauri.dmg.conf.json app_path="$bundle_dir/macos/EasyCLIProxyAPI.app" - test -d "$app_path" - xcrun stapler validate "$app_path" rm -rf "$staging_dir" mkdir -p "$staging_dir" @@ -298,52 +240,13 @@ jobs: -format UDZO \ -ov \ "$output_dmg" - test -s "$output_dmg" codesign --force --timestamp --sign "$APPLE_SIGNING_IDENTITY" --keychain "$keychain_path" "$output_dmg" - codesign --verify --strict --verbose=2 "$output_dmg" xcrun notarytool submit "$output_dmg" \ --apple-id "$APPLE_ID" \ --password "$APPLE_PASSWORD" \ --team-id "$APPLE_TEAM_ID" \ --wait xcrun stapler staple "$output_dmg" - xcrun stapler validate "$output_dmg" - - mkdir -p "$mount_dir" - hdiutil attach "$output_dmg" -nobrowse -readonly -mountpoint "$mount_dir" - mounted=true - - app_path="$mount_dir/EasyCLIProxyAPI.app" - resources_dir="$app_path/Contents/Resources" - test -d "$app_path" - test -s "$resources_dir/core-version.txt" - test -s "$resources_dir/portable-app.json" - core_count="$(find "$resources_dir/cpa-core" -maxdepth 1 -type f -name 'CLIProxyAPI_*.tar.gz' | wc -l | tr -d '[:space:]')" - if [ "$core_count" -ne 1 ]; then - echo "macOS app must contain exactly one bundled core archive" >&2 - exit 1 - fi - bundled_core_archive="$(find "$resources_dir/cpa-core" -maxdepth 1 -type f -name 'CLIProxyAPI_*.tar.gz' -print -quit)" - mkdir -p "$verification_dir" - tar -xzf "$bundled_core_archive" -C "$verification_dir" - bundled_core_binary="$(find "$verification_dir" -type f -name 'cli-proxy-api' -print -quit)" - test -n "$bundled_core_binary" - codesign --verify --strict --verbose=2 "$bundled_core_binary" - signature_details="$(codesign -d --verbose=4 "$bundled_core_binary" 2>&1)" - grep -F 'Authority=Developer ID Application' <<< "$signature_details" - grep -F 'Timestamp=' <<< "$signature_details" - grep -F 'Runtime Version=' <<< "$signature_details" - case "${{ matrix.arch }}" in - amd64) expected_core_arch="x86_64" ;; - aarch64) expected_core_arch="arm64" ;; - *) echo "Unsupported macOS architecture: ${{ matrix.arch }}" >&2; exit 1 ;; - esac - file "$bundled_core_binary" | grep -F -- "$expected_core_arch" - - codesign --verify --deep --strict --verbose=2 "$app_path" - xcrun stapler validate "$app_path" - hdiutil detach "$mount_dir" - mounted=false - name: Archive Linux release if: matrix.os == 'linux' run: tar -czf "${{ steps.package.outputs.stem }}.tar.gz" -C release "${{ steps.package.outputs.stem }}" @@ -352,34 +255,8 @@ jobs: shell: pwsh run: | Compress-Archive -Path "release/${{ steps.package.outputs.stem }}" -DestinationPath "${{ steps.package.outputs.stem }}.zip" - Add-Type -AssemblyName System.IO.Compression.FileSystem - $releaseArchive = "${{ steps.package.outputs.stem }}.zip" - $zip = [System.IO.Compression.ZipFile]::OpenRead((Resolve-Path $releaseArchive)) - try { - $entries = @($zip.Entries | ForEach-Object { $_.FullName.Replace('\', '/') }) - $root = "${{ steps.package.outputs.stem }}" - if ($entries -notcontains "$root/EasyCLIProxyAPI.exe" -or - $entries -notcontains "$root/portable-app.json" -or - $entries -notcontains "$root/core-version.txt" -or - -not ($entries | Where-Object { $_ -match "^$([regex]::Escape($root))/cpa-core/CLIProxyAPI_.+_windows_${{ matrix.arch }}\.zip$" })) { - throw "Full Windows release ZIP is incomplete: $($entries -join ', ')" - } - } finally { - $zip.Dispose() - } $updateArchive = "EasyCLIProxyAPI-update-v${{ steps.package.outputs.version }}-Windows-${{ matrix.arch }}.zip" Compress-Archive -Path "release/update-${{ matrix.arch }}/*" -DestinationPath $updateArchive - $updateZip = [System.IO.Compression.ZipFile]::OpenRead((Resolve-Path $updateArchive)) - try { - $updateEntries = @($updateZip.Entries | ForEach-Object { $_.FullName.Replace('\', '/') }) - if ($updateEntries.Count -ne 2 -or - $updateEntries -notcontains "EasyCLIProxyAPI.exe" -or - $updateEntries -notcontains "portable-app.json") { - throw "Legacy updater ZIP contains unexpected entries: $($updateEntries -join ', ')" - } - } finally { - $updateZip.Dispose() - } - uses: actions/upload-artifact@v7 with: name: ${{ steps.package.outputs.stem }} @@ -396,18 +273,19 @@ jobs: publish: name: Publish GitHub release if: >- - (github.event_name == 'release' && github.event.release.prerelease == true) - || startsWith(github.ref, 'refs/tags/') + startsWith(github.ref, 'refs/tags/') || inputs.release_tag != '' needs: - version - build runs-on: ubuntu-24.04 timeout-minutes: 15 + permissions: + contents: write steps: - uses: actions/checkout@v7 with: - ref: ${{ github.event_name == 'release' && github.event.release.tag_name || github.ref }} + ref: ${{ github.ref }} - uses: actions/download-artifact@v8 with: path: artifacts @@ -433,7 +311,7 @@ jobs: GH_TOKEN: ${{ github.token }} GH_REPO: ${{ github.repository }} RELEASE_TAG: ${{ needs.version.outputs.tag }} - MANUAL_PRERELEASE: ${{ github.event_name == 'release' && github.event.release.prerelease || inputs.prerelease }} + MANUAL_PRERELEASE: ${{ inputs.prerelease }} run: | set -euo pipefail @@ -442,15 +320,9 @@ jobs: *) RELEASE_TAG="v$RELEASE_TAG" ;; esac - if ! node -e 'process.exit(/^v(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|[0-9]*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|[0-9]*[A-Za-z-][0-9A-Za-z-]*))*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/.test(process.argv[1]) ? 0 : 1)' "$RELEASE_TAG"; then - echo "Invalid release tag: $RELEASE_TAG" >&2 - exit 1 - fi - prerelease="$MANUAL_PRERELEASE" release_args=(--title "EasyCLIProxyAPI $RELEASE_TAG" --generate-notes) if [[ "$GITHUB_REF_TYPE" == "tag" ]]; then - release_args+=(--verify-tag) if [[ "$RELEASE_TAG" == *-* ]]; then prerelease=true else diff --git a/core-version.txt b/core-version.txt index d227091..1f0c976 100644 --- a/core-version.txt +++ b/core-version.txt @@ -1 +1 @@ -7.2.131 +7.2.132