|
| 1 | +#!/usr/bin/env pwsh |
| 2 | +<# |
| 3 | +.SYNOPSIS |
| 4 | + Promote the staged 0.0.0 block in the auto-update manifest to a real release version. |
| 5 | +
|
| 6 | +.DESCRIPTION |
| 7 | + This is the release action: the manifest is promoted by running this script, not by hand. |
| 8 | +
|
| 9 | + The staged <update version="0.0.0"> block is renamed to X.Y.Z (its staged <change>s become |
| 10 | + this release's changelog), the current newest release's <files> is moved onto it with the |
| 11 | + asset paths rewritten download/v<old>/ -> download/v<new>/ (only the newest release may list |
| 12 | + files, so the old entry is left an empty <files />), and a fresh empty version="0.0.0" block |
| 13 | + is added on top for the next cycle. |
| 14 | +
|
| 15 | + Existing formatting and the header comment are byte-preserved (PreserveWhitespace); only the |
| 16 | + inserted/edited nodes are touched. The result is validated with validate-manifest.ps1. |
| 17 | +#> |
| 18 | +param( |
| 19 | + [Parameter(Mandatory)] |
| 20 | + [ValidatePattern('^\d+\.\d+\.\d+$')] |
| 21 | + [string]$Version, |
| 22 | + [string]$Path = 'update.LiveSplit.AutoSplitIntegration.xml' |
| 23 | +) |
| 24 | +$ErrorActionPreference = 'Stop' |
| 25 | + |
| 26 | +if ($Version -eq '0.0.0') { throw '0.0.0 is the staging version, not a release version' } |
| 27 | + |
| 28 | +$file = (Resolve-Path -LiteralPath $Path).Path |
| 29 | +[xml]$doc = New-Object System.Xml.XmlDocument |
| 30 | +$doc.PreserveWhitespace = $true |
| 31 | +$doc.Load($file) |
| 32 | +$root = $doc.DocumentElement |
| 33 | + |
| 34 | +$staging = $root.SelectSingleNode("update[@version='0.0.0']") |
| 35 | +if ($null -eq $staging) { throw 'no <update version="0.0.0"> staging block to promote' } |
| 36 | +if ($root.SelectSingleNode("update[@version='$Version']")) { throw "manifest already has an <update version=""$Version"">" } |
| 37 | + |
| 38 | +# Refuse before writing anything: a release needs at least one staged <change>, else it ships an |
| 39 | +# empty changelog and the manifest fails validation (which the Release workflow runs per version). |
| 40 | +$staged = @($staging.SelectNodes('changelog/change') | Where-Object { $_.InnerText.Trim() }) |
| 41 | +if ($staged.Count -eq 0) { throw 'the 0.0.0 staging block has no <change> to release. Write at least 1 entry first' } |
| 42 | + |
| 43 | +# The current newest release is the only entry that lists files. Move that <files> onto the |
| 44 | +# staging entry (rewriting the version in each asset path), and empty out the old one. |
| 45 | +$oldRelease = $root.SelectSingleNode('update[files/file]') |
| 46 | +if ($null -eq $oldRelease) { |
| 47 | + Write-Host "::warning::no existing release lists <files>; add this release's <file> entries manually" |
| 48 | +} |
| 49 | +else { |
| 50 | + $oldVersion = $oldRelease.GetAttribute('version') |
| 51 | + $srcFiles = $oldRelease.SelectSingleNode('files') |
| 52 | + $dstFiles = $staging.SelectSingleNode('files') |
| 53 | + |
| 54 | + foreach ($f in @($srcFiles.SelectNodes('file'))) { |
| 55 | + $f.SetAttribute('path', $f.GetAttribute('path').Replace("download/v$oldVersion/", "download/v$Version/")) |
| 56 | + } |
| 57 | + $dstFiles.IsEmpty = $false |
| 58 | + foreach ($child in @($srcFiles.ChildNodes)) { [void]$dstFiles.AppendChild($child) } # moves the node |
| 59 | + $srcFiles.IsEmpty = $true # old release back to <files /> |
| 60 | +} |
| 61 | + |
| 62 | +# Promote the staging block to the release version. |
| 63 | +$staging.SetAttribute('version', $Version) |
| 64 | + |
| 65 | +# Insert a fresh empty 0.0.0 staging block above the promoted one, matching indentation. |
| 66 | +$frag = $doc.CreateDocumentFragment() |
| 67 | +$frag.InnerXml = "<update version=`"0.0.0`">`n <files />`n <changelog>`n </changelog>`n </update>" |
| 68 | +[void]$root.InsertBefore($frag.FirstChild, $staging) |
| 69 | +[void]$root.InsertBefore($doc.CreateTextNode("`n "), $staging) |
| 70 | + |
| 71 | +# Save without a BOM and without re-indenting (the tree already carries its whitespace). |
| 72 | +$settings = New-Object System.Xml.XmlWriterSettings |
| 73 | +$settings.Encoding = New-Object System.Text.UTF8Encoding($false) |
| 74 | +$settings.NewLineChars = "`r`n" # match the manifest's CRLF (.editorconfig end_of_line = crlf) |
| 75 | +$writer = [System.Xml.XmlWriter]::Create($file, $settings) |
| 76 | +try { $doc.Save($writer) } finally { $writer.Dispose() } |
| 77 | +Write-Host "Promoted 0.0.0 -> $Version in $Path (moved <file> attributes onto one line each)" |
| 78 | + |
| 79 | +& "$PSScriptRoot/validate-manifest.ps1" -Path $Path -ReleaseVersion $Version |
0 commit comments