The launcher reported "no client available" because its update source was
pinned to a GitHub Releases manifest in a PRIVATE repo — nothing anonymous
could ever be fetched from it. Switch the feed to the PUBLIC Gitea repo so a
friend needs no account, and add the two commands that publish it.
- ReleaseManifestClient.ProductionManifestUri now points at
git.snakedesert.se/erik/acdream raw on the `dist` branch. No update
machinery changed: the existing strict reader already accepts any HTTPS
manifest, so this is a URL swap plus a build script.
- tools/publish-bin.ps1 publishes the payloads into /bin and writes
bin/manifest.json (schema v1, SHA-256 + size per artifact):
client-win-x64.zip AcDream.App + acdream-headless
launcher-win-x64.zip acdream-launcher + co-deployed acdream-bake
Stamps InformationalVersion ONLY — never -p:Version, which also rewrites
project-reference versions inside the committed packages.<rid>.lock.json
files and churned every one of them with a throwaway build stamp.
- tools/publish-dist.ps1 pushes /bin to the Gitea-only `dist` branch from a
throwaway worktree, leaving the developer's checkout, index, and HEAD
untouched. It refuses a GitHub remote outright.
Why `dist` and not main: the launcher payload is ~103 MB because the launcher
and its co-deployed bake CLI are each self-contained single files (deliberate,
see AcDream.Launcher.csproj). GitHub hard-rejects files over 100 MB, and all
three refs currently track main, so payloads on main would break every GitHub
push. `dist` is a single-commit orphan branch that each publish REPLACES, so
superseded builds never accumulate. /bin stays gitignored repo-wide and is
force-added only on that branch.
Verified live: manifest and both payloads serve anonymously over HTTPS, and a
downloaded client payload matches its declared SHA-256 and size byte for byte.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
161 lines
6.3 KiB
PowerShell
161 lines
6.3 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Publishes the /bin alpha feed to the Gitea-only `dist` branch.
|
|
|
|
.DESCRIPTION
|
|
Copies the payloads written by tools/publish-bin.ps1 onto an orphan `dist`
|
|
branch and pushes it to Gitea (the `origin` remote). The launcher's update
|
|
check reads that branch's raw URLs.
|
|
|
|
Why a separate branch, not main:
|
|
* The launcher payload is ~103 MB. GitHub hard-rejects any file over
|
|
100 MB, so payloads on main would break every GitHub push.
|
|
* Each build is ~150 MB. On main that weight would land in the history
|
|
every developer clones forever.
|
|
`dist` is a single-commit ORPHAN branch — each publish REPLACES it, so the
|
|
feed never accumulates old builds. Nothing on it is a parent of main.
|
|
|
|
.PARAMETER Remote
|
|
Remote to publish to. Defaults to `origin` (Gitea). Never pass the GitHub
|
|
remote: the payload exceeds its per-file limit.
|
|
|
|
.EXAMPLE
|
|
pwsh -NoProfile -File tools/publish-bin.ps1
|
|
pwsh -NoProfile -File tools/publish-dist.ps1
|
|
#>
|
|
[CmdletBinding()]
|
|
param(
|
|
[string]$Remote = 'origin',
|
|
[switch]$KeepHistory
|
|
)
|
|
|
|
Set-StrictMode -Version Latest
|
|
$ErrorActionPreference = 'Stop'
|
|
|
|
if ($PSVersionTable.PSVersion.Major -lt 7) {
|
|
throw 'publish-dist requires PowerShell 7 or newer.'
|
|
}
|
|
|
|
$RepoRoot = [IO.Path]::GetFullPath((Join-Path $PSScriptRoot '..'))
|
|
$BinRoot = Join-Path $RepoRoot 'bin'
|
|
$ManifestPath = Join-Path $BinRoot 'manifest.json'
|
|
|
|
if (-not (Test-Path -LiteralPath $ManifestPath)) {
|
|
throw "No feed found at '$ManifestPath'. Run tools/publish-bin.ps1 first."
|
|
}
|
|
|
|
$manifest = Get-Content -LiteralPath $ManifestPath -Raw | ConvertFrom-Json
|
|
$version = $manifest.version
|
|
if ([string]::IsNullOrWhiteSpace($version)) {
|
|
throw 'The manifest has no version.'
|
|
}
|
|
|
|
$payloads = @(Get-ChildItem -LiteralPath $BinRoot -File -Filter *.zip)
|
|
if ($payloads.Count -eq 0) {
|
|
throw "No .zip payloads in '$BinRoot'. Run tools/publish-bin.ps1 first."
|
|
}
|
|
|
|
$remoteUrl = (& git -C $RepoRoot remote get-url $Remote 2>&1)
|
|
if ($LASTEXITCODE) { throw "Remote '$Remote' is not configured." }
|
|
if ($remoteUrl -match 'github\.com') {
|
|
throw "Refusing to publish payloads to '$Remote' ($remoteUrl): GitHub " +
|
|
'rejects files over 100 MB and the alpha feed is Gitea-only.'
|
|
}
|
|
|
|
Write-Host "Publishing alpha feed $version to $Remote ($remoteUrl)" -ForegroundColor Cyan
|
|
foreach ($payload in $payloads) {
|
|
' {0,-26} {1,8:N1} MB' -f $payload.Name, ($payload.Length / 1MB) | Write-Host
|
|
}
|
|
|
|
# A throwaway worktree keeps the developer's checkout, index, and HEAD
|
|
# completely untouched while the dist branch is built and pushed.
|
|
$stamp = [DateTime]::UtcNow.ToString('yyyyMMddHHmmss')
|
|
$workTree = Join-Path ([IO.Path]::GetTempPath()) "acdream-dist-$stamp"
|
|
$branch = 'dist'
|
|
# Build under a unique local branch and push it AS dist. Reusing the name
|
|
# locally breaks the second publish outright: `checkout --orphan dist` fails
|
|
# once a local dist ref exists (observed 2026-08-18).
|
|
$stagingBranch = "dist-publish-$stamp"
|
|
|
|
try {
|
|
if ($KeepHistory) {
|
|
& git -C $RepoRoot fetch $Remote $branch 2>&1 | Out-Null
|
|
$hasRemoteBranch = -not $LASTEXITCODE
|
|
& git -C $RepoRoot worktree add --no-checkout -b $stagingBranch $workTree `
|
|
$(if ($hasRemoteBranch) { "$Remote/$branch" } else { 'HEAD' }) 2>&1 | Out-Null
|
|
if ($LASTEXITCODE) { throw 'Could not create the dist worktree.' }
|
|
& git -C $workTree checkout . 2>&1 | Out-Null
|
|
}
|
|
else {
|
|
# Default: one commit, no ancestry. Each publish REPLACES the branch so
|
|
# superseded payloads never pile up in the object store.
|
|
& git -C $RepoRoot worktree add --detach $workTree 2>&1 | Out-Null
|
|
if ($LASTEXITCODE) { throw 'Could not create the dist worktree.' }
|
|
& git -C $workTree checkout --orphan $stagingBranch 2>&1 | Out-Null
|
|
if ($LASTEXITCODE) { throw 'Could not start the dist branch.' }
|
|
& git -C $workTree rm -rf --cached . 2>&1 | Out-Null
|
|
Get-ChildItem -LiteralPath $workTree -Force |
|
|
Where-Object { $_.Name -ne '.git' } |
|
|
Remove-Item -Recurse -Force
|
|
}
|
|
|
|
$targetBin = Join-Path $workTree 'bin'
|
|
if (Test-Path -LiteralPath $targetBin) {
|
|
Remove-Item -LiteralPath $targetBin -Recurse -Force
|
|
}
|
|
$null = New-Item -ItemType Directory -Path $targetBin -Force
|
|
Copy-Item -LiteralPath $ManifestPath -Destination $targetBin
|
|
foreach ($payload in $payloads) {
|
|
Copy-Item -LiteralPath $payload.FullName -Destination $targetBin
|
|
}
|
|
|
|
$readme = @"
|
|
# acdream alpha feed
|
|
|
|
Published by ``tools/publish-dist.ps1``. This branch carries ONLY the launcher
|
|
update feed — it has no source history and is never merged into ``main``.
|
|
|
|
Current release: **$version**
|
|
|
|
## For players
|
|
|
|
1. Download ``bin/launcher-win-x64.zip``.
|
|
2. Unzip it anywhere and run ``acdream-launcher.exe``.
|
|
3. The launcher installs the game client and keeps both up to date.
|
|
|
|
You need Asheron's Call's DAT files for first-run setup.
|
|
"@
|
|
[IO.File]::WriteAllText(
|
|
(Join-Path $workTree 'README.md'),
|
|
$readme,
|
|
[Text.UTF8Encoding]::new($false))
|
|
|
|
# bin/ is gitignored repo-wide (so main can never take the payloads by
|
|
# accident) — force-add it here, where it is the whole point of the branch.
|
|
& git -C $workTree add -f bin README.md
|
|
if ($LASTEXITCODE) { throw 'Could not stage the feed.' }
|
|
|
|
& git -C $workTree commit -q -m "release: acdream alpha $version" 2>&1 | Out-Null
|
|
if ($LASTEXITCODE) {
|
|
Write-Host 'Nothing changed since the last publish.' -ForegroundColor Yellow
|
|
}
|
|
|
|
& git -C $workTree push --force $Remote "${stagingBranch}:${branch}"
|
|
if ($LASTEXITCODE) { throw "Push to $Remote/$branch failed." }
|
|
}
|
|
finally {
|
|
if (Test-Path -LiteralPath $workTree) {
|
|
& git -C $RepoRoot worktree remove --force $workTree 2>&1 | Out-Null
|
|
if (Test-Path -LiteralPath $workTree) {
|
|
Remove-Item -LiteralPath $workTree -Recurse -Force -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
& git -C $RepoRoot worktree prune 2>&1 | Out-Null
|
|
# The staging branch exists only to carry one publish to the remote.
|
|
& git -C $RepoRoot branch -D $stagingBranch 2>&1 | Out-Null
|
|
}
|
|
|
|
Write-Host ''
|
|
Write-Host "Published $version." -ForegroundColor Green
|
|
Write-Host 'Feed: https://git.snakedesert.se/erik/acdream/raw/branch/dist/bin/manifest.json'
|
|
Write-Host 'Players: https://git.snakedesert.se/erik/acdream/src/branch/dist'
|