Skip to content

Winget manifest uploader #620

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
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: 27 additions & 0 deletions .github/workflows/winget.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Publish to Winget

on:
release:
types: [published]


env:
REGEX: 'DSC-(\d+\.\d+\.\d+(?:-preview\.\d+)?)-(?:x86_64|aarch64)-pc-windows-msvc\.zip'

jobs:
publish:
runs-on: windows-latest # Action can only run on Windows
steps:
- name: Publish Microsoft.DSC ${{ github.event.release.prerelease && 'Preview' || 'Stable' }}
run: |
$assets = '${{ toJSON(github.event.release.assets) }}' | ConvertFrom-Json
$wingetRelevantAsset = $assets | Where-Object { $_.name -like '*.zip' -and $_.name -like '*.msixbundle' } | Select-Object -First 1
$regex = [Regex]::New($env:REGEX)
$version = $regex.Match($wingetRelevantAsset.name).Groups[1].Value

$wingetPackage = "Microsoft.DSC${{ github.event.release.prerelease && '.Preview' || '' }}"

& curl.exe -JLO https://aka.ms/wingetcreate/latest
& .\wingetcreate.exe update $wingetPackage -s -v $version -u $wingetRelevantAsset.browser_download_url -t "${{ secrets.WINGET_TOKEN }}"


3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@
"vscode-nmake-tools.workspaceBuildDirectories": [
"."
],
"azure-pipelines.1ESPipelineTemplatesSchemaFile": true
"azure-pipelines.1ESPipelineTemplatesSchemaFile": true,
"powershell.codeFormatting.preset": "OTBS"
}
116 changes: 72 additions & 44 deletions build.ps1
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

