Skip to content
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

YamlCreate v2.0.5 #41445

Merged
merged 6 commits into from
Jan 24, 2022
Merged
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
131 changes: 103 additions & 28 deletions Tools/YamlCreate.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,22 @@ if ($help) {
exit
}

# Installs `powershell-yaml` as a dependency for parsing yaml content
if (-not(Get-Module -ListAvailable -Name powershell-yaml)) {
try {
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Install-Module -Name powershell-yaml -Force -Repository PSGallery -Scope CurrentUser
} catch {
# If there was an exception while installing powershell-yaml, pass it as an InternalException for further debugging
throw [UnmetDependencyException]::new("'powershell-yaml' unable to be installed successfully", $_.Exception)
} finally {
# Double check that it was installed properly
if (-not(Get-Module -ListAvailable -Name powershell-yaml)) {
throw [UnmetDependencyException]::new("'powershell-yaml' is not found")
}
}
}

# Set settings directory on basis of Operating System
$script:SettingsPath = Join-Path $(if ([System.Environment]::OSVersion.Platform -match 'Win') { $env:LOCALAPPDATA } else { $env:HOME + '/.config' } ) -ChildPath 'YamlCreate'
# Check for settings directory and create it if none exists
Expand All @@ -38,7 +54,7 @@ if ($Settings) {
exit
}

$ScriptHeader = '# Created with YamlCreate.ps1 v2.0.4'
$ScriptHeader = '# Created with YamlCreate.ps1 v2.0.5'
$ManifestVersion = '1.1.0'
$PSDefaultParameterValues = @{ '*:Encoding' = 'UTF8' }
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
Expand Down Expand Up @@ -67,22 +83,6 @@ $ofs = ', '
https://github.com/microsoft/winget-pkgs/blob/master/Tools/YamlCreate.ps1
#>

# Installs `powershell-yaml` as a dependency for parsing yaml content
if (-not(Get-Module -ListAvailable -Name powershell-yaml)) {
try {
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Install-Module -Name powershell-yaml -Force -Repository PSGallery -Scope CurrentUser
} catch {
# If there was an exception while installing powershell-yaml, pass it as an InternalException for further debugging
throw [UnmetDependencyException]::new("'powershell-yaml' unable to be installed successfully", $_.Exception)
} finally {
# Double check that it was installed properly
if (-not(Get-Module -ListAvailable -Name powershell-yaml)) {
throw [UnmetDependencyException]::new("'powershell-yaml' is not found")
}
}
}

# Fetch Schema data from github for entry validation, key ordering, and automatic commenting
try {
$ProgressPreference = 'SilentlyContinue'
Expand Down Expand Up @@ -162,6 +162,8 @@ $Patterns = @{
ValidInstallModes = $InstallerSchema.definitions.InstallModes.items.enum
FileExtension = $InstallerSchema.definitions.FileExtensions.items.pattern
FileExtensionMaxLength = $InstallerSchema.definitions.FileExtensions.items.maxLength
ReleaseNotesMinLength = $LocaleSchema.properties.ReleaseNotes.MinLength
ReleaseNotesMaxLength = $LocaleSchema.properties.ReleaseNotes.MaxLength
}

# This function validates whether a string matches Minimum Length, Maximum Length, and Regex pattern
Expand Down Expand Up @@ -458,7 +460,9 @@ Function Read-InstallerEntry {
if ($_) { $_Installer['InstallerType'] = $_ | Select-Object -First 1 }
Get-UriArchitecture -URI $_Installer['InstallerUrl'] -OutVariable _ | Out-Null
if ($_) { $_Installer['Architecture'] = $_ | Select-Object -First 1 }
$ProductCode = $(Get-AppLockerFileInformation -Path $script:dest | Select-Object Publisher | Select-String -Pattern '{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}}').Matches
if ([System.Environment]::OSVersion.Platform -match 'Win') {
$MSIProductCode = [string]$(Get-AppLockerFileInformation -Path $script:dest | Select-Object Publisher | Select-String -Pattern '{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}}').Matches
}
if (Test-String -Not "$ProductCode" -IsNull) { $_Installer['ProductCode'] = "$ProductCode" }
}
}
Expand Down Expand Up @@ -699,6 +703,26 @@ Function Read-InstallerEntry {
'U' { $_Installer['UpgradeBehavior'] = 'uninstallPrevious' }
default { $_Installer['UpgradeBehavior'] = 'install' }
}
Write-Host

