Skip to content
Closed
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
59 changes: 59 additions & 0 deletions .pipelines/templates/release-Nuget.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
parameters:
- name: skipPublish
type: boolean

jobs:
- job: NuGetPublish
displayName: Publish to NuGet
condition: succeeded()
pool:
type: release
os: windows
templateContext:
inputs:
- input: pipelineArtifact
pipeline: PSPackagesOfficial
artifactName: drop_upload_upload_packages
variables:
- template: ./variables/release-shared.yml@self
parameters:
VERSION: $[ stageDependencies.setReleaseTagAndChangelog.SetTagAndChangelog.outputs['OutputVersion.Version'] ]

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The output reference casing here doesn't match the producing job name. release-SetTagAndChangelog.yml defines the job as setTagAndChangelog, but this template uses SetTagAndChangelog in stageDependencies.setReleaseTagAndChangelog.SetTagAndChangelog.outputs[...]. Update the reference to use the correct job name to ensure the OutputVersion.Version value resolves reliably.

Suggested change
VERSION: $[ stageDependencies.setReleaseTagAndChangelog.SetTagAndChangelog.outputs['OutputVersion.Version'] ]
VERSION: $[ stageDependencies.setReleaseTagAndChangelog.setTagAndChangelog.outputs['OutputVersion.Version'] ]

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think copilot is right


steps:
- task: PowerShell@2
inputs:
targetType: inline
script: |
Write-Verbose -Verbose "Version: $(Version)"
Get-ChildItem Env: | Out-String -width 9999 -Stream | write-Verbose -Verbose
displayName: 'Capture Environment Variables'

- task: PowerShell@2
inputs:
targetType: inline
script: |
#Exclude all global tool packages. Their names start with 'PowerShell.'
$null = New-Item -ItemType Directory -Path "$(Pipeline.Workspace)/release"
Copy-Item "$(Pipeline.Workspace)/NuGetPackages/*.nupkg" -Destination "$(Pipeline.Workspace)/release" -Exclude "PowerShell.*.nupkg" -Force -Verbose

$releaseVersion = '$(Version)'
$globalToolPath = "$(Pipeline.Workspace)/NuGetPackages/PowerShell.$releaseVersion.nupkg"

if ($releaseVersion -notlike '*-*') {
# Copy the global tool package for stable releases
Copy-Item $globalToolPath -Destination "$(Pipeline.Workspace)/release"
}

Write-Verbose -Verbose "The .nupkgs below will be pushed:"
Get-ChildItem "$(Pipeline.Workspace)/release" -recurse
displayName: Download and capture nupkgs
condition: and(ne('${{ parameters.skipPublish }}', 'true'), succeeded())

- task: NuGetCommand@2
displayName: 'NuGet push'
condition: and(ne('${{ parameters.skipPublish }}', 'true'), succeeded())
Comment on lines +50 to +54

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

skipPublish is declared as a boolean parameter, but the job conditions compare it as a string: ne('${{ parameters.skipPublish }}', 'true'). Template booleans expand to True/False (or non-string), so this comparison can evaluate incorrectly (often always true) and unintentionally publish when skipPublish is set. Use a boolean-safe condition (for example, and(succeeded(), not(${{ parameters.skipPublish }})) or eq(${{ parameters.skipPublish }}, false)).

Suggested change
condition: and(ne('${{ parameters.skipPublish }}', 'true'), succeeded())
- task: NuGetCommand@2
displayName: 'NuGet push'
condition: and(ne('${{ parameters.skipPublish }}', 'true'), succeeded())
condition: and(succeeded(), not(${{ parameters.skipPublish }}))
- task: NuGetCommand@2
displayName: 'NuGet push'
condition: and(succeeded(), not(${{ parameters.skipPublish }}))

Copilot uses AI. Check for mistakes.
inputs:
command: push
packagesToPush: '$(Pipeline.Workspace)/release/*.nupkg'
nuGetFeedType: external
publishFeedCredentials: PowerShellNuGetOrgPush
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:
$fileContent = Get-Content -Path $OutputPath -Raw | Out-String
Write-Verbose -Verbose -Message $fileContent
displayName: Add sha256 hashes

- task: PowerShell@2
inputs:
targetType: inline
Expand All @@ -81,18 +81,18 @@ jobs:
Get-Module | Write-Verbose -Verbose

$filePath = Get-ChildItem -Path "$(Pipeline.Workspace)/CHANGELOG" -Filter '*.md' | Select-Object -First 1 -ExpandProperty FullName

if (-not (Test-Path $filePath)) {
throw "$filePath not found"
}

$changelog = Get-Content -Path $filePath

$headingPattern = "^## \[\d+\.\d+\.\d+"
$headingStartLines = $changelog | Select-String -Pattern $headingPattern | Select-Object -ExpandProperty LineNumber
$startLine = $headingStartLines[0]
$endLine = $headingStartLines[1] - 1

$clContent = $changelog | Select-Object -Skip ($startLine-1) -First ($endLine - $startLine) | Out-String

$StringBuilder = [System.Text.StringBuilder]::new($clContent, $clContent.Length + 2kb)
Expand All @@ -105,14 +105,14 @@ jobs:
}

$clContent = $StringBuilder.ToString()

Write-Verbose -Verbose "Selected content: `n$clContent"

$releaseNotesFilePath = "$(Pipeline.Workspace)/release-notes.md"
$clContent | Out-File -FilePath $releaseNotesFilePath -Encoding utf8

