@@ -190,6 +190,7 @@ $settings = [pscustomobject]@{
190190 Skip = $settings.Publish.Module.Skip ?? $false
191191 AutoCleanup = $settings.Publish.Module.AutoCleanup ?? $true
192192 AutoPatching = $settings.Publish.Module.AutoPatching ?? $true
193+ AllowDirectPushRelease = $settings.Publish.Module.AllowDirectPushRelease ?? $false
193194 IncrementalPrerelease = $settings.Publish.Module.IncrementalPrerelease ?? $true
194195 DatePrereleaseFormat = $settings.Publish.Module.DatePrereleaseFormat ?? ' '
195196 VersionPrefix = $settings.Publish.Module.VersionPrefix ?? ' v'
@@ -226,43 +227,103 @@ LogGroup 'Calculate Job Run Conditions:' {
226227 $eventData | ConvertTo-Json - Depth 10 | Out-String
227228 }
228229
230+ $defaultBranch = $eventData.Repository.default_branch
231+ $eventName = $env: GITHUB_EVENT_NAME
232+ $isPR = $eventName -eq ' pull_request'
233+ $isPush = $eventName -eq ' push'
229234 $pullRequestAction = $eventData.Action
235+ $commitSha = if ($isPush ) { $eventData.After ?? $env: GITHUB_SHA } else { $env: GITHUB_SHA }
236+ $pushBranch = if ($isPush ) { $eventData.Ref -replace ' ^refs/heads/' , ' ' } else { ' ' }
237+ $isPushToDefaultBranch = $isPush -and $pushBranch -eq $defaultBranch
230238 $pullRequest = $eventData.PullRequest
231- $pullRequestIsMerged = $pullRequest.Merged
232- $targetBranch = $pullRequest.Base.Ref
233- $defaultBranch = $eventData.Repository.default_branch
239+
240+ if ($isPush -and $commitSha ) {
241+ LogGroup " Resolve pull request for commit [$commitSha ]" {
242+ $owner = $env: GITHUB_REPOSITORY_OWNER
243+ $repo = $env: GITHUB_REPOSITORY_NAME
244+ $response = Invoke-GitHubAPI - ApiEndpoint " /repos/$owner /$repo /commits/$commitSha /pulls" - Method GET
245+ $associatedPullRequests = @ ($response.Response )
246+ $pullRequest = $associatedPullRequests |
247+ Where-Object { $_.Base.Ref -eq $defaultBranch } |
248+ Sort-Object - Property @ { Expression = { $_ .' merge_commit_sha' -eq $commitSha }; Descending = $true },
249+ @ { Expression = { $_ .' merged_at' }; Descending = $true } |
250+ Select-Object - First 1
251+
252+ if ($pullRequest ) {
253+ Write-Host " Resolved pull request #$ ( $pullRequest.Number ) from commit [$commitSha ]."
254+ } else {
255+ Write-Host " ::notice::No pull request is associated with commit [$commitSha ]."
256+ }
257+ }
258+ }
259+
260+ $pullRequestIsMerged = if ($null -ne $pullRequest.Merged ) {
261+ [bool ]$pullRequest.Merged
262+ } else {
263+ -not [string ]::IsNullOrWhiteSpace($pullRequest .' merged_at' )
264+ }
265+ $targetBranch = if ($pullRequest ) { $pullRequest.Base.Ref } elseif ($isPush ) { $pushBranch } else { ' ' }
234266 $isTargetDefaultBranch = $targetBranch -eq $defaultBranch
267+ $pullRequestContext = if ($pullRequest ) {
268+ [pscustomobject ]@ {
269+ Number = $pullRequest.Number
270+ Title = $pullRequest.Title
271+ Body = $pullRequest.Body
272+ HeadRef = $pullRequest.Head.Ref
273+ BaseRef = $pullRequest.Base.Ref
274+ Labels = @ ($pullRequest.Labels.Name )
275+ Merged = $pullRequestIsMerged
276+ MergeCommitSha = $pullRequest .' merge_commit_sha'
277+ HtmlUrl = $pullRequest .' html_url'
278+ }
279+ } else {
280+ $null
281+ }
282+
283+ $settings | Add-Member - MemberType NoteProperty - Name Context - Value ([pscustomobject ]@ {
284+ EventName = $eventName
285+ EventAction = $pullRequestAction
286+ CommitSha = $commitSha
287+ Ref = if ($isPush ) { $eventData.Ref } else { $env: GITHUB_REF }
288+ DefaultBranch = $defaultBranch
289+ IsPushToDefaultBranch = $isPushToDefaultBranch
290+ PullRequest = $pullRequestContext
291+ }) - Force
235292
236293 Write-Host ' GitHub event inputs:'
237294 [pscustomobject ]@ {
238- GITHUB_EVENT_NAME = $env: GITHUB_EVENT_NAME
295+ GITHUB_EVENT_NAME = $eventName
239296 GITHUB_EVENT_ACTION = $pullRequestAction
240297 GITHUB_EVENT_PULL_REQUEST_MERGED = $pullRequestIsMerged
298+ CommitSha = $commitSha
299+ PushBranch = $pushBranch
241300 TargetBranch = $targetBranch
242301 DefaultBranch = $defaultBranch
243302 IsTargetDefaultBranch = $isTargetDefaultBranch
303+ IsPushToDefaultBranch = $isPushToDefaultBranch
304+ AssociatedPullRequest = $pullRequestContext.Number
244305 } | Format-List | Out-String
245306
246- $isPR = $env: GITHUB_EVENT_NAME -eq ' pull_request'
247307 $isOpenOrUpdatedPR = $isPR -and $pullRequestAction -in @ (' opened' , ' reopened' , ' synchronize' , ' labeled' , ' unlabeled' )
308+ $isClosedPR = $isPR -and $pullRequestAction -eq ' closed'
248309 $isAbandonedPR = $isPR -and $pullRequestAction -eq ' closed' -and $pullRequestIsMerged -ne $true
249310 $isMergedPR = $isPR -and $pullRequestAction -eq ' closed' -and $pullRequestIsMerged -eq $true
250- $isNotAbandonedPR = -not $isAbandonedPR
311+ $hasPullRequestContext = $null -ne $pullRequestContext
251312
252313 # Check if a prerelease label exists on the PR
253314 $prereleaseLabels = $settings.Publish.Module.PrereleaseLabels -split ' ,' | ForEach-Object { $_.Trim () }
254- $prLabels = @ ($pullRequest .labels.name )
315+ $prLabels = @ ($pullRequestContext .Labels )
255316 $hasPrereleaseLabel = ($prLabels | Where-Object { $prereleaseLabels -contains $_ }).Count -gt 0
256317 $isOpenOrLabeledPR = $isPR -and $pullRequestAction -in @ (' opened' , ' reopened' , ' synchronize' , ' labeled' )
257318
258319 # Check if important files have changed in the PR
259320 # Important files are determined by the configured ImportantFilePatterns setting
260321 $hasImportantChanges = $false
261- if ($isPR -and $pullRequest .Number ) {
322+ if ($pullRequestContext .Number ) {
262323 LogGroup ' Check for Important File Changes' {
263324 $owner = $env: GITHUB_REPOSITORY_OWNER
264325 $repo = $env: GITHUB_REPOSITORY_NAME
265- $prNumber = $pullRequest .Number
326+ $prNumber = $pullRequestContext .Number
266327
267328 Write-Host " Fetching changed files for PR #$prNumber ..."
268329 $changedFiles = Invoke-GitHubAPI - ApiEndpoint " /repos/$owner /$repo /pulls/$prNumber /files" - Method GET |
@@ -332,10 +393,17 @@ If you believe this is incorrect, please verify that your changes are in the cor
332393 }
333394 }
334395 }
396+ } elseif ($isPush ) {
397+ $hasImportantChanges = $isPushToDefaultBranch -and $settings.Publish.Module.AllowDirectPushRelease
398+ if ($hasImportantChanges ) {
399+ Write-Host ' Direct push release is explicitly enabled; treating the push as having important changes.'
400+ } else {
401+ Write-Host ' Push has no associated pull request; stable publishing is disabled by default.'
402+ }
335403 } else {
336- # Not a PR event or no PR number - consider as having important changes (e.g., workflow_dispatch, schedule)
404+ # Preserve build/test behavior for workflow_dispatch and schedule events.
337405 $hasImportantChanges = $true
338- Write-Host ' Not a PR event or missing PR number - treating as having important changes'
406+ Write-Host ' Non- PR event - treating as having important changes'
339407 }
340408
341409 # Prerelease requires both: prerelease label AND important file changes
@@ -344,9 +412,12 @@ If you believe this is incorrect, please verify that your changes are in the cor
344412
345413 # Determine ReleaseType - what type of release to create
346414 # Values: 'Release', 'Prerelease', 'None'
347- # Release only happens when important files changed (actual module code/docs)
348- # Merged PRs without important changes should only trigger cleanup, not a new release
349- $releaseType = if ($isMergedPR -and $isTargetDefaultBranch -and $hasImportantChanges ) {
415+ # Stable releases are push-driven. A direct push requires explicit opt-in.
416+ $releaseType = if (
417+ $isPushToDefaultBranch -and
418+ $hasImportantChanges -and
419+ ($hasPullRequestContext -or $settings.Publish.Module.AllowDirectPushRelease )
420+ ) {
350421 ' Release'
351422 } elseif ($shouldPrerelease ) {
352423 ' Prerelease'
@@ -358,10 +429,13 @@ If you believe this is incorrect, please verify that your changes are in the cor
358429 isPR = $isPR
359430 isOpenOrUpdatedPR = $isOpenOrUpdatedPR
360431 isOpenOrLabeledPR = $isOpenOrLabeledPR
432+ isClosedPR = $isClosedPR
361433 isAbandonedPR = $isAbandonedPR
362434 isMergedPR = $isMergedPR
363- isNotAbandonedPR = $isNotAbandonedPR
435+ isPush = $isPush
436+ isPushToDefaultBranch = $isPushToDefaultBranch
364437 isTargetDefaultBranch = $isTargetDefaultBranch
438+ hasPullRequestContext = $hasPullRequestContext
365439 hasPrereleaseLabel = $hasPrereleaseLabel
366440 shouldPrerelease = $shouldPrerelease
367441 ReleaseType = $releaseType
@@ -532,23 +606,22 @@ $settings.Test.Module | Add-Member -MemberType NoteProperty -Name Suites -Value
532606# Calculate job-specific conditions and add to settings
533607LogGroup ' Calculate Job Run Conditions:' {
534608 # Calculate if prereleases should be cleaned up:
535- # True if (Release, merged PR to default branch, or Abandoned PR) AND user has AutoCleanup enabled (defaults to true)
536- # Even if no important files changed, we still want to cleanup prereleases when merging to default branch
537- $isReleaseOrMergedOrAbandoned = (
609+ # Closed PRs only clean up prereleases. Push runs also clean up the associated PR channel.
610+ $shouldCleanupEvent = (
538611 ($releaseType -eq ' Release' ) -or
539- ( $isMergedPR -and $isTargetDefaultBranch ) -or
540- $isAbandonedPR
612+ $isClosedPR -or
613+ ( $isPushToDefaultBranch -and $hasPullRequestContext )
541614 )
542- $shouldAutoCleanup = $isReleaseOrMergedOrAbandoned -and ($settings.Publish.Module.AutoCleanup -eq $true )
615+ $shouldAutoCleanup = $shouldCleanupEvent -and ($settings.Publish.Module.AutoCleanup -eq $true )
543616
544617 # Update Publish.Module with computed release values
545618 $settings.Publish.Module | Add-Member - MemberType NoteProperty - Name ReleaseType - Value $releaseType - Force
546619 $settings.Publish.Module.AutoCleanup = $shouldAutoCleanup
547620
548621 # For open PRs, we only want to run build/test stages if important files changed.
549- # For merged PRs, workflow_dispatch, schedule - $hasImportantChanges is already true .
622+ # Closed PR events are cleanup-only. workflow_dispatch and schedule retain build/test behavior .
550623 # Note: $shouldPrerelease already requires $hasImportantChanges, so no separate check needed.
551- $shouldRunBuildTest = $isNotAbandonedPR -and $hasImportantChanges
624+ $shouldRunBuildTest = ( -not $isClosedPR ) -and $hasImportantChanges
552625
553626 # Check if setup/teardown scripts exist in the repository
554627 $hasBeforeAllScript = Test-Path - Path ' tests/BeforeAll.ps1'
@@ -607,8 +680,8 @@ LogGroup 'Calculate Job Run Conditions:' {
607680 $settings.Publish.Module | Add-Member - MemberType NoteProperty - Name Desired - Value (($releaseType -ne ' None' ) -or $shouldAutoCleanup ) - Force
608681 $settings.Publish.Module | Add-Member - MemberType NoteProperty - Name Enabled - Value (($releaseType -ne ' None' ) -or $shouldAutoCleanup ) - Force
609682 $settings.Publish | Add-Member - MemberType NoteProperty - Name Site - Value ([pscustomobject ]@ {
610- Desired = $isMergedPR -and $isTargetDefaultBranch -and $hasImportantChanges
611- Enabled = $isMergedPR -and $isTargetDefaultBranch -and $hasImportantChanges
683+ Desired = $releaseType -eq ' Release '
684+ Enabled = $releaseType -eq ' Release '
612685 }) - Force
613686
614687 $settings | Add-Member - MemberType NoteProperty - Name HasImportantChanges - Value $hasImportantChanges
0 commit comments