param(
[switch]$Release,
[ValidateSet('current','aarch64-pc-windows-msvc','x86_64-pc-windows-msvc','aarch64-apple-darwin','x86_64-apple-darwin','aarch64-unknown-linux-gnu','aarch64-unknown-linux-musl','x86_64-unknown-linux-gnu','x86_64-unknown-linux-musl')]
[ValidateSet('current', 'aarch64-pc-windows-msvc', 'x86_64-pc-windows-msvc', 'aarch64-apple-darwin', 'x86_64-apple-darwin', 'aarch64-unknown-linux-gnu', 'aarch64-unknown-linux-musl', 'x86_64-unknown-linux-gnu', 'x86_64-unknown-linux-musl')]
$architecture = 'current',
[switch]$Clippy,
[switch]$SkipBuild,
[ValidateSet('msix','msix-private','msixbundle','tgz','zip')]
[ValidateSet('msix', 'msix-private', 'msixbundle', 'tgz', 'zip')]
$packageType,
[switch]$Test,
[switch]$GetPackageVersion,
Expand All @@ -19,6 +19,9 @@ param(
[switch]$UpdateLockFile,
[switch]$Audit,
[switch]$UseCFSAuth,
[switch]$SubmitWinGetManifest,
[switch]$PreRelease,
[string]$GitToken,
[switch]$Clean,
[switch]$Verbose
)
Expand Down Expand Up @@ -121,8 +124,7 @@ function Find-LinkExe {
$linkexe = (Get-Location).Path
Write-Verbose -Verbose "Using $linkexe"
$linkexe
}
finally {
} finally {
Pop-Location
}
}
Expand All @@ -149,8 +151,7 @@ if ($null -ne $packageType) {
if (!$IsWindows) {
curl https://sh.rustup.rs -sSf | sh -s -- -y
$env:PATH += ":$env:HOME/.cargo/bin"
}
else {
} else {
Invoke-WebRequest 'https://static.rust-lang.org/rustup/dist/i686-pc-windows-gnu/rustup-init.exe' -OutFile 'temp:/rustup-init.exe'
Write-Verbose -Verbose "Use the default settings to ensure build works"
& 'temp:/rustup-init.exe' -y
Expand All @@ -172,9 +173,9 @@ if (!$SkipBuild -and !$SkipLinkCheck -and $IsWindows -and !(Get-Command 'link.ex
if (!(Test-Path $BuildToolsPath)) {
Write-Verbose -Verbose "link.exe not found, installing C++ build tools"
Invoke-WebRequest 'https://aka.ms/vs/17/release/vs_BuildTools.exe' -OutFile 'temp:/vs_buildtools.exe'
$arg = @('--passive','--add','Microsoft.VisualStudio.Workload.VCTools','--includerecommended')
$arg = @('--passive', '--add', 'Microsoft.VisualStudio.Workload.VCTools', '--includerecommended')
if ($env:PROCESSOR_ARCHITECTURE -eq 'ARM64') {
$arg += '--add','Microsoft.VisualStudio.Component.VC.Tools.ARM64'
$arg += '--add', 'Microsoft.VisualStudio.Component.VC.Tools.ARM64'
}
Start-Process -FilePath 'temp:/vs_buildtools.exe' -ArgumentList $arg -Wait
Remove-Item temp:/vs_installer.exe -ErrorAction Ignore
Expand Down Expand Up @@ -204,8 +205,7 @@ $flags = @($Release ? '-r' : $null)
if ($architecture -eq 'current') {
$path = ".\target\$configuration"
$target = Join-Path $PSScriptRoot 'bin' $configuration
}
else {
} else {
$flags += '--target'
$flags += $architecture
$path = ".\target\$architecture\$configuration"
Expand Down Expand Up @@ -248,8 +248,7 @@ if (!$SkipBuild) {
$env:CARGO_REGISTRIES_POWERSHELL_TOKEN = $header
$env:CARGO_REGISTRIES_POWERSHELL_CREDENTIAL_PROVIDER = 'cargo:token'
}
}
else {
} else {
Write-Warning "Azure CLI not found, proceeding with anonymous access."
}
}
Expand Down Expand Up @@ -302,8 +301,7 @@ if (!$SkipBuild) {
if ($project -eq 'tree-sitter-dscexpression') {
if ($UpdateLockFile) {
cargo generate-lockfile
}
else {
} else {
if ($Audit) {
if ($null -eq (Get-Command cargo-audit -ErrorAction Ignore)) {
cargo install cargo-audit --features=fix
Expand All @@ -316,26 +314,21 @@ if (!$SkipBuild) {
}
}

if (Test-Path "./Cargo.toml")
{
if (Test-Path "./Cargo.toml") {
if ($Clippy) {
if ($clippy_unclean_projects -contains $project) {
Write-Verbose -Verbose "Skipping clippy for $project"
}
elseif ($pedantic_unclean_projects -contains $project) {
} elseif ($pedantic_unclean_projects -contains $project) {
Write-Verbose -Verbose "Running clippy for $project"
cargo clippy @flags -- -Dwarnings
}
else {
} else {
Write-Verbose -Verbose "Running clippy with pedantic for $project"
cargo clippy @flags --% -- -Dwarnings -Dclippy::pedantic
}
}
else {
} else {
if ($UpdateLockFile) {
cargo generate-lockfile
}
else {
} else {
if ($Audit) {
if ($null -eq (Get-Command cargo-audit -ErrorAction Ignore)) {
cargo install cargo-audit --features=fix
Expand Down Expand Up @@ -363,8 +356,7 @@ if (!$SkipBuild) {
if ($IsWindows) {
Copy-Item "$path/$binary.exe" $target -ErrorAction Ignore -Verbose
Copy-Item "$path/$binary.pdb" $target -ErrorAction Ignore -Verbose
}
else {
} else {
Copy-Item "$path/$binary" $target -ErrorAction Ignore -Verbose
}

Expand Down Expand Up @@ -421,8 +413,7 @@ if (!$Clippy -and !$SkipBuild) {
$dirSeparator = [System.IO.Path]::DirectorySeparatorChar
if ($Release) {
$oldTarget = $target.Replace($dirSeparator + 'release', $dirSeparator + 'debug')
}
else {
} else {
$oldTarget = $target.Replace($dirSeparator + 'debug', $dirSeparator + 'release')
}
$env:PATH = $env:PATH.Replace($oldTarget, '')
Expand Down Expand Up @@ -461,15 +452,14 @@ if ($Test) {

if ($IsWindows) {
# PSDesiredStateConfiguration module is needed for Microsoft.Windows/WindowsPowerShell adapter
$FullyQualifiedName = @{ModuleName="PSDesiredStateConfiguration";ModuleVersion="2.0.7"}
if (-not(Get-Module -ListAvailable -FullyQualifiedName $FullyQualifiedName))
{
$FullyQualifiedName = @{ModuleName = "PSDesiredStateConfiguration"; ModuleVersion = "2.0.7" }
if (-not(Get-Module -ListAvailable -FullyQualifiedName $FullyQualifiedName)) {
Install-PSResource -Name PSDesiredStateConfiguration -Version 2.0.7 -Repository $repository -TrustRepository
}
}

if (-not(Get-Module -ListAvailable -Name Pester))
{ "Installing module Pester"
if (-not(Get-Module -ListAvailable -Name Pester)) {
"Installing module Pester"
Install-PSResource Pester -WarningAction Ignore -Repository $repository -TrustRepository
}

Expand All @@ -482,8 +472,7 @@ if ($Test) {
Write-Host -ForegroundColor Cyan "Testing $project ..."
try {
Push-Location "$PSScriptRoot/$project"
if (Test-Path "./Cargo.toml")
{
if (Test-Path "./Cargo.toml") {
cargo test

if ($LASTEXITCODE -ne 0) {
Expand Down Expand Up @@ -512,8 +501,8 @@ if ($Test) {
"Updated PSModulePath is:"
$env:PSModulePath

if (-not(Get-Module -ListAvailable -Name Pester))
{ "Installing module Pester"
if (-not(Get-Module -ListAvailable -Name Pester)) {
"Installing module Pester"
$InstallTargetDir = ($env:PSModulePath -split ";")[0]
Find-PSResource -Name 'Pester' -Repository $repository | Save-PSResource -Path $InstallTargetDir -TrustRepository
}
Expand All @@ -531,8 +520,7 @@ function Find-MakeAppx() {
# try to find
if (!$UseX64MakeAppx -and $architecture -eq 'aarch64-pc-windows-msvc') {
$arch = 'arm64'
}
else {
} else {
$arch = 'x64'
}

Expand Down Expand Up @@ -577,8 +565,7 @@ if ($packageType -eq 'msixbundle') {
Write-Verbose -Verbose "Preview version detected"
if ($isPrivate) {
$productName += "-Private"
}
else {
} else {
$productName += "-Preview"
}
# save preview number
Expand All @@ -595,8 +582,7 @@ if ($packageType -eq 'msixbundle') {

if ($isPrivate) {
$displayName += "-Private"
}
else {
} else {
$displayName += "-Preview"
}
}
Expand Down Expand Up @@ -746,4 +732,46 @@ if ($packageType -eq 'msixbundle') {
Write-Host -ForegroundColor Green "`ntar.gz file is created at $tarFile"
}

$env:RUST_BACKTRACE=1
function Submit-DSCWinGetAssets {
param(
[string]$GitToken,
[switch] $IsPreRelease
)

$project = 'PowerShell/DSC'
$packageId = 'Microsoft.DSC'
$restParameters = @{
SslProtocol = 'Tls13'
Headers = @{'X-GitHub-Api-Version' = '2022-11-28' }
}

$assets = ((Invoke-RestMethod -uri "https://api.github.com/repos/$Project/releases" -Headers $restParameters) |
Where-Object -Property prerelease -EQ $IsPreRelease.IsPresent |
Select-Object -First 1 -Property assets).assets # ExpandProperty did not work
# Grab the download URLs for supported WinGet

$downloadUrls = $assets.Where({ $_.content_type -in @('application/zip', 'application/octet-stream') }).browser_download_url

Choose a reason for hiding this comment

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

This will break if a new zip based asset is added in the future. I suggest regex matching specific installers from the assets. One can refer to the sample workflows I shared above on how


if (-not (Get-Command wingetcreate -ErrorAction SilentlyContinue)) {
Invoke-RestMethod https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe
}

# TODO: Version number might change in the future
$url = $downloadUrls[0]
if ($url -match 'v(\d+\.\d+\.\d+)-preview\.(\d+)') {
$firstPart = $matches[1].Remove(3) # Remove the last digit
$lastPart = $matches[2] + ".0"
$version = "$firstPart.$lastPart"

$packageId = "$packageId.Preview"
}
Comment on lines +760 to +767
Copy link

@mdanish-kh mdanish-kh Jun 6, 2025

Choose a reason for hiding this comment

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

Why not grab the version from the GitHub API response itself (there's a tag_name field in the response) instead of manually parsing it from the URL?



& wingetcreate.exe update $packageId --version $version --urls $downloadUrls --submit --token $GitToken

Choose a reason for hiding this comment

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

With wingetcreate, you have to be explicit with how many URLs you're passing to the update command, because otherwise the update command will fail if the number of installers in the latest manifest at winget-pkgs don't match what's passed in the update command.

What this means is - if we're including MSIX in the latest manifest at winget-pkgs, this update command must also contain the MSIX URL otherwise the update will fail. I know the MSIX installer availability is delayed for any DSC releases so that may be an area of concern. If we're not including MSIX in the latest winget-pkgs manifests, then the workflow will work as intended

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hey @mdanish-kh, thanks for jumping in, I appreciate it!

I have now created a winget.yml file. Do you mind having a glimpse one more time? If it's okay, I'll remove the other content from the build.ps1.

Coming back to the MSIX, it depends if it will be added to the assets. @SteveL-MSFT ?

Copy link
Member

@SteveL-MSFT SteveL-MSFT Jun 7, 2025

Choose a reason for hiding this comment

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

msixbundle will be added to the assets in the near future for 3.2

}

if ($SubmitWinGetManifest) {
Submit-DSCWinGetAssets -GitToken $GitToken -IsPreRelease:$PreRelease
}

$env:RUST_BACKTRACE = 1
Loading