From 91e50ad243e5d7eca85c64ee7d2974f369269e74 Mon Sep 17 00:00:00 2001 From: Johannes Passing Date: Thu, 17 Oct 2024 13:13:59 +1100 Subject: [PATCH 1/5] Add script to generate manifests --- sources/scripts/create-winget-manifest.ps1 | 235 +++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 sources/scripts/create-winget-manifest.ps1 diff --git a/sources/scripts/create-winget-manifest.ps1 b/sources/scripts/create-winget-manifest.ps1 new file mode 100644 index 000000000..410fd07cb --- /dev/null +++ b/sources/scripts/create-winget-manifest.ps1 @@ -0,0 +1,235 @@ +# +# Copyright 2024 Google LLC +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +# +# Create WinGet manifests for a GitHub release. +# + +[CmdletBinding()] +Param( + [Parameter(Mandatory=$False)][string]$ReleaseUrl = "https://api.github.com/repos/GoogleCloudPlatform/iap-desktop/releases/latest", + + [ValidateSet('Version','DefaultLocale','Installer')] + [string]$ManifestType = "Version" +) + +$ErrorActionPreference = "stop" +$GithubRepository = "GoogleCloudPlatform/iap-desktop" + +# +# Return all entries of an MSI's Property table. +# +function Get-MsiProperties { + Param( + [Parameter(Mandatory=$True)][string]$Package + ) + + $Installer = New-Object -ComObject WindowsInstaller.Installer + try { + $PackageDatabase = $Installer.OpenDatabase($Package, 0) + $View = $PackageDatabase.OpenView('SELECT `Property`, `Value` FROM `Property`') + $View.Execute() + $Record = $view.Fetch() + + $Properties = @{} + while ($Record -ne $null) { + $Properties.Add($Record.StringData(1), $Record.StringData(2)) + $Record = $View.Fetch() + } + + $View.Close() + + return $Properties + } + catch { + throw "The file does not exist or is not a valid MSI database: " + $_.Exception; + } +} + +# +# Get architecture of an MSI package, which is encoded in +# the Template summary property, see +# https://learn.microsoft.com/en-au/windows/win32/msi/template-summary +# +function Get-MsiArchitecture { + Param( + [Parameter(Mandatory=$True)][string]$Package + ) + + # Map to architecture IDs as use bt WinGet. + $Architectures = @{ + "Intel" = "x86" + "x64" = "x64" + "arm64" = "arm64" + } + + # Open MSI database to query metadata. + $Installer = New-Object -ComObject WindowsInstaller.Installer + try { + $SummaryInfo = $Installer.SummaryInformation($Package) + + $Architecture = ($SummaryInfo.Property(7) -split ";")[0] + return $Architectures[$Architecture] + } + catch { + throw "The file does not exist or is not a valid MSI database: " + $_.Exception; + } +} + +# +# Get release metadata from GitHub. +# +$Release = Invoke-RestMethod -Uri $ReleaseUrl +if (-not $Release.id) { + throw "The URL does not refer to a GitHub release" +} + + +# +# Extract relevant assets. +# +$MsiAssets = $Release.assets.Where{$_.browser_download_url -match 'iapdesktop(.+)\.msi'} +if (!$MsiAssets) { + throw "The release does not contain any matching MSI packages" +} + +# +# Download MSI files to temp folder. +# +$MsiFiles = @{} +foreach ($MsiAsset in $MsiAssets) { + $LocalFile = "$($env:Temp)\$($MsiAsset.id)_$($MsiAsset.name)" + if (!(Test-Path $LocalFile)) { + Write-Host "Downloading $($MsiAsset.name) to $LocalFile..." -ForegroundColor Yellow + + Start-BitsTransfer ` + -Source $MsiAsset.browser_download_url ` + -Destination $LocalFile + + } + + $MsiFiles[$MsiAsset.id] = $LocalFile +} + +# +# Generate the requested type of manifest. +# +$SharedProperties = Get-MsiProperties $MsiFiles[$MsiAssets[0].id] + +if ($ManifestType -eq "Version") { + # + # Version manifest. + # + + @" +ManifestType: "version" +ManifestVersion: 1.9.0 +PackageIdentifier: Google.IAPDesktop +PackageVersion: '$($SharedProperties.ProductVersion)' + +DefaultLocale: "en-US" +"@ +} + +elseif ($ManifestType -eq "DefaultLocale") { + # + # Manifest for default locale. + # + + @" +ManifestType: "defaultLocale" +ManifestVersion: 1.9.0 +PackageIdentifier: Google.IAPDesktop +PackageVersion: '$($SharedProperties.ProductVersion)' + +PackageName: IAP Desktop +DefaultLocale: "en-US" +Author: GoogleCloudPlatform +Publisher: Google LLC +PublisherUrl: https://github.com/$GithubRepository +PublisherSupportUrl: https://github.com/$GithubRepository/issues + +License: Apache License 2.0 +LicenseUrl: https://raw.githubusercontent.com/$GithubRepository/master/LICENSE.txt + +Copyright: Copyright 2024 Google, Inc. +CopyrightUrl: https://raw.githubusercontent.com/$GithubRepository/master/LICENSE.txt +ShortDescription: IAP Desktop is an open-source Remote Desktop and SSH client that lets you connect to your Google Cloud VM instances from anywhere. +Moniker: iap-desktop +Tags: +- google-cloud +- iap +- ssh +- rdp +- windows +ReleaseNotesUrl: https://github.com/$GithubRepository/releases/tag/$($Release.tag_name) +"@ +} + +elseif ($ManifestType -eq "Installer") { + # + # Installer manifest. + # + +$Manifest = @" +ManifestType: installer +ManifestVersion: 1.9.0 +PackageIdentifier: Google.IAPDesktop +PackageVersion: '$($SharedProperties.ProductVersion)' + +Platform: +- Windows.Desktop +InstallerLocale: en-US +InstallerType: wix +Scope: user +InstallModes: +- interactive +- silent +- silentWithProgress +UpgradeBehavior: install +ReleaseDate: $($Release.published_at) +AppsAndFeaturesEntries: +- UpgradeCode: '$($SharedProperties.UpgradeCode)' +Installers: +"@ + +foreach ($MsiAsset in $MsiAssets) { + $MsiFile = $MsiFiles[$MsiAsset.id] + + $Architecture = Get-MsiArchitecture $MsiFile + $Properties = Get-MsiProperties $MsiFile + $Hash = Get-FileHash -Algorithm SHA256 $MsiFile + + $Manifest += @" + +- Architecture: $($Architecture) + ProductCode: '$($Properties.ProductCode)' + InstallerUrl: $($MsiAsset.browser_download_url) + InstallerSha256: $($Hash.Hash) +"@ +} + +$Manifest +} + +else { + throw "The manifest type is not supported" +} From 6d8db6050337ef37a3f189a1428b60ca087e629a Mon Sep 17 00:00:00 2001 From: Johannes Passing Date: Thu, 17 Oct 2024 13:28:49 +1100 Subject: [PATCH 2/5] Add makefile target --- doc/site/.gitignore | 1 + doc/site/makefile | 21 +++++++++++++++++++++ sources/scripts/create-winget-manifest.ps1 | 2 +- 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/doc/site/.gitignore b/doc/site/.gitignore index 93ac04d94..f836ec630 100644 --- a/doc/site/.gitignore +++ b/doc/site/.gitignore @@ -20,4 +20,5 @@ # public/ +winget/ release-notes.md \ No newline at end of file diff --git a/doc/site/makefile b/doc/site/makefile index d5be39b55..5e4417899 100644 --- a/doc/site/makefile +++ b/doc/site/makefile @@ -19,6 +19,10 @@ # under the License. # +#------------------------------------------------------------------------------ +# mkdocs targets +#------------------------------------------------------------------------------ + serve: release-notes @echo "========================================================" @echo "=== Serving site ===" @@ -40,3 +44,20 @@ install: @echo "========================================================" python -m pip install mkdocs-material + +#------------------------------------------------------------------------------ +# WinGet targets +#------------------------------------------------------------------------------ + +POWERSHELL = powershell -NoProfile -ExecutionPolicy Unrestricted +CREATE_MANIFEST = $(POWERSHELL) $(MAKEDIR)\..\..\sources\scripts\create-winget-manifest.ps1 + +winget-manifests: + if not exist $(MAKEDIR)\winget \ + md $(MAKEDIR)\winget + + $(CREATE_MANIFEST) -ManifestType Version > $(MAKEDIR)\winget\IAPDesktop.yaml + $(CREATE_MANIFEST) -ManifestType DefaultLocale > $(MAKEDIR)\winget\IAPDesktop.locale.en-US.yaml + $(CREATE_MANIFEST) -ManifestType Installer > $(MAKEDIR)\winget\IAPDesktop.installer.yaml + + winget validate --manifest $(MAKEDIR)\winget diff --git a/sources/scripts/create-winget-manifest.ps1 b/sources/scripts/create-winget-manifest.ps1 index 410fd07cb..76bbb9b86 100644 --- a/sources/scripts/create-winget-manifest.ps1 +++ b/sources/scripts/create-winget-manifest.ps1 @@ -159,9 +159,9 @@ ManifestType: "defaultLocale" ManifestVersion: 1.9.0 PackageIdentifier: Google.IAPDesktop PackageVersion: '$($SharedProperties.ProductVersion)' +PackageLocale: en-US PackageName: IAP Desktop -DefaultLocale: "en-US" Author: GoogleCloudPlatform Publisher: Google LLC PublisherUrl: https://github.com/$GithubRepository From ce39dadc9610a05653a50512689e6887120befd0 Mon Sep 17 00:00:00 2001 From: Johannes Passing Date: Thu, 17 Oct 2024 13:33:38 +1100 Subject: [PATCH 3/5] Move to separate folder --- doc/site/.gitignore | 1 - doc/site/makefile | 21 --------------------- doc/winget/.gitignore | 22 ++++++++++++++++++++++ doc/winget/makefile | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 55 insertions(+), 22 deletions(-) create mode 100644 doc/winget/.gitignore create mode 100644 doc/winget/makefile diff --git a/doc/site/.gitignore b/doc/site/.gitignore index f836ec630..93ac04d94 100644 --- a/doc/site/.gitignore +++ b/doc/site/.gitignore @@ -20,5 +20,4 @@ # public/ -winget/ release-notes.md \ No newline at end of file diff --git a/doc/site/makefile b/doc/site/makefile index 5e4417899..d5be39b55 100644 --- a/doc/site/makefile +++ b/doc/site/makefile @@ -19,10 +19,6 @@ # under the License. # -#------------------------------------------------------------------------------ -# mkdocs targets -#------------------------------------------------------------------------------ - serve: release-notes @echo "========================================================" @echo "=== Serving site ===" @@ -44,20 +40,3 @@ install: @echo "========================================================" python -m pip install mkdocs-material - -#------------------------------------------------------------------------------ -# WinGet targets -#------------------------------------------------------------------------------ - -POWERSHELL = powershell -NoProfile -ExecutionPolicy Unrestricted -CREATE_MANIFEST = $(POWERSHELL) $(MAKEDIR)\..\..\sources\scripts\create-winget-manifest.ps1 - -winget-manifests: - if not exist $(MAKEDIR)\winget \ - md $(MAKEDIR)\winget - - $(CREATE_MANIFEST) -ManifestType Version > $(MAKEDIR)\winget\IAPDesktop.yaml - $(CREATE_MANIFEST) -ManifestType DefaultLocale > $(MAKEDIR)\winget\IAPDesktop.locale.en-US.yaml - $(CREATE_MANIFEST) -ManifestType Installer > $(MAKEDIR)\winget\IAPDesktop.installer.yaml - - winget validate --manifest $(MAKEDIR)\winget diff --git a/doc/winget/.gitignore b/doc/winget/.gitignore new file mode 100644 index 000000000..619150435 --- /dev/null +++ b/doc/winget/.gitignore @@ -0,0 +1,22 @@ +# +# Copyright 2023 Google LLC +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +public/ \ No newline at end of file diff --git a/doc/winget/makefile b/doc/winget/makefile new file mode 100644 index 000000000..4f06afdeb --- /dev/null +++ b/doc/winget/makefile @@ -0,0 +1,33 @@ +# +# Copyright 2023 Google LLC +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +POWERSHELL = powershell -NoProfile -ExecutionPolicy Unrestricted +CREATE_MANIFEST = $(POWERSHELL) $(MAKEDIR)\..\..\sources\scripts\create-winget-manifest.ps1 + +winget-manifests: + if not exist $(MAKEDIR)\public \ + md $(MAKEDIR)\public + + $(CREATE_MANIFEST) -ManifestType Version > $(MAKEDIR)\public\IAPDesktop.yaml + $(CREATE_MANIFEST) -ManifestType DefaultLocale > $(MAKEDIR)\public\IAPDesktop.locale.en-US.yaml + $(CREATE_MANIFEST) -ManifestType Installer > $(MAKEDIR)\public\IAPDesktop.installer.yaml + + winget validate --manifest $(MAKEDIR)\public From 4aab7aa915641c25d7ec1c17e376b6836dd4a17d Mon Sep 17 00:00:00 2001 From: Johannes Passing Date: Thu, 17 Oct 2024 14:38:56 +1100 Subject: [PATCH 4/5] Cleanup --- doc/winget/makefile | 25 +++++++++++++++++----- sources/scripts/create-winget-manifest.ps1 | 16 ++++++++------ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/doc/winget/makefile b/doc/winget/makefile index 4f06afdeb..1d4e02a55 100644 --- a/doc/winget/makefile +++ b/doc/winget/makefile @@ -22,12 +22,27 @@ POWERSHELL = powershell -NoProfile -ExecutionPolicy Unrestricted CREATE_MANIFEST = $(POWERSHELL) $(MAKEDIR)\..\..\sources\scripts\create-winget-manifest.ps1 -winget-manifests: +default: winget-manifests clone-repo + +public-folder: if not exist $(MAKEDIR)\public \ md $(MAKEDIR)\public - $(CREATE_MANIFEST) -ManifestType Version > $(MAKEDIR)\public\IAPDesktop.yaml - $(CREATE_MANIFEST) -ManifestType DefaultLocale > $(MAKEDIR)\public\IAPDesktop.locale.en-US.yaml - $(CREATE_MANIFEST) -ManifestType Installer > $(MAKEDIR)\public\IAPDesktop.installer.yaml +winget-manifests: public-folder + if not exist $(MAKEDIR)\public\manifest \ + md $(MAKEDIR)\public\manifest + + $(CREATE_MANIFEST) -ManifestType Version > $(MAKEDIR)\public\manifest\IAPDesktop.yaml + $(CREATE_MANIFEST) -ManifestType DefaultLocale > $(MAKEDIR)\public\manifest\IAPDesktop.locale.en-US.yaml + $(CREATE_MANIFEST) -ManifestType Installer > $(MAKEDIR)\public\manifest\IAPDesktop.installer.yaml + + winget validate --manifest $(MAKEDIR)\public\manifest + +clone-repo: public-folder + if not exist $(MAKEDIR)\public\winget-pkgs \ + git clone --depth 1 https://github.com/microsoft/winget-pkgs.git $(MAKEDIR)\public\winget-pkgs - winget validate --manifest $(MAKEDIR)\public + cd $(MAKEDIR)\public\winget-pkgs + git fetch + git checkout origin/master + cd $(MAKEDIR) \ No newline at end of file diff --git a/sources/scripts/create-winget-manifest.ps1 b/sources/scripts/create-winget-manifest.ps1 index 76bbb9b86..54b576b22 100644 --- a/sources/scripts/create-winget-manifest.ps1 +++ b/sources/scripts/create-winget-manifest.ps1 @@ -27,6 +27,7 @@ Param( [Parameter(Mandatory=$False)][string]$ReleaseUrl = "https://api.github.com/repos/GoogleCloudPlatform/iap-desktop/releases/latest", + [Parameter(Mandatory=$False)] [ValidateSet('Version','DefaultLocale','Installer')] [string]$ManifestType = "Version" ) @@ -139,7 +140,7 @@ if ($ManifestType -eq "Version") { # Version manifest. # - @" + $Manifest = @" ManifestType: "version" ManifestVersion: 1.9.0 PackageIdentifier: Google.IAPDesktop @@ -154,7 +155,7 @@ elseif ($ManifestType -eq "DefaultLocale") { # Manifest for default locale. # - @" + $Manifest = @" ManifestType: "defaultLocale" ManifestVersion: 1.9.0 PackageIdentifier: Google.IAPDesktop @@ -211,7 +212,7 @@ AppsAndFeaturesEntries: Installers: "@ -foreach ($MsiAsset in $MsiAssets) { + foreach ($MsiAsset in $MsiAssets) { $MsiFile = $MsiFiles[$MsiAsset.id] $Architecture = Get-MsiArchitecture $MsiFile @@ -225,11 +226,14 @@ foreach ($MsiAsset in $MsiAssets) { InstallerUrl: $($MsiAsset.browser_download_url) InstallerSha256: $($Hash.Hash) "@ -} - -$Manifest + } } else { throw "The manifest type is not supported" } + +# +# Write to stdout. +# +$Manifest \ No newline at end of file From 4445ed309d8aa758eaf64810a23b50267c19d64d Mon Sep 17 00:00:00 2001 From: Johannes Passing Date: Thu, 17 Oct 2024 15:48:03 +1100 Subject: [PATCH 5/5] Set manifest version to 1.6 --- sources/scripts/create-winget-manifest.ps1 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sources/scripts/create-winget-manifest.ps1 b/sources/scripts/create-winget-manifest.ps1 index 54b576b22..91ff4f98e 100644 --- a/sources/scripts/create-winget-manifest.ps1 +++ b/sources/scripts/create-winget-manifest.ps1 @@ -142,7 +142,7 @@ if ($ManifestType -eq "Version") { $Manifest = @" ManifestType: "version" -ManifestVersion: 1.9.0 +ManifestVersion: 1.6.0 PackageIdentifier: Google.IAPDesktop PackageVersion: '$($SharedProperties.ProductVersion)' @@ -157,7 +157,7 @@ elseif ($ManifestType -eq "DefaultLocale") { $Manifest = @" ManifestType: "defaultLocale" -ManifestVersion: 1.9.0 +ManifestVersion: 1.6.0 PackageIdentifier: Google.IAPDesktop PackageVersion: '$($SharedProperties.ProductVersion)' PackageLocale: en-US @@ -192,7 +192,7 @@ elseif ($ManifestType -eq "Installer") { $Manifest = @" ManifestType: installer -ManifestVersion: 1.9.0 +ManifestVersion: 1.6.0 PackageIdentifier: Google.IAPDesktop PackageVersion: '$($SharedProperties.ProductVersion)'