From e860895ac401fb7ecaff4e138d28036d036c6992 Mon Sep 17 00:00:00 2001 From: Roy <59626501+RDMacLachlan@users.noreply.github.com> Date: Tue, 17 Oct 2023 04:49:24 -0700 Subject: [PATCH 1/2] Support for converting YAML to JSON Package Manifests Support for converting YAML to JSON Package Manifests --- .../src/Library/Convert-YAMLToJSON.ps1 | 36 +++ .../src/Library/WingetClasses.ps1 | 274 ++++++++++++++++++ .../src/Microsoft.WinGet.Source.psd1 | 2 +- .../src/Microsoft.WinGet.Source.psm1 | 2 +- 4 files changed, 312 insertions(+), 2 deletions(-) create mode 100644 Tools/PowershellModule/src/Library/Convert-YAMLToJSON.ps1 create mode 100644 Tools/PowershellModule/src/Library/WingetClasses.ps1 diff --git a/Tools/PowershellModule/src/Library/Convert-YAMLToJSON.ps1 b/Tools/PowershellModule/src/Library/Convert-YAMLToJSON.ps1 new file mode 100644 index 00000000..a8b7662a --- /dev/null +++ b/Tools/PowershellModule/src/Library/Convert-YAMLToJSON.ps1 @@ -0,0 +1,36 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. +Function Convert-YamlToJson +{ + <# + .SYNOPSIS + Converts the YAML files in a specific directory to a PowerShell Object that can be exported to a JSON file. + + .DESCRIPTION + Converts the YAML files in a specific directory to a PowerShell Object that can be exported to a JSON file. + + .PARAMETER Path + Path to the directory containing YAML files. + + .EXAMPLE + Convert-YamlToJson -Path "C:\Folder\"" + + #> + + PARAM( + [Parameter(Position=0, Mandatory=$false)] [string]$Path + ) + BEGIN + { + $Files = Get-ChildItem $Path + $PackageManifest = [PackageManifest]::new() + } + PROCESS + { + $PackageManifest.ConvertFromYAML($Files) + } + END + { + Return $PackageManifest + } +} \ No newline at end of file diff --git a/Tools/PowershellModule/src/Library/WingetClasses.ps1 b/Tools/PowershellModule/src/Library/WingetClasses.ps1 new file mode 100644 index 00000000..53de81be --- /dev/null +++ b/Tools/PowershellModule/src/Library/WingetClasses.ps1 @@ -0,0 +1,274 @@ +class Locale +{ + [string]$Moniker = $null + [string]$PackageLocale = $null + [string]$Publisher = $null + [string]$PublisherUrl = $null + [string]$PublisherSupportUrl = $null + [string]$PrivacyUrl = $null + [string]$Author = $null + [string]$PackageName = $null + [string]$PackageUrl = $null + [string]$License = $null + [string]$LicenseUrl = $null + [string]$Copyright = $null + [string]$CopyrightUrl = $null + [string]$ShortDescription = $null + [string]$Description = $null + [System.Collections.ArrayList]$Tags = @() + + Locale () + {} + Locale ([Locale] $a) + { + $this = $a + } + Locale ($a) + { + $this.Moniker = $a.Moniker + $this.PackageLocale = $a.PackageLocale + $this.Publisher = $a.Publisher + $this.PublisherUrl = $a.PublisherUrl + $this.PublisherSupportUrl = $a.PublisherSupportUrl + $this.PrivacyUrl = $a.PrivacyUrl + $this.Author = $a.Author + $this.PackageName = $a.PackageName + $this.PackageUrl = $a.PackageUrl + $this.License = $a.License + $this.LicenseUrl = $a.LicenseUrl + $this.Copyright = $a.Copyright + $this.CopyrightUrl = $a.CopyRightUrl + $this.ShortDescription = $a.ShortDescription + $this.Description = $a.Description + + foreach ($Tag in $a.Tags){ + $this.Tags.add([string]::new($Tag)) + } + } +} + +class PackageDependencies +{ + [string]$PackageIdentifier = "" + [string]$MinimumVersion = "" + [System.Collections.ArrayList]$ExternalDependencies = @() + + Locale () + {} + Locale ([Locale] $a) + { + $this = $a + } + Locale ($a) + { + $this.PackageIdentifier = $a.PackageIdentifier + $this.MinimumVersion = $a.MinimumVersion + $this.ExternalDependencies = $a.ExternalDependencies + } +} + +class Dependencies +{ + [System.Collections.ArrayList]$WindowsFeatures = @() + [System.Collections.ArrayList]$WindowsLibraries = @() + [System.Collections.ArrayList]$PackageDependencies = @() + + Dependencies () + { + $this.WindowsFeatures.Add([string]::New("")) + $this.WindowsLibraries.Add([string]::New("")) + $this.PackageDependencies.Add([PackageDependencies]::New()) + } + Dependencies ([Dependencies] $a) + { + $this = $a + } + Dependencies ($a) + { + $this.WindowsFeatures = $a.WindowsFeatures + $this.WindowsLibraries = $a.WindowsLibraries + $this.PackageDependencies = $a.PackageDependencies + } +} + +class Installer +{ + $Architecture = $null + $InstallerIdentifier = $null + $InstallerSha256 = $null + $InstallerUrl = $null + $InstallerLocale = $null + [System.Collections.ArrayList]$Platform = @() + $MinimumOsVersion = $null + $InstallerType = $null + $Scope = $null + $SignatureSha256 = $null + [System.Collections.ArrayList]$InstallModes = @() + [System.Object]$InstallerSwitches = $null #Silent, SilentWithProgress, Interactive, InstallLocation, Log, Upgrade, Custom + [System.Collections.ArrayList]$InstallerSuccessCodes = @() + $UpgradeBehavior = "install" + [System.Collections.ArrayList]$Commands = @() + [System.Collections.ArrayList]$Protocols = @() + [System.Collections.ArrayList]$FileExtensions = @() + [System.Collections.ArrayList]$Dependencies = @() + $PackageFamilyName = $null + $ProductCode = $null + [System.Collections.ArrayList]$Capabilities = @() + [System.Collections.ArrayList]$RestrictedCapabilities = @() + [Boolean]$InstallerAbortsTerminal = $false + $ReleaseDate = "0001-01-01T00:00:00" + [Boolean]$InstallLocationRequired = $false + [Boolean]$RequireExplicitUpgrade = $false + [Boolean]$DisplayInstallWarnings = $false + [Boolean]$DownloadCommandProhibited = $false + + Installer () + {} + Installer ([Installer] $a) + { + $this = $a + } + Installer ($a) + { + $this.Architecture = $a.Architecture + $this.InstallerIdentifier = $a.InstallerIdentifier + $this.InstallerSha256 = $a.InstallerSha256 + $this.InstallerUrl = $a.InstallerUrl + $this.InstallerLocale = $a.InstallerLocale + $this.MinimumOsVersion = $a.MinimumOsVersion + $this.InstallerType = $a.InstallerType + $this.Scope = $a.Scope + $this.SignatureSha256 = $a.SignatureSha256 + $this.InstallModes = $a.InstallModes + $this.InstallerSwitches = $a.InstallerSwitches + $this.InstallerSuccessCodes = $a.InstallerSuccessCodes + $this.UpgradeBehavior = $a.UpgradeBehavior + $this.Commands = $a.Commands + $this.Protocols = $a.Protocols + $this.FileExtensions = $a.FileExtensions + $this.Dependencies = $a.Dependencies + $this.PackageFamilyName = $a.PackageFamilyName + $this.ProductCode = $a.ProductCode + $this.Capabilities = $a.Capabilities + $this.RestrictedCapabilities = $a.RestrictedCapabilities + + foreach ($platform in $a.Platform){ + $this.Platform.Add([string]::new($Platform)) + } + } +} + +class WingetVersion +{ + [string] $PackageVersion + [Locale] $DefaultLocale + [System.Collections.ArrayList]$Locales = @() + [System.Collections.ArrayList]$Installers = @() + + WingetVersion () + {} + WingetVersion ([WingetVersion] $a) + { + $this = $a + } + WingetVersion ($a) + { + $this.PackageVersion = $a.PackageVersion + } + AddInstaller ($a) + { + foreach ($Installer in $a.Installers) + { + $this.Installers.Add([Installer]::new($a)) + $i = $this.Installers.Count -1 + + $this.Installers[$i].Scope = $Installer.Scope + $this.Installers[$i].InstallerURL = $Installer.InstallerURL + $this.Installers[$i].InstallerSha256 = $Installer.InstallerSha256 + $this.Installers[$i].Architecture = $Installer.Architecture + $this.Installers[$i].InstallerIdentifier = "$($Installer.Architecture)-$($Installer.Scope)" + } + } + AddLocale ($a) + { + $i = $this.Locales.Count -1 + if($this.Locales[$i] -ne $([Locale]::new())){ + $this.Locales.Add([Locale]::new()) + } + + $i = $this.Locales.Count -1 + $this.locales[$i] = [Locale]::new($a) + } + AddDefaultLocale ($a) + { + $this.DefaultLocale = [Locale]::new($a) + } +} + +class PackageManifest +{ + $PackageIdentifier = "" + [System.Collections.ArrayList]$Versions = @() + [System.Collections.ArrayList]$ExternalDependencies = @() + + + PackageManifest () + { + } + PackageManifest ([PackageManifest] $a) + { + $this = $a + } + PackageManifest ($a) + { + $this.PackageIdentifier = $a.PackageIdentifier + $this.Versions = $a.Version + } + AddVersion ($a) + { + $this.Versions.Add([WingetVersion]::new($a)) + } + AddVersion ($a, $b, $c) + { + Write-Host $a + $this.Versions.Add([WingetVersion]::new($a)) + $i = $this.Versions.Count -1 + + foreach ($installer in $b){ + $this.Versions[$i].AddInstaller($installer) + } + foreach ($locale in $c){ + $this.Versions.AddLocale($locale) + + if($locale.ManifestType -eq "defaultLocale"){ + $this.Versions.AddDefaultLocale($locale) + } + } + } + ConvertFromYAML ($a) + { + [System.Collections.ArrayList]$YAMLInstallers = @() + [System.Collections.ArrayList]$YAMLLocales = @() + [System.Collections.ArrayList]$YAMLVersions = @() + + foreach ($file in $a){ + $FileContents = Get-Content -Raw -Path $file.FullName + + if ($FileContents.Contains('$schema=https://aka.ms/winget-manifest.installer')){ + $ConvertedContents = ConvertFrom-Yaml -Yaml $FileContents + $YAMLInstallers.Add(($ConvertedContents)) + } + elseif ($FileContents.Contains('$schema=https://aka.ms/winget-manifest.defaultLocale')){ + $ConvertedContents = ConvertFrom-Yaml -Yaml $FileContents + $YAMLLocales.Add(($ConvertedContents)) + } + elseif ($FileContents.Contains('$schema=https://aka.ms/winget-manifest.version')){ + $ConvertedContents = ConvertFrom-Yaml -Yaml $FileContents + $YAMLVersions.Add(($ConvertedContents)) + } + } + + $this.PackageIdentifier = $YAMLVersions[0].PackageIdentifier + $this.AddVersion($YAMLVersions[0], $YAMLInstallers, $YAMLLocales) + } +} \ No newline at end of file diff --git a/Tools/PowershellModule/src/Microsoft.WinGet.Source.psd1 b/Tools/PowershellModule/src/Microsoft.WinGet.Source.psd1 index 322321d6..a693b843 100644 --- a/Tools/PowershellModule/src/Microsoft.WinGet.Source.psd1 +++ b/Tools/PowershellModule/src/Microsoft.WinGet.Source.psd1 @@ -71,7 +71,7 @@ # NestedModules = @() # Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. - FunctionsToExport = @("Add-WinGetManifest", "Get-WinGetManifest", "Remove-WinGetManifest", "New-WinGetSource") + FunctionsToExport = @("Add-WinGetManifest", "Get-WinGetManifest", "Remove-WinGetManifest", "New-WinGetSource", "Convert-YamlToJson") # Cmdlets to export from this module, for best performance, do not use wild cards and do not delete the entry, use an empty array if there are no cmdlets to export. CmdletsToExport = @() diff --git a/Tools/PowershellModule/src/Microsoft.WinGet.Source.psm1 b/Tools/PowershellModule/src/Microsoft.WinGet.Source.psm1 index c8c063f3..77e8f92a 100644 --- a/Tools/PowershellModule/src/Microsoft.WinGet.Source.psm1 +++ b/Tools/PowershellModule/src/Microsoft.WinGet.Source.psm1 @@ -28,7 +28,7 @@ else { } ## Validates that the required Azure Modules are present when the script is imported. -[string[]]$RequiredModules = @("Az.Resources", "Az.Accounts", "Az.Websites", "Az.Functions") +[string[]]$RequiredModules = @("Az.Resources", "Az.Accounts", "Az.Websites", "Az.Functions", "powershell-yaml") ## Verifies that the Azure Modules were previously installed. [Boolean] $TestResult = Test-PowerShellModuleExist -Modules $RequiredModules From a462caba105cdff8b9583d4c686c76d048b2fa60 Mon Sep 17 00:00:00 2001 From: Zach Carpenter Date: Tue, 17 Oct 2023 10:08:43 -0500 Subject: [PATCH 2/2] Remove Triggers and Filters --- pipelines/winget-cli-restsource-ci-pr.yml | 31 +++++++---------------- 1 file changed, 9 insertions(+), 22 deletions(-) diff --git a/pipelines/winget-cli-restsource-ci-pr.yml b/pipelines/winget-cli-restsource-ci-pr.yml index 6f04b1c8..b3f4b63b 100644 --- a/pipelines/winget-cli-restsource-ci-pr.yml +++ b/pipelines/winget-cli-restsource-ci-pr.yml @@ -1,31 +1,18 @@ # Copyright (c) Microsoft Corporation. All rights reserved # CI pipeline for winget-cli-restsource -# Standard Triggers -trigger: none - -# PR triggers -pr: - branches: - include: - - main - paths: - include: - - pipelines/* - - src/* - -# TODO: The forked pr builds need to have the same permission as non-forked ones to access -# project's internal nuget feed. Remove DisablePipelineConfigDetector variable when -# a long term fix is available. -variables: -- name: DisablePipelineConfigDetector - value: true +# TODO: The forked pr builds need to have the same permission as non-forked ones to access +# project's internal nuget feed. Remove DisablePipelineConfigDetector variable when +# a long term fix is available. +variables: +- name: DisablePipelineConfigDetector + value: true jobs: - job: 'BuildPublishTest' displayName: 'Build Publish & Tests' timeoutInMinutes: 60 - pool: + pool: name: 'Azure Pipelines' vmImage: windows-latest demands: @@ -43,7 +30,7 @@ jobs: - job: 'StaticAnalysis' displayName: 'Static Analysis' timeoutInMinutes: 60 - pool: + pool: name: 'Azure Pipelines' vmImage: windows-latest demands: @@ -68,4 +55,4 @@ jobs: - task: securedevelopmentteam.vss-secure-development-tools.build-task-postanalysis.PostAnalysis@1 displayName: 'Post Analysis' inputs: - CredScan: true + CredScan: true