diff --git a/.github/workflows/winget.yml b/.github/workflows/winget.yml new file mode 100644 index 00000000..6630aa99 --- /dev/null +++ b/.github/workflows/winget.yml @@ -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 }}" + + diff --git a/.vscode/settings.json b/.vscode/settings.json index fe5bf673..a7ce3508 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -26,5 +26,6 @@ "vscode-nmake-tools.workspaceBuildDirectories": [ "." ], - "azure-pipelines.1ESPipelineTemplatesSchemaFile": true + "azure-pipelines.1ESPipelineTemplatesSchemaFile": true, + "powershell.codeFormatting.preset": "OTBS" } \ No newline at end of file diff --git a/build.ps1 b/build.ps1 old mode 100755 new mode 100644 index 970a186b..c346114c --- a/build.ps1 +++ b/build.ps1 @@ -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, @@ -19,6 +19,9 @@ param( [switch]$UpdateLockFile, [switch]$Audit, [switch]$UseCFSAuth, + [switch]$SubmitWinGetManifest, + [switch]$PreRelease, + [string]$GitToken, [switch]$Clean, [switch]$Verbose ) @@ -121,8 +124,7 @@ function Find-LinkExe { $linkexe = (Get-Location).Path Write-Verbose -Verbose "Using $linkexe" $linkexe - } - finally { + } finally { Pop-Location } } @@ -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 @@ -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 @@ -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" @@ -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." } } @@ -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 @@ -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 @@ -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 } @@ -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, '') @@ -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 } @@ -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) { @@ -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 } @@ -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' } @@ -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 @@ -595,8 +582,7 @@ if ($packageType -eq 'msixbundle') { if ($isPrivate) { $displayName += "-Private" - } - else { + } else { $displayName += "-Preview" } } @@ -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 + + 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" + } + + + & wingetcreate.exe update $packageId --version $version --urls $downloadUrls --submit --token $GitToken +} + +if ($SubmitWinGetManifest) { + Submit-DSCWinGetAssets -GitToken $GitToken -IsPreRelease:$PreRelease +} + +$env:RUST_BACKTRACE = 1