# Request release date
$script:ReleaseDatePrompted = $true
do {
Write-Host -ForegroundColor 'Red' $script:_returnValue.ErrorString()
Write-Host -ForegroundColor 'Yellow' -Object '[Optional] Enter the application release date. Example: 2021-11-17'
Read-Host -Prompt 'ReleaseDate' -OutVariable ReleaseDate | Out-Null
try {
Get-Date([datetime]$($ReleaseDate | TrimString)) -f 'yyyy-MM-dd' -OutVariable _ValidDate | Out-Null
if ($_ValidDate) { $_Installer['ReleaseDate'] = $_ValidDate | TrimString }
$script:_returnValue = [ReturnValue]::Success()
} catch {
if (Test-String $ReleaseDate -IsNull) {
$script:_returnValue = [ReturnValue]::Success()
} else {
$script:_returnValue = [ReturnValue]::new(400, 'Invalid Date', 'Input could not be resolved to a date', 2)
}
}
} until ($script:_returnValue.StatusCode -eq [ReturnValue]::Success().StatusCode)

if ($script:SaveOption -eq '1' -and (Test-Path -Path $script:dest)) { Remove-Item -Path $script:dest }

Expand Down Expand Up @@ -785,10 +809,12 @@ Function Read-QuickInstallerEntry {
$_NewInstaller['InstallerSha256'] = (Get-FileHash -Path $script:dest -Algorithm SHA256).Hash
# Update the product code, if a new one exists
# If a new product code doesn't exist, and the installer isn't an `.exe` file, remove the product code if it exists
$MSIProductCode = [string]$(Get-AppLockerFileInformation -Path $script:dest | Select-Object Publisher | Select-String -Pattern '{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}}').Matches
if ([System.Environment]::OSVersion.Platform -match 'Win') {
$MSIProductCode = [string]$(Get-AppLockerFileInformation -Path $script:dest | Select-Object Publisher | Select-String -Pattern '{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}}').Matches
}
if (Test-String -not $MSIProductCode -IsNull) {
$_NewInstaller['ProductCode'] = $MSIProductCode
} elseif ( ($_NewInstaller.Keys -contains 'ProductCode') -and ($_NewInstaller.InstallerType -in @('appx';'msi';'msix';'appxbundle';'msixbundle'))) {
} elseif ( ($_NewInstaller.Keys -contains 'ProductCode') -and ($_NewInstaller.InstallerType -in @('appx'; 'msi'; 'msix'; 'appxbundle'; 'msixbundle'))) {
$_NewInstaller.Remove('ProductCode')
}
# If the installer is msix or appx, try getting the new SignatureSha256
Expand Down Expand Up @@ -1279,6 +1305,36 @@ Function Read-LocaleMetadata {
$script:_returnValue = [ReturnValue]::LengthError($Patterns.DescriptionMinLength, $Patterns.DescriptionMaxLength)
}
} until ($script:_returnValue.StatusCode -eq [ReturnValue]::Success().StatusCode)

# Request ReleaseNotes and Validate
do {
Write-Host -ForegroundColor 'Red' $script:_returnValue.ErrorString()
Write-Host -ForegroundColor 'Yellow' -Object '[Optional] Enter release notes for this version of the package.'
$script:ReleaseNotes = Read-Host -Prompt 'ReleaseNotes' | TrimString
if (Test-String $script:ReleaseNotes -MinLength $Patterns.ReleaseNotesMinLength -MaxLength $Patterns.ReleaseNotesMaxLength -AllowNull) {
$script:_returnValue = [ReturnValue]::Success()
} else {
$script:_returnValue = [ReturnValue]::LengthError($Patterns.ReleaseNotesMinLength, $Patterns.ReleaseNotesMaxLength)
}
} until ($script:_returnValue.StatusCode -eq [ReturnValue]::Success().StatusCode)

# Request ReleaseNotes URL and Validate
do {
Write-Host -ForegroundColor 'Red' $script:_returnValue.ErrorString()
Write-Host -ForegroundColor 'Yellow' -Object '[Optional] Enter the release notes URL for this version of the package.'
$script:ReleaseNotesUrl = Read-Host -Prompt 'ReleaseNotesUrl' | TrimString
if (Test-String $script:ReleaseNotesUrl -MaxLength $Patterns.GenericUrlMaxLength -MatchPattern $Patterns.GenericUrl -AllowNull) {
$script:_returnValue = [ReturnValue]::Success()
} else {
if (Test-String -not $script:ReleaseNotesUrl -MaxLength $Patterns.GenericUrlMaxLength -AllowNull) {
$script:_returnValue = [ReturnValue]::LengthError(1, $Patterns.GenericUrlMaxLength)
} elseif (Test-String -not $script:ReleaseNotesUrl -MatchPattern $Patterns.GenericUrl) {
$script:_returnValue = [ReturnValue]::PatternError()
} else {
$script:_returnValue = [ReturnValue]::GenericError()
}
}
} until ($script:_returnValue.StatusCode -eq [ReturnValue]::Success().StatusCode)
}

