Skip to content
This repository was archived by the owner on Jul 16, 2026. It is now read-only.

Commit 400f65d

Browse files
🪲 [Fix]: Only resolve a prerelease for open pull requests (never on merge/push to the default branch)
1 parent 6a59a88 commit 400f65d

3 files changed

Lines changed: 200 additions & 65 deletions

File tree

‎scripts/Resolve-PSModuleVersion.Helpers.psm1‎

Lines changed: 57 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,9 @@ function Get-GitHubPullRequest {
132132
returns $null and the caller resolves the current version without a version bump.
133133
134134
.OUTPUTS
135-
PSCustomObject with HeadRef and Labels properties for a pull_request event, or
136-
$null when the event has no pull request (non-PR events).
135+
PSCustomObject with HeadRef, Labels, and IsOpen properties for a pull_request event, or
136+
$null when the event has no pull request (non-PR events). IsOpen is $true only while the
137+
pull request is open (under review); it is $false once the PR is merged or closed.
137138
138139
.EXAMPLE
139140
$pullRequest = Get-GitHubPullRequest
@@ -160,16 +161,25 @@ function Get-GitHubPullRequest {
160161
$labels = @()
161162
$labels += $pr.labels.name
162163

164+
# A pull request is OPEN while it is under review (opened/reopened/synchronize/labeled).
165+
# Once it is merged or closed its state becomes 'closed'. Only an open pull request may
166+
# resolve to a prerelease; a merged/closed PR - like a push to the default branch - never
167+
# does. Default to not-open when state is missing so we never accidentally prerelease.
168+
$isOpen = $pr.state -eq 'open'
169+
163170
Write-Host '-------------------------------------------------'
164171
Write-Host ([PSCustomObject]@{
165172
PRHeadRef = $pr.head.ref
173+
State = $pr.state
174+
IsOpen = $isOpen
166175
Labels = $labels -join ', '
167176
} | Format-List | Out-String)
168177
Write-Host '-------------------------------------------------'
169178

170179
[PSCustomObject]@{
171180
HeadRef = $pr.head.ref
172181
Labels = $labels
182+
IsOpen = $isOpen
173183
}
174184
}
175185
}
@@ -181,7 +191,12 @@ function Resolve-ReleaseDecision {
181191
182192
.DESCRIPTION
183193
Evaluates the PR labels against the configured label categories and release type
184-
to produce a complete release decision.
194+
to produce a complete release decision. A prerelease - whether a published prerelease or
195+
a non-published preview - is only ever resolved for an OPEN pull request, so the artifact
196+
built during review can never masquerade as a stable release before the merge decision is
197+
made. Once a PR is merged or closed (and likewise for a push to the default branch, which
198+
the workflow treats the same as a merged PR) the outcome is final: a full release, or the
199+
current version unchanged - never a prerelease.
185200
186201
.OUTPUTS
187202
PSCustomObject with ShouldPublish, CreateRelease, CreatePrerelease, MajorRelease,
@@ -208,6 +223,7 @@ function Resolve-ReleaseDecision {
208223
$prereleaseName = $PullRequest.HeadRef -replace '[^a-zA-Z0-9]'
209224
$labels = $PullRequest.Labels
210225
$releaseType = $Configuration.ReleaseType
226+
$isOpenPullRequest = [bool]$PullRequest.IsOpen
211227

212228
$validReleaseTypes = @('Release', 'Prerelease', 'None')
213229
if ([string]::IsNullOrWhiteSpace($releaseType)) {
@@ -217,15 +233,7 @@ function Resolve-ReleaseDecision {
217233
throw "Invalid ReleaseType: [$releaseType]. Valid values are: $($validReleaseTypes -join ', ')"
218234
}
219235

220-
$createRelease = $releaseType -eq 'Release'
221-
$createPrerelease = $releaseType -eq 'Prerelease'
222-
$shouldPublish = $createRelease -or $createPrerelease
223-
224236
$ignoreRelease = ($labels | Where-Object { $Configuration.IgnoreLabels -contains $_ }).Count -gt 0
225-
if ($ignoreRelease -and $shouldPublish) {
226-
Write-Host 'Ignoring release creation due to ignore label.'
227-
$shouldPublish = $false
228-
}
229237

230238
# Always evaluate the version-bump labels so the resolved version reflects what WOULD be
231239
# created, regardless of whether this run publishes. ReleaseType (and the prerelease label
@@ -235,32 +243,51 @@ function Resolve-ReleaseDecision {
235243
$patchRelease = (
236244
(($labels | Where-Object { $Configuration.PatchLabels -contains $_ }).Count -gt 0) -or $Configuration.AutoPatching
237245
) -and -not $majorRelease -and -not $minorRelease
238-
239246
$hasVersionBump = $majorRelease -or $minorRelease -or $patchRelease
240-
if (-not $hasVersionBump) {
241-
# No explicit bump label and no AutoPatching: still resolve a patch version so the run
242-
# can preview what it would create, but do not publish a full release for an unlabeled change.
243-
Write-Host 'No version bump label and AutoPatching disabled; previewing a patch version without publishing.'
244-
$patchRelease = $true
245-
$hasVersionBump = $true
246-
$shouldPublish = $false
247-
}
248247

249-
# Anything that is not a published full release is surfaced as a prerelease - either a
250-
# published prerelease (ShouldPublish) or a non-published preview.
251-
if (-not $shouldPublish) {
248+
# A prerelease - whether a published prerelease or a non-published preview - only makes
249+
# sense while a pull request is OPEN. It lets the artifact built during review carry a
250+
# prerelease tag so it can never be mistaken for a stable release before the merge decision
251+
# is made. Once the change lands on the default branch the outcome is final: a merged pull
252+
# request publishes a full release (or, when nothing warrants one, nothing at all), and a
253+
# push to the default branch is treated the same as a merged pull request. A merge or push
254+
# therefore never resolves to a prerelease.
255+
if ($isOpenPullRequest) {
256+
# Open pull request: always carry a prerelease tag. ReleaseType 'Prerelease' (the
257+
# prerelease label) publishes it; otherwise it is a non-published preview. An ignore
258+
# label only suppresses publishing - the reviewed artifact still stays a prerelease.
259+
$createRelease = $false
252260
$createPrerelease = $true
261+
$shouldPublish = ($releaseType -eq 'Prerelease') -and -not $ignoreRelease
262+
if (-not $hasVersionBump) {
263+
Write-Host 'No version bump label and AutoPatching disabled; previewing a patch version.'
264+
$patchRelease = $true
265+
$hasVersionBump = $true
266+
}
267+
} else {
268+
# Merged/closed pull request or a push to the default branch: never a prerelease.
269+
$createPrerelease = $false
270+
$createRelease = ($releaseType -eq 'Release') -and -not $ignoreRelease -and $hasVersionBump
271+
$shouldPublish = $createRelease
272+
if (-not $createRelease) {
273+
Write-Host 'No open pull request and nothing to release; keeping the current version.'
274+
$majorRelease = $false
275+
$minorRelease = $false
276+
$patchRelease = $false
277+
$hasVersionBump = $false
278+
}
253279
}
254280

255281
Write-Host '-------------------------------------------------'
256282
Write-Host ([PSCustomObject]@{
257-
ReleaseType = $releaseType
258-
ShouldPublish = $shouldPublish
259-
CreateRelease = $createRelease
260-
CreatePrerelease = $createPrerelease
261-
Major = $majorRelease
262-
Minor = $minorRelease
263-
Patch = $patchRelease
283+
ReleaseType = $releaseType
284+
IsOpenPullRequest = $isOpenPullRequest
285+
ShouldPublish = $shouldPublish
286+
CreateRelease = $createRelease
287+
CreatePrerelease = $createPrerelease
288+
Major = $majorRelease
289+
Minor = $minorRelease
290+
Patch = $patchRelease
264291
} | Format-List | Out-String)
265292
Write-Host '-------------------------------------------------'
266293

0 commit comments

Comments
 (0)