Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions .codex/scripts/prerelease-notes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,10 @@ if [ ! -f "$CHANGELOG_PATH" ]; then
fail "Unable to locate changelog at '$CHANGELOG_PATH'."
fi

if ! grep -Eq '^##[[:space:]]*Unreleased[[:space:]]*$' "$CHANGELOG_PATH"; then
fail "CHANGELOG.md must contain a ## Unreleased section before creating or publishing a prerelease."
fi

unreleased_body=$(
awk '
/^##[[:space:]]*Unreleased[[:space:]]*$/ { in_unreleased = 1; next }
Expand Down Expand Up @@ -143,21 +147,18 @@ cat > "$OUTPUT_PATH" <<EOF
> [!NOTE]
> This GitHub pre-release is the source artifact for the matching Thunderstore publish. Thunderstore receives package version \`${VERSION}\` from tag \`${TAG}\`.

<details open>
<summary>Good to know before Thunderstore</summary>
### 📦 Thunderstore handoff

| Item | Detail |
| Signal | Detail |
| --- | --- |
| Changelog turnover | \`## Unreleased\` is empty; notes below come from \`${VERSION}\`. |
| Source branch | \`${BRANCH}\` |
| Source commit | \`${short_commit}\` |
| Workflow run | ${run_detail} |
| GitHub tag | \`${TAG}\` |
| Thunderstore version | \`${VERSION}\` |

</details>

### Changes
| 📝 Changelog | \`## Unreleased\` is empty; notes below come from \`${VERSION}\`. |
| 🌿 Branch | \`${BRANCH}\` |
| 🔖 Commit | \`${short_commit}\` |
| ▶️ Run | ${run_detail} |
| 🏷️ Tag | \`${TAG}\` |
| 📦 Package | \`${VERSION}\` |

### ✨ Changes

${version_body}
EOF
Expand Down
54 changes: 51 additions & 3 deletions .codex/scripts/prerelease-notes.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,19 @@ function Test-PrereleaseNotesIncludesChangelogAndDetailsCard {
}

$Notes = Get-Content -Raw -Path $OutputPath
Assert-Match -Text $Notes -Pattern '<details open>' -Message "Release notes did not include the details card."
Assert-Match -Text $Notes -Pattern 'Good to know before Thunderstore' -Message "Release notes did not include the card summary."
if ($Notes -match '<details') {
throw "Release notes should keep the Thunderstore handoff card visible without a dropdown."
}

Assert-Match -Text $Notes -Pattern '### 📦 Thunderstore handoff' -Message "Release notes did not include the handoff card heading."
Assert-Match -Text $Notes -Pattern '📝 Changelog' -Message "Release notes did not include the changelog cue."
Assert-Match -Text $Notes -Pattern '🌿 Branch' -Message "Release notes did not include the branch cue."
Assert-Match -Text $Notes -Pattern '🔖 Commit' -Message "Release notes did not include the commit cue."
Assert-Match -Text $Notes -Pattern '▶️ Run' -Message "Release notes did not include the workflow run cue."
Assert-Match -Text $Notes -Pattern '🏷️ Tag' -Message "Release notes did not include the tag cue."
Assert-Match -Text $Notes -Pattern '📦 Package' -Message "Release notes did not include the package cue."
Assert-Match -Text $Notes -Pattern '## Unreleased.*empty' -Message "Release notes did not describe changelog turnover."
Assert-Match -Text $Notes -Pattern 'Thunderstore version.*1\.2\.3' -Message "Release notes did not include the Thunderstore package version."
Assert-Match -Text $Notes -Pattern 'Package.*1\.2\.3' -Message "Release notes did not include the Thunderstore package version."
Assert-Match -Text $Notes -Pattern 'fixed the client widget timing' -Message "Release notes did not include current version changelog notes."
Assert-Match -Text $Notes -Pattern '1234567890ab' -Message "Release notes did not include the short commit."
}
Expand Down Expand Up @@ -107,6 +116,30 @@ function Test-PrereleaseNotesRejectsUnreleasedContent {
}
}

function Test-PrereleaseNotesRejectsMissingUnreleasedHeader {
$FixtureRoot = New-Fixture
try {
$ChangelogPath = Join-Path $FixtureRoot "CHANGELOG.md"
Set-Content -Path $ChangelogPath -Value @'
`1.2.3`
- fixed the client widget timing
'@

$Output = Invoke-PrereleaseNotes -Arguments @(
"--changelog", $ChangelogPath,
"--version", "1.2.3",
"--check-only")
if ($LASTEXITCODE -eq 0) {
throw "prerelease-notes.sh unexpectedly accepted a missing Unreleased header."
}

Assert-Match -Text $Output -Pattern 'must contain a ## Unreleased section' -Message "Missing Unreleased rejection message was not specific."
}
finally {
Remove-Item -Recurse -Force -LiteralPath $FixtureRoot
}
}

function Test-PrereleaseNotesRejectsMissingVersionEntry {
$FixtureRoot = New-Fixture
try {
Expand Down Expand Up @@ -137,12 +170,18 @@ function Test-ReleaseWorkflowChecksOnlyDownloadedReleaseChangelog {
$WorkflowPath = Join-Path (Split-Path -Parent (Split-Path -Parent $ScriptRoot)) ".github/workflows/release.yml"
$WorkflowText = Get-Content -Raw -Path $WorkflowPath

$PreserveMarker = " - name: Preserve release helper scripts"
$DownloadMarker = " - name: Download Release"
$DownloadedChangelogMarker = " - name: Validate downloaded release changelog"

$PreserveIndex = $WorkflowText.IndexOf($PreserveMarker, [StringComparison]::Ordinal)
$DownloadIndex = $WorkflowText.IndexOf($DownloadMarker, [StringComparison]::Ordinal)
$DownloadedChangelogIndex = $WorkflowText.IndexOf($DownloadedChangelogMarker, [StringComparison]::Ordinal)

if ($PreserveIndex -lt 0) {
throw "release.yml is missing the Preserve release helper scripts step."
}

if ($DownloadIndex -lt 0) {
throw "release.yml is missing the Download Release step."
}
Expand All @@ -151,6 +190,10 @@ function Test-ReleaseWorkflowChecksOnlyDownloadedReleaseChangelog {
throw "release.yml is missing downloaded release changelog validation."
}

if ($DownloadIndex -lt $PreserveIndex) {
throw "Release helper scripts must be preserved before downloading the selected release."
}

if ($DownloadedChangelogIndex -lt $DownloadIndex) {
throw "Downloaded release changelog validation must run after the release download."
}
Expand All @@ -159,10 +202,15 @@ function Test-ReleaseWorkflowChecksOnlyDownloadedReleaseChangelog {
if ($BeforeDownload -match 'prerelease-notes\.sh[\s\S]*--check-only') {
throw "release.yml must not run prerelease-notes.sh --check-only against the checkout before downloading the selected release tag."
}

if ($WorkflowText -notmatch '\$RUNNER_TEMP/prerelease-notes\.sh') {
throw "release.yml should run changelog validation from the preserved helper script."
}
}

Test-PrereleaseNotesIncludesChangelogAndDetailsCard
Test-PrereleaseNotesRejectsUnreleasedContent
Test-PrereleaseNotesRejectsMissingUnreleasedHeader
Test-PrereleaseNotesRejectsMissingVersionEntry
Test-ReleaseWorkflowChecksOnlyDownloadedReleaseChangelog

Expand Down
8 changes: 7 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ jobs:
echo "ALLOWED_TAG_PATTERN=$allowed_tag_pattern" >> "$GITHUB_ENV"
echo "ALLOWED_PACKAGE_VERSION_PATTERN=$allowed_package_version_pattern" >> "$GITHUB_ENV"

- name: Preserve release helper scripts
shell: bash
run: |
cp .codex/scripts/prerelease-notes.sh "$RUNNER_TEMP/prerelease-notes.sh"
chmod +x "$RUNNER_TEMP/prerelease-notes.sh"

- name: Download Release
run: gh release download "$RELEASE_TAG" -D ./dist
env:
Expand All @@ -83,7 +89,7 @@ jobs:
- name: Validate downloaded release changelog
shell: bash
run: |
bash .codex/scripts/prerelease-notes.sh \
bash "$RUNNER_TEMP/prerelease-notes.sh" \
--changelog ./dist/CHANGELOG.md \
--version "$PACKAGE_VERSION" \
--tag "$RELEASE_TAG" \
Expand Down
Loading