From 255429d529abe1e39b768f2b499540c1f9e21fa1 Mon Sep 17 00:00:00 2001 From: shumengya Date: Fri, 3 Jul 2026 16:55:12 +0800 Subject: [PATCH] fix: pass app_version to CI and ship Windows NSIS installer only Add app_version to workflow_dispatch inputs and worker dispatch payload. Collect only setup.exe from bundle/nsis, prefer installer URLs in release lookup, and use git-tag-safe job IDs. --- .github/workflows/build-app.yml | 23 +++++++++++++++-------- worker/src/routes/builds.ts | 11 +++++++++-- worker/src/services/github.ts | 22 ++++++++++++++-------- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/.github/workflows/build-app.yml b/.github/workflows/build-app.yml index ef10da0..2afc146 100644 --- a/.github/workflows/build-app.yml +++ b/.github/workflows/build-app.yml @@ -19,6 +19,10 @@ on: description: Application bundle identifier required: true type: string + app_version: + description: Application version string + required: true + type: string permissions: contents: write @@ -67,14 +71,17 @@ jobs: shell: pwsh run: | New-Item -ItemType Directory -Force -Path artifacts/windows | Out-Null - $bundleRoot = "template/src-tauri/target/release/bundle" - if (Test-Path $bundleRoot) { - Get-ChildItem -Path $bundleRoot -Recurse -Include *setup.exe,*.exe,*.msi -ErrorAction SilentlyContinue | - Copy-Item -Destination artifacts/windows -Force + $nsisDir = "template/src-tauri/target/release/bundle/nsis" + if (-not (Test-Path $nsisDir)) { + Write-Error "NSIS bundle directory not found: $nsisDir" + exit 1 } - Get-ChildItem -Path "template/src-tauri/target/release" -Filter "*.exe" -ErrorAction SilentlyContinue | - Where-Object { $_.Name -notmatch "wix|candle|light" } | - Copy-Item -Destination artifacts/windows -Force + $installers = Get-ChildItem -Path $nsisDir -Filter "*-setup.exe" + if (-not $installers) { + Write-Error "No NSIS installer (*-setup.exe) found in $nsisDir" + exit 1 + } + $installers | Copy-Item -Destination artifacts/windows -Force Get-ChildItem artifacts/windows - uses: actions/upload-artifact@v4 @@ -212,7 +219,7 @@ jobs: body: | Automated build for **${{ inputs.app_name }}** (English: `${{ inputs.app_name_en }}`, version: `${{ inputs.app_version }}`, ID: `${{ inputs.app_identifier }}`). - - Windows desktop installer/portable binary + - Windows NSIS installer (*-setup.exe) - Android APK (arm64-v8a, signed for sideload install) draft: false prerelease: true diff --git a/worker/src/routes/builds.ts b/worker/src/routes/builds.ts index de228e3..2a14c5e 100644 --- a/worker/src/routes/builds.ts +++ b/worker/src/routes/builds.ts @@ -1,4 +1,10 @@ -import { nanoid } from "nanoid"; +import { customAlphabet } from "nanoid"; + +// GitHub published releases reject tag names ending with '-'. +const generateJobId = customAlphabet( + "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", + 10, +); import type { Env } from "../env"; import { getBuild, @@ -112,7 +118,7 @@ async function createBuild(request: Request, env: Env): Promise { const buffer = new Uint8Array(await file.arrayBuffer()); const { normalizedBuffer } = validateZipBuffer(buffer, maxUploadBytes(env)); - const jobId = nanoid(10); + const jobId = generateJobId(); const slug = slugifyIdentifier(appNameEn) || jobId.toLowerCase(); const appIdentifier = normalizeAppIdentifier( identifierInput || `com.web2app.${slug}`, @@ -148,6 +154,7 @@ async function createBuild(request: Request, env: Env): Promise { appName: appNameZh, appNameEn, appIdentifier, + appVersion, }); await updateBuild(env, jobId, { diff --git a/worker/src/services/github.ts b/worker/src/services/github.ts index cd20065..48be194 100644 --- a/worker/src/services/github.ts +++ b/worker/src/services/github.ts @@ -115,6 +115,7 @@ export async function triggerBuildWorkflow( appName: string; appNameEn: string; appIdentifier: string; + appVersion: string; }, ): Promise { const { owner, repo, branch } = getGitHubConfig(env); @@ -133,6 +134,7 @@ export async function triggerBuildWorkflow( app_name: input.appName, app_name_en: input.appNameEn, app_identifier: input.appIdentifier, + app_version: input.appVersion, }, }), }, @@ -217,18 +219,19 @@ export async function getReleaseAssets( assets: Array<{ name: string; browser_download_url: string }>; }; - let windowsUrl: string | null = null; + let windowsInstallerUrl: string | null = null; + let windowsFallbackUrl: string | null = null; let androidUrl: string | null = null; for (const asset of release.assets) { const name = asset.name.toLowerCase(); - if ( - !windowsUrl && - (name.endsWith(".exe") || - name.endsWith(".msi") || - name.includes("windows")) + if (name.endsWith("-setup.exe") || name.endsWith(".msi")) { + windowsInstallerUrl = asset.browser_download_url; + } else if ( + !windowsFallbackUrl && + name.endsWith(".exe") ) { - windowsUrl = asset.browser_download_url; + windowsFallbackUrl = asset.browser_download_url; } if ( !androidUrl && @@ -238,7 +241,10 @@ export async function getReleaseAssets( } } - return { windowsUrl, androidUrl }; + return { + windowsUrl: windowsInstallerUrl ?? windowsFallbackUrl, + androidUrl, + }; } export function getActionsRunUrl(env: Env, runId: number | null): string | null {