# Requests the user to answer the prompts found in the winget-pkgs pull request template
Expand Down Expand Up @@ -1564,6 +1620,10 @@ Function Write-InstallerManifest {
$InstallerManifest['Installers'] = $script:OldVersionManifest['Installers']
}

foreach ($_Installer in $InstallerManifest.Installers){
if ($_Installer['ReleaseDate'] -and !$script:ReleaseDatePrompted) { $_Installer.Remove('ReleaseDate') }
}

Add-YamlParameter -Object $InstallerManifest -Parameter 'ManifestType' -Value 'installer'
Add-YamlParameter -Object $InstallerManifest -Parameter 'ManifestVersion' -Value $ManifestVersion
If ($InstallerManifest['Dependencies']) {
Expand Down Expand Up @@ -1633,7 +1693,7 @@ Function Write-InstallerManifest {

# Create the folder for the file if it doesn't exist
New-Item -ItemType 'Directory' -Force -Path $AppFolder | Out-Null
$InstallerManifestPath = $AppFolder + "\$PackageIdentifier" + '.installer' + '.yaml'
$script:InstallerManifestPath = $AppFolder + "\$PackageIdentifier" + '.installer' + '.yaml'

# Write the manifest to the file
$ScriptHeader + "$(Get-DebugString)`n# yaml-language-server: `$schema=https://aka.ms/winget-manifest.installer.$ManifestVersion.schema.json`n" > $InstallerManifestPath
Expand All @@ -1655,9 +1715,6 @@ Function Write-LocaleManifest {
}
if (!$LocaleManifest) { [PSCustomObject]$LocaleManifest = [ordered]@{} }

# Set the appropriate langage server depending on if it is a default locale file or generic locale file
if ($LocaleManifest.ManifestType -eq 'defaultLocale') { $yamlServer = "# yaml-language-server: `$schema=https://aka.ms/winget-manifest.defaultLocale.$ManifestVersion.schema.json" } else { $yamlServer = "# yaml-language-server: `$schema=https://aka.ms/winget-manifest.locale.$ManifestVersion.schema.json" }

# Add the properties to the manifest
$_Singletons = [ordered]@{
'PackageIdentifier' = $PackageIdentifier
Expand All @@ -1676,6 +1733,8 @@ Function Write-LocaleManifest {
'CopyrightUrl' = $CopyrightUrl
'ShortDescription' = $ShortDescription
'Description' = $Description
'ReleaseNotes' = $ReleaseNotes
'ReleaseNotesUrl' = $ReleaseNotesUrl
}
foreach ($_Item in $_Singletons.GetEnumerator()) {
If ($_Item.Value) { Add-YamlParameter -Object $LocaleManifest -Parameter $_Item.Name -Value $_Item.Value }
Expand All @@ -1690,8 +1749,15 @@ Function Write-LocaleManifest {
if ($LocaleManifest['Tags']) { $LocaleManifest['Tags'] = @($LocaleManifest['Tags'] | ToLower | UniqueItems | NoWhitespace | Sort-Object) }
if ($LocaleManifest['Moniker']) { $LocaleManifest['Moniker'] = $LocaleManifest['Moniker'] | ToLower | NoWhitespace }

# Clean up the volatile fields
if ($LocaleManifest['ReleaseNotes'] -and (Test-String $script:ReleaseNotes -IsNull)) { $LocaleManifest.Remove('ReleaseNotes') }
if ($LocaleManifest['ReleaseNotesUrl'] -and (Test-String $script:ReleaseNotes -IsNull)) { $LocaleManifest.Remove('ReleaseNotesUrl') }

$LocaleManifest = Restore-YamlKeyOrder $LocaleManifest $LocaleProperties

# Set the appropriate langage server depending on if it is a default locale file or generic locale file
if ($LocaleManifest.ManifestType -eq 'defaultLocale') { $yamlServer = "# yaml-language-server: `$schema=https://aka.ms/winget-manifest.defaultLocale.$ManifestVersion.schema.json" } else { $yamlServer = "# yaml-language-server: `$schema=https://aka.ms/winget-manifest.locale.$ManifestVersion.schema.json" }

# Create the folder for the file if it doesn't exist
New-Item -ItemType 'Directory' -Force -Path $AppFolder | Out-Null
$script:LocaleManifestPath = $AppFolder + "\$PackageIdentifier" + '.locale.' + "$PackageLocale" + '.yaml'
Expand All @@ -1714,6 +1780,11 @@ Function Write-LocaleManifest {
$script:OldLocaleManifest['ManifestVersion'] = $ManifestVersion
# Clean up the existing files just in case
if ($script:OldLocaleManifest['Tags']) { $script:OldLocaleManifest['Tags'] = @($script:OldLocaleManifest['Tags'] | ToLower | UniqueItems | NoWhitespace | Sort-Object) }

# Clean up the volatile fields
if ($OldLocaleManifest['ReleaseNotes'] -and (Test-String $script:ReleaseNotes -IsNull)) { $OldLocaleManifest.Remove('ReleaseNotes') }
if ($OldLocaleManifest['ReleaseNotesUrl'] -and (Test-String $script:ReleaseNotes -IsNull)) { $OldLocaleManifest.Remove('ReleaseNotesUrl') }

$script:OldLocaleManifest = Restore-YamlKeyOrder $script:OldLocaleManifest $LocaleProperties

$yamlServer = "# yaml-language-server: `$schema=https://aka.ms/winget-manifest.locale.$ManifestVersion.schema.json"
Expand Down Expand Up @@ -2142,10 +2213,12 @@ Switch ($script:Option) {
$_Installer['InstallerSha256'] = (Get-FileHash -Path $script:dest -Algorithm SHA256).Hash
# Update the product code, if a new one exists
# If a new product code doesn't exist, and the installer isn't an `.exe` file, remove the product code if it exists
$MSIProductCode = [string]$(Get-AppLockerFileInformation -Path $script:dest | Select-Object Publisher | Select-String -Pattern '{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}}').Matches
if ([System.Environment]::OSVersion.Platform -match 'Win') {
$MSIProductCode = [string]$(Get-AppLockerFileInformation -Path $script:dest | Select-Object Publisher | Select-String -Pattern '{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}}').Matches
}
if (Test-String -not $MSIProductCode -IsNull) {
$_Installer['ProductCode'] = $MSIProductCode
} elseif ( ($_Installer.Keys -contains 'ProductCode') -and ($_Installer.InstallerType -in @('appx';'msi';'msix';'appxbundle';'msixbundle'))) {
} elseif ( ($_Installer.Keys -contains 'ProductCode') -and ($_Installer.InstallerType -in @('appx'; 'msi'; 'msix'; 'appxbundle'; 'msixbundle'))) {
$_Installer.Remove('ProductCode')
}
# If the installer is msix or appx, try getting the new SignatureSha256
Expand Down Expand Up @@ -2279,8 +2352,10 @@ if ($PromptSubmit -eq '0') {
git switch -d upstream/master
if ($LASTEXITCODE -eq '0') {
# Make sure path exists and is valid before hashing
if ($script:LocaleManifestPath -and (Test-Path -Path $script:LocaleManifestPath)) { $UniqueBranchID = $(Get-FileHash $script:LocaleManifestPath).Hash[0..6] -Join '' }
else { $UniqueBranchID = 'DEL' }
$UniqueBranchID = ''
if ($script:LocaleManifestPath -and (Test-Path -Path $script:LocaleManifestPath)) { $UniqueBranchID = $UniqueBranchID + $($(Get-FileHash $script:LocaleManifestPath).Hash[0..6] -Join '') }
if ($script:InstallerManifestPath -and (Test-Path -Path $script:InstallerManifestPath)) { $UniqueBranchID = $UniqueBranchID + $($(Get-FileHash $script:InstallerManifestPath).Hash[0..6] -Join '') }
if (Test-String -IsNull $UniqueBranchID) { $UniqueBranchID = 'DEL' }
$BranchName = "$PackageIdentifier-$PackageVersion-$UniqueBranchID"
# Git branch names cannot start with `.` cannot contain any of {`..`, `\`, `~`, `^`, `:`, ` `, `?`, `@{`, `[`}, and cannot end with {`/`, `.lock`, `.`}
$BranchName = $BranchName -replace '[\~,\^,\:,\\,\?,\@\{,\*,\[,\s]{1,}|[.lock|/|\.]*$|^\.{1,}|\.\.', ''
Expand Down