From 4e5d320c360f380621d25f94baa669e42436ed8d Mon Sep 17 00:00:00 2001 From: Ivan Fontosh Date: Mon, 18 May 2026 08:26:43 +0800 Subject: [PATCH] =?UTF-8?q?=D1=84=D0=B8=D0=BA=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 1 + .nvmrc | 1 + app/shared/package.build.test.ts | 4 +- docs/MANUAL_MAC_UPDATE_UPLOAD.md | 6 +- package.json | 1 + scripts/ttrpg-release/prepare-release.ps1 | 47 ++++++++++--- scripts/ttrpg-release/publish.ps1 | 83 +++++++++++++++++++++-- scripts/wsl-pack-linux.sh | 19 ++++++ 8 files changed, 145 insertions(+), 17 deletions(-) create mode 100644 .gitattributes create mode 100644 .nvmrc create mode 100644 scripts/wsl-pack-linux.sh diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfdb8b7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.sh text eol=lf diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..941d7c0 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +22.22.3 diff --git a/app/shared/package.build.test.ts b/app/shared/package.build.test.ts index 68e2bb1..fb99e2b 100644 --- a/app/shared/package.build.test.ts +++ b/app/shared/package.build.test.ts @@ -13,7 +13,7 @@ void test('package.json: конфиг electron-builder (mac/win/linux)', () => { asar: boolean; asarUnpack: string[]; extraResources: { from: string; to: string }[]; - mac: { target: unknown }; + mac: { target: unknown; artifactName?: string }; linux: { target: unknown }; appImage?: { artifactName?: string }; nsis?: { artifactName?: string }; @@ -39,6 +39,8 @@ void test('package.json: конфиг electron-builder (mac/win/linux)', () => { ), ); assert.ok(Array.isArray(pkg.build.mac.target)); + assert.equal(pkg.build.mac.artifactName, '${productName}-${arch}.${ext}'); + assert.ok(!pkg.build.mac.artifactName?.includes('version')); assert.equal(pkg.build.toolsets?.appimage, '1.0.2'); assert.ok(Array.isArray(pkg.build.linux.target)); const linuxTargets = pkg.build.linux.target as { target: string; arch: string[] }[]; diff --git a/docs/MANUAL_MAC_UPDATE_UPLOAD.md b/docs/MANUAL_MAC_UPDATE_UPLOAD.md index b4f2efb..b108a97 100644 --- a/docs/MANUAL_MAC_UPDATE_UPLOAD.md +++ b/docs/MANUAL_MAC_UPDATE_UPLOAD.md @@ -10,9 +10,9 @@ npm run pack:mac В `release/` (имена **без версии**): -- `latest-mac.yml` -- `TTRPGPlayer-x64.dmg` -- `TTRPGPlayer-arm64.dmg` (если собирали arm64) +- `latest-mac.yml` — сгенерирован electron-builder, не копируйте старый с Windows +- `TTRPGPlayer-x64.zip` и `TTRPGPlayer-arm64.zip` — **нужны для автообновления** (поле `path` в yml) +- `TTRPGPlayer-x64.dmg`, `TTRPGPlayer-arm64.dmg` — опционально, для ручной установки Скопируйте эти файлы на Windows в общую папку релиза (вместе с Win/Linux) и залейте на VPS вместе с остальными. diff --git a/package.json b/package.json index 2d51306..9e710dc 100644 --- a/package.json +++ b/package.json @@ -105,6 +105,7 @@ }, "mac": { "category": "public.app-category.games", + "artifactName": "${productName}-${arch}.${ext}", "target": [ { "target": "dmg", diff --git a/scripts/ttrpg-release/prepare-release.ps1 b/scripts/ttrpg-release/prepare-release.ps1 index d524f35..61514d7 100644 --- a/scripts/ttrpg-release/prepare-release.ps1 +++ b/scripts/ttrpg-release/prepare-release.ps1 @@ -64,6 +64,11 @@ function Convert-ToWslPath([string]$winPath) { return $p } +function Get-WslLinuxBuildCommand([string]$WslProjectPath) { + # WSL Debian often has node 18 on PATH; scripts/wsl-pack-linux.sh uses nvm + .nvmrc. + return "cd '$WslProjectPath' && bash scripts/wsl-pack-linux.sh" +} + function Read-PackageVersion([string]$packageJsonPath) { $json = Get-Content -LiteralPath $packageJsonPath -Raw -Encoding UTF8 | ConvertFrom-Json return [string]$json.version @@ -100,21 +105,47 @@ function Invoke-Git { } } +function Write-GitLines($lines) { + foreach ($line in $lines) { + if ($line -is [System.Management.Automation.ErrorRecord]) { + Write-Host $line.ToString() + } else { + Write-Host ([string]$line) + } + } +} + +function Invoke-GitPush { + param( + [string]$ProjectRoot, + [string[]]$PushArgs + ) + $prevEap = $ErrorActionPreference + $ErrorActionPreference = 'Continue' + try { + $output = & git -C $ProjectRoot push @PushArgs 2>&1 + Write-GitLines $output + return $LASTEXITCODE + } finally { + $ErrorActionPreference = $prevEap + } +} + function Push-Git([string]$ProjectRoot, [string]$Remote, [string]$McpConfigPath) { $branch = (git -C $ProjectRoot rev-parse --abbrev-ref HEAD).Trim() Write-Host " > git push $Remote $branch" - & git -C $ProjectRoot push $Remote $branch 2>&1 | ForEach-Object { Write-Host $_ } - if ($LASTEXITCODE -eq 0) { + $exitCode = Invoke-GitPush $ProjectRoot @($Remote, $branch) + if ($exitCode -eq 0) { return } $pushUrl = Get-GiteaPushUrl $McpConfigPath if (-not $pushUrl) { - throw "git push failed and no Gitea token in mcp config" + throw "git push failed (exit $exitCode) and no Gitea token in mcp config ($McpConfigPath)" } Write-Host " > git push via Gitea token URL" - & git -C $ProjectRoot push $pushUrl "HEAD:${branch}" 2>&1 | ForEach-Object { Write-Host $_ } - if ($LASTEXITCODE -ne 0) { - throw "git push failed (exit $LASTEXITCODE)" + $exitCode = Invoke-GitPush $ProjectRoot @($pushUrl, "HEAD:${branch}") + if ($exitCode -ne 0) { + throw "git push failed (exit $exitCode)" } } @@ -252,7 +283,7 @@ if ($SkipLinux) { } else { Write-Step 4 'Build Linux via WSL (npm ci + pack:linux)' $wslProject = Convert-ToWslPath $projectRoot - $wslCmd = "cd '$wslProject' && npm ci && npm run pack:linux" + $wslCmd = Get-WslLinuxBuildCommand $wslProject $wslArgs = @() if ($wslDistro) { $wslArgs += '-d', $wslDistro @@ -279,7 +310,7 @@ Write-Host '=== Prepare release done ===' -ForegroundColor Green Write-Host "Version: $newVersion" Write-Host '' Write-Host 'Next steps:' -ForegroundColor Yellow -Write-Host ' 1) Copy Mac files (latest-mac.yml, *.dmg) from Mac into release folder if needed' +Write-Host ' 1) Copy Mac files (latest-mac.yml, TTRPGPlayer-*.zip, optional *.dmg) from Mac into release folder if needed' Write-Host ' 2) Run publish.cmd to validate and upload to updates.mailib.ru' Write-Host '' diff --git a/scripts/ttrpg-release/publish.ps1 b/scripts/ttrpg-release/publish.ps1 index 7d55331..b867a72 100644 --- a/scripts/ttrpg-release/publish.ps1 +++ b/scripts/ttrpg-release/publish.ps1 @@ -1,7 +1,8 @@ # Copy of D:\TTRPG-Release\publish.ps1 - keep in sync when updating the release folder tool. param( - [switch]$CheckOnly + [switch]$CheckOnly, + [switch]$SkipMac ) Set-StrictMode -Version Latest @@ -38,6 +39,24 @@ function Write-Warn([string]$text) { Write-Host " [--] $text" -ForegroundColor Yellow } +function Get-YmlVersion([string]$ymlPath) { + $content = Get-Content -LiteralPath $ymlPath -Raw -Encoding UTF8 + $m = [regex]::Match($content, '(?m)^version:\s*(\S+)\s*$') + if ($m.Success) { + return $m.Groups[1].Value.Trim() + } + return $null +} + +function Get-YmlPrimaryPath([string]$ymlPath) { + $content = Get-Content -LiteralPath $ymlPath -Raw -Encoding UTF8 + $m = [regex]::Match($content, '(?m)^path:\s*(\S+)\s*$') + if ($m.Success) { + return $m.Groups[1].Value.Trim() + } + return $null +} + function Get-YmlReferencedFiles([string]$ymlPath) { $names = [System.Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase) $content = Get-Content -LiteralPath $ymlPath -Raw -Encoding UTF8 @@ -47,6 +66,20 @@ function Get-YmlReferencedFiles([string]$ymlPath) { return @($names) } +function Get-YmlOptionalUrls([string]$ymlPath) { + $primary = Get-YmlPrimaryPath $ymlPath + $names = [System.Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase) + $content = Get-Content -LiteralPath $ymlPath -Raw -Encoding UTF8 + foreach ($m in [regex]::Matches($content, '(?m)^\s*-\s*url:\s*(\S+)\s*$')) { + $name = $m.Groups[1].Value.Trim() + if ($primary -and $name.Equals($primary, [StringComparison]::OrdinalIgnoreCase)) { + continue + } + [void]$names.Add($name) + } + return @($names) +} + function Resolve-ReleaseFile([string]$name) { $direct = Join-Path $ReleaseDir $name if (Test-Path -LiteralPath $direct) { @@ -149,17 +182,50 @@ if ($linuxYmls.Count -eq 0) { Write-Title 'macOS (if latest-mac.yml present)' $macYml = Join-Path $ReleaseDir 'latest-mac.yml' -if (-not (Test-Path -LiteralPath $macYml)) { +if ($SkipMac) { + Write-Warn 'macOS skipped (-SkipMac)' +} elseif (-not (Test-Path -LiteralPath $macYml)) { Write-Warn 'No latest-mac.yml - skipping macOS' } else { Write-Ok 'latest-mac.yml' [void]$uploadFiles.Add($macYml) - foreach ($name in (Get-YmlReferencedFiles $macYml)) { + + $macVersion = Get-YmlVersion $macYml + $winYml = Join-Path $ReleaseDir 'latest.yml' + $winVersion = $null + if (Test-Path -LiteralPath $winYml) { + $winVersion = Get-YmlVersion $winYml + } + if ($macVersion -and $winVersion -and $macVersion -ne $winVersion) { + $errors.Add( + "macOS: latest-mac.yml is v$macVersion but latest.yml is v$winVersion (stale Mac feed). " + + 'On Mac run: npm run pack:mac, then copy latest-mac.yml + TTRPGPlayer-*.zip (+ optional *.dmg). ' + + 'Or publish Win/Linux only: publish.cmd -SkipMac' + ) + } + + $primaryName = Get-YmlPrimaryPath $macYml + if (-not $primaryName) { + $errors.Add('macOS: latest-mac.yml has no path: entry') + } else { + $primaryFile = Resolve-ReleaseFile $primaryName + if ($null -eq $primaryFile) { + $errors.Add( + "macOS: missing primary update file $primaryName (path in latest-mac.yml). " + + 'electron-updater on macOS needs the .zip from pack:mac, not only .dmg. Rebuild on Mac or use -SkipMac.' + ) + } else { + Write-Ok "primary update: $($primaryFile.Name)" + Add-FileToUploadSet $uploadFiles $primaryFile + } + } + + foreach ($name in (Get-YmlOptionalUrls $macYml)) { $file = Resolve-ReleaseFile $name if ($null -eq $file) { - $errors.Add("macOS: missing file $name (from latest-mac.yml)") + $warnings.Add("macOS: optional file missing (not uploaded): $name") } else { - Write-Ok $name + Write-Ok "optional: $($file.Name)" Add-FileToUploadSet $uploadFiles $file } } @@ -213,4 +279,11 @@ if ($LASTEXITCODE -ne 0) { Write-Title 'Done' Write-Host 'Verify:' Write-Host " ${feedUrl}latest.yml" +if (Test-Path -LiteralPath (Join-Path $ReleaseDir 'latest-linux.yml')) { + Write-Host " ${feedUrl}latest-linux.yml" +} +if (Test-Path -LiteralPath (Join-Path $ReleaseDir 'latest-mac.yml')) { + Write-Host " ${feedUrl}latest-mac.yml" +} + exit 0 diff --git a/scripts/wsl-pack-linux.sh b/scripts/wsl-pack-linux.sh new file mode 100644 index 0000000..deec4d0 --- /dev/null +++ b/scripts/wsl-pack-linux.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -euo pipefail + +cd "$(dirname "$0")/.." + +export NVM_DIR="${HOME}/.nvm" +if [[ -s "${NVM_DIR}/nvm.sh" ]]; then + # shellcheck source=/dev/null + . "${NVM_DIR}/nvm.sh" + nvm install + nvm use +else + echo "nvm not found at ${NVM_DIR}/nvm.sh (install nvm or use Node 20.19+ / 22.12+ for Vite)" >&2 + exit 1 +fi + +echo "Using $(node -v) ($(command -v node))" +npm ci +npm run pack:linux