Write-Host "##vso[task.setvariable variable=ReleaseNotesFilePath;]$releaseNotesFilePath"

#if name has prelease then make prerelease true as a variable
if ($releaseVersion -like '*-*') {
Write-Host "##vso[task.setvariable variable=IsPreRelease;]true"
Expand Down Expand Up @@ -161,58 +161,3 @@ jobs:
action: 'create'
releaseNotesFilePath: '$(ReleaseNotesFilePath)'
isPrerelease: '$(IsPreRelease)'

- job: NuGetPublish
displayName: Publish to NuGet
condition: succeeded()
pool:
type: release
os: windows
templateContext:
inputs:
- input: pipelineArtifact
pipeline: PSPackagesOfficial
artifactName: drop_upload_upload_packages
variables:
- template: ./variables/release-shared.yml@self
parameters:
VERSION: $[ stageDependencies.setReleaseTagAndChangelog.SetTagAndChangelog.outputs['OutputVersion.Version'] ]

steps:
- task: PowerShell@2
inputs:
targetType: inline
script: |
Write-Verbose -Verbose "Version: $(Version)"
Get-ChildItem Env: | Out-String -width 9999 -Stream | write-Verbose -Verbose
displayName: 'Capture Environment Variables'

- task: PowerShell@2
inputs:
targetType: inline
script: |
#Exclude all global tool packages. Their names start with 'PowerShell.'
$null = New-Item -ItemType Directory -Path "$(Pipeline.Workspace)/release"
Copy-Item "$(Pipeline.Workspace)/NuGetPackages/*.nupkg" -Destination "$(Pipeline.Workspace)/release" -Exclude "PowerShell.*.nupkg" -Force -Verbose

$releaseVersion = '$(Version)'
$globalToolPath = "$(Pipeline.Workspace)/NuGetPackages/PowerShell.$releaseVersion.nupkg"

if ($releaseVersion -notlike '*-*') {
# Copy the global tool package for stable releases
Copy-Item $globalToolPath -Destination "$(Pipeline.Workspace)/release"
}

Write-Verbose -Verbose "The .nupkgs below will be pushed:"
Get-ChildItem "$(Pipeline.Workspace)/release" -recurse
displayName: Download and capture nupkgs
condition: and(ne('${{ parameters.skipPublish }}', 'true'), succeeded())

- task: NuGetCommand@2
displayName: 'NuGet push'
condition: and(ne('${{ parameters.skipPublish }}', 'true'), succeeded())
inputs:
command: push
packagesToPush: '$(Pipeline.Workspace)/release/*.nupkg'
nuGetFeedType: external
publishFeedCredentials: PowerShellNuGetOrgPush
20 changes: 16 additions & 4 deletions .pipelines/templates/stages/PowerShell-Release-Stages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -159,21 +159,21 @@ stages:
Update and merge the changelog for the release.
This step is required for creating GitHub draft release.

- stage: PublishGitHubReleaseAndNuget
displayName: Publish GitHub and Nuget Release
- stage: PublishGitHubRelease
displayName: Publish GitHub
dependsOn:
- setReleaseTagAndChangelog
- UpdateChangeLog
variables:
ob_release_environment: ${{ parameters.releaseEnvironment }}
jobs:
- template: /.pipelines/templates/release-githubNuget.yml@self
- template: /.pipelines/templates/release-github.yml@self
parameters:
skipPublish: ${{ parameters.SkipPublish }}

- stage: PushGitTagAndMakeDraftPublic
displayName: Push Git Tag and Make Draft Public
dependsOn: PublishGitHubReleaseAndNuget
dependsOn: PublishGitHubRelease
jobs:
- template: /.pipelines/templates/approvalJob.yml@self
parameters:
Expand All @@ -190,6 +190,18 @@ stages:
instructions: |
Make the GitHub Release Draft Public

- stage: PublishNugetRelease
displayName: Publish Nuget Release
dependsOn:

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

release-Nuget.yml reads stageDependencies.setReleaseTagAndChangelog...outputs[...], but the new PublishNugetRelease stage no longer depends on setReleaseTagAndChangelog. stageDependencies is scoped to the current stage's dependsOn, so this output reference can be undefined at runtime. Add setReleaseTagAndChangelog to PublishNugetRelease.dependsOn (or refactor to pass the version/tag into the template via parameters).

Suggested change
dependsOn:
dependsOn:
- setReleaseTagAndChangelog

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think copilot is right

- PushGitTagAndMakeDraftPublic
- UpdateChangeLog
variables:
ob_release_environment: ${{ parameters.releaseEnvironment }}
jobs:
- template: /.pipelines/templates/release-nuget.yml@self

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PublishNugetRelease references a template path that doesn't exist in this PR: the repo adds .pipelines/templates/release-Nuget.yml, but the stage includes /.pipelines/templates/release-nuget.yml@self. On case-sensitive agents/template resolution this will fail to load. Rename the file or update the template reference so the casing/name matches exactly (and keep it consistent with other release-*.yml templates).

Suggested change
- template: /.pipelines/templates/release-nuget.yml@self
- template: /.pipelines/templates/release-Nuget.yml@self

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think copilot is right

parameters:
skipPublish: ${{ parameters.SkipPublish }}

- stage: BlobPublic
displayName: Make Blob Public
dependsOn:
Expand Down
Loading