This commit is contained in:
Ivan Fontosh
2026-05-18 08:26:43 +08:00
parent 411ac634f4
commit 4e5d320c36
8 changed files with 145 additions and 17 deletions
+1
View File
@@ -0,0 +1 @@
*.sh text eol=lf
+1
View File
@@ -0,0 +1 @@
22.22.3
+3 -1
View File
@@ -13,7 +13,7 @@ void test('package.json: конфиг electron-builder (mac/win/linux)', () => {
asar: boolean; asar: boolean;
asarUnpack: string[]; asarUnpack: string[];
extraResources: { from: string; to: string }[]; extraResources: { from: string; to: string }[];
mac: { target: unknown }; mac: { target: unknown; artifactName?: string };
linux: { target: unknown }; linux: { target: unknown };
appImage?: { artifactName?: string }; appImage?: { artifactName?: string };
nsis?: { 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.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.equal(pkg.build.toolsets?.appimage, '1.0.2');
assert.ok(Array.isArray(pkg.build.linux.target)); assert.ok(Array.isArray(pkg.build.linux.target));
const linuxTargets = pkg.build.linux.target as { target: string; arch: string[] }[]; const linuxTargets = pkg.build.linux.target as { target: string; arch: string[] }[];
+3 -3
View File
@@ -10,9 +10,9 @@ npm run pack:mac
В `release/` (имена **без версии**): В `release/` (имена **без версии**):
- `latest-mac.yml` - `latest-mac.yml` — сгенерирован electron-builder, не копируйте старый с Windows
- `TTRPGPlayer-x64.dmg` - `TTRPGPlayer-x64.zip` и `TTRPGPlayer-arm64.zip`**нужны для автообновления** (поле `path` в yml)
- `TTRPGPlayer-arm64.dmg` (если собирали arm64) - `TTRPGPlayer-x64.dmg`, `TTRPGPlayer-arm64.dmg` — опционально, для ручной установки
Скопируйте эти файлы на Windows в общую папку релиза (вместе с Win/Linux) и залейте на VPS вместе с остальными. Скопируйте эти файлы на Windows в общую папку релиза (вместе с Win/Linux) и залейте на VPS вместе с остальными.
+1
View File
@@ -105,6 +105,7 @@
}, },
"mac": { "mac": {
"category": "public.app-category.games", "category": "public.app-category.games",
"artifactName": "${productName}-${arch}.${ext}",
"target": [ "target": [
{ {
"target": "dmg", "target": "dmg",
+39 -8
View File
@@ -64,6 +64,11 @@ function Convert-ToWslPath([string]$winPath) {
return $p 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) { function Read-PackageVersion([string]$packageJsonPath) {
$json = Get-Content -LiteralPath $packageJsonPath -Raw -Encoding UTF8 | ConvertFrom-Json $json = Get-Content -LiteralPath $packageJsonPath -Raw -Encoding UTF8 | ConvertFrom-Json
return [string]$json.version 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) { function Push-Git([string]$ProjectRoot, [string]$Remote, [string]$McpConfigPath) {
$branch = (git -C $ProjectRoot rev-parse --abbrev-ref HEAD).Trim() $branch = (git -C $ProjectRoot rev-parse --abbrev-ref HEAD).Trim()
Write-Host " > git push $Remote $branch" Write-Host " > git push $Remote $branch"
& git -C $ProjectRoot push $Remote $branch 2>&1 | ForEach-Object { Write-Host $_ } $exitCode = Invoke-GitPush $ProjectRoot @($Remote, $branch)
if ($LASTEXITCODE -eq 0) { if ($exitCode -eq 0) {
return return
} }
$pushUrl = Get-GiteaPushUrl $McpConfigPath $pushUrl = Get-GiteaPushUrl $McpConfigPath
if (-not $pushUrl) { 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" Write-Host " > git push via Gitea token URL"
& git -C $ProjectRoot push $pushUrl "HEAD:${branch}" 2>&1 | ForEach-Object { Write-Host $_ } $exitCode = Invoke-GitPush $ProjectRoot @($pushUrl, "HEAD:${branch}")
if ($LASTEXITCODE -ne 0) { if ($exitCode -ne 0) {
throw "git push failed (exit $LASTEXITCODE)" throw "git push failed (exit $exitCode)"
} }
} }
@@ -252,7 +283,7 @@ if ($SkipLinux) {
} else { } else {
Write-Step 4 'Build Linux via WSL (npm ci + pack:linux)' Write-Step 4 'Build Linux via WSL (npm ci + pack:linux)'
$wslProject = Convert-ToWslPath $projectRoot $wslProject = Convert-ToWslPath $projectRoot
$wslCmd = "cd '$wslProject' && npm ci && npm run pack:linux" $wslCmd = Get-WslLinuxBuildCommand $wslProject
$wslArgs = @() $wslArgs = @()
if ($wslDistro) { if ($wslDistro) {
$wslArgs += '-d', $wslDistro $wslArgs += '-d', $wslDistro
@@ -279,7 +310,7 @@ Write-Host '=== Prepare release done ===' -ForegroundColor Green
Write-Host "Version: $newVersion" Write-Host "Version: $newVersion"
Write-Host '' Write-Host ''
Write-Host 'Next steps:' -ForegroundColor Yellow 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 ' 2) Run publish.cmd to validate and upload to updates.mailib.ru'
Write-Host '' Write-Host ''
+78 -5
View File
@@ -1,7 +1,8 @@
# Copy of D:\TTRPG-Release\publish.ps1 - keep in sync when updating the release folder tool. # Copy of D:\TTRPG-Release\publish.ps1 - keep in sync when updating the release folder tool.
param( param(
[switch]$CheckOnly [switch]$CheckOnly,
[switch]$SkipMac
) )
Set-StrictMode -Version Latest Set-StrictMode -Version Latest
@@ -38,6 +39,24 @@ function Write-Warn([string]$text) {
Write-Host " [--] $text" -ForegroundColor Yellow 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) { function Get-YmlReferencedFiles([string]$ymlPath) {
$names = [System.Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase) $names = [System.Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase)
$content = Get-Content -LiteralPath $ymlPath -Raw -Encoding UTF8 $content = Get-Content -LiteralPath $ymlPath -Raw -Encoding UTF8
@@ -47,6 +66,20 @@ function Get-YmlReferencedFiles([string]$ymlPath) {
return @($names) 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) { function Resolve-ReleaseFile([string]$name) {
$direct = Join-Path $ReleaseDir $name $direct = Join-Path $ReleaseDir $name
if (Test-Path -LiteralPath $direct) { if (Test-Path -LiteralPath $direct) {
@@ -149,17 +182,50 @@ if ($linuxYmls.Count -eq 0) {
Write-Title 'macOS (if latest-mac.yml present)' Write-Title 'macOS (if latest-mac.yml present)'
$macYml = Join-Path $ReleaseDir 'latest-mac.yml' $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' Write-Warn 'No latest-mac.yml - skipping macOS'
} else { } else {
Write-Ok 'latest-mac.yml' Write-Ok 'latest-mac.yml'
[void]$uploadFiles.Add($macYml) [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 $file = Resolve-ReleaseFile $name
if ($null -eq $file) { if ($null -eq $file) {
$errors.Add("macOS: missing file $name (from latest-mac.yml)") $warnings.Add("macOS: optional file missing (not uploaded): $name")
} else { } else {
Write-Ok $name Write-Ok "optional: $($file.Name)"
Add-FileToUploadSet $uploadFiles $file Add-FileToUploadSet $uploadFiles $file
} }
} }
@@ -213,4 +279,11 @@ if ($LASTEXITCODE -ne 0) {
Write-Title 'Done' Write-Title 'Done'
Write-Host 'Verify:' Write-Host 'Verify:'
Write-Host " ${feedUrl}latest.yml" 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 exit 0
+19
View File
@@ -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