Skip to content
Merged
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
29 changes: 27 additions & 2 deletions .github/workflows/winget.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
name: Prepare winTerm WinGet manifests

on:
pull_request:
paths:
- '.github/workflows/winget.yml'
- 'scripts/winterm/generate-winget-manifests.ps1'
- 'scripts/winterm/test-release-workflow.ps1'
release:
types:
- published
Expand All @@ -12,7 +17,7 @@ permissions:
jobs:
validate:
name: Generate and validate public-release manifests
if: github.event_name == 'workflow_dispatch' || github.event.release.tag_name == 'v1.0.2'
if: github.event_name == 'pull_request' || github.event_name == 'workflow_dispatch' || github.event.release.tag_name == 'v1.0.2'
runs-on: windows-2022
timeout-minutes: 20
steps:
Expand Down Expand Up @@ -49,10 +54,30 @@ jobs:
-InstallerSha256 $sha `
-OutputDirectory 'packaging\winget\1.0.2'

- name: Install the pinned WinGet manifest validator
shell: pwsh
env:
GH_TOKEN: ${{ github.token }}
run: |
Install-Module `
-Name Microsoft.WinGet.Client `
-RequiredVersion '1.29.280' `
-Repository PSGallery `
-Scope CurrentUser `
-Force
Import-Module Microsoft.WinGet.Client -RequiredVersion '1.29.280' -Force
Repair-WinGetPackageManager -Version 'v1.29.280' -AllUsers -Force

$winget = Get-Command winget.exe -ErrorAction Stop
& $winget.Source --version
if ($LASTEXITCODE -ne 0) {
throw 'The pinned WinGet manifest validator is not executable.'
}

- name: Validate WinGet manifests
shell: pwsh
run: |
winget validate 'packaging\winget\1.0.2'
winget validate --manifest 'packaging\winget\1.0.2' --disable-interactivity
if ($LASTEXITCODE -ne 0) {
throw 'winget validate failed.'
}
Expand Down
31 changes: 27 additions & 4 deletions scripts/winterm/test-release-workflow.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ try
{
$workflowPath = Join-Path $repositoryRoot '.github\workflows\release.yml'
$workflow = Get-Content -LiteralPath $workflowPath -Raw
$wingetWorkflowPath = Join-Path $repositoryRoot '.github\workflows\winget.yml'
$wingetWorkflow = Get-Content -LiteralPath $wingetWorkflowPath -Raw
$wingetGeneratorPath = Join-Path $repositoryRoot 'scripts\winterm\generate-winget-manifests.ps1'
$wingetGenerator = Get-Content -LiteralPath $wingetGeneratorPath -Raw

Expand Down Expand Up @@ -53,13 +55,16 @@ try
throw 'Release workflow contains a forbidden trigger, permission, or asset replacement option.'
}

foreach ($line in $workflow -split "`r?`n")
foreach ($workflowToInspect in @($workflow, $wingetWorkflow))
{
if ($line -match '^\s*uses:\s*(?<action>[^@\s]+)@(?<reference>[^\s#]+)')
foreach ($line in $workflowToInspect -split "`r?`n")
{
if ($Matches.reference -notmatch '^[0-9a-f]{40}$')
if ($line -match '^\s*uses:\s*(?<action>[^@\s]+)@(?<reference>[^\s#]+)')
{
throw "GitHub Action '$($Matches.action)' is not pinned to an immutable commit SHA."
if ($Matches.reference -notmatch '^[0-9a-f]{40}$')
{
throw "GitHub Action '$($Matches.action)' is not pinned to an immutable commit SHA."
}
}
}
}
Expand All @@ -76,6 +81,24 @@ try
throw 'WinGet manifest generation does not accept only the current v1.0.2 public installer URL.'
}

foreach ($required in @(
'pull_request:',
'Microsoft.WinGet.Client',
"-RequiredVersion '1.29.280'",
"Repair-WinGetPackageManager -Version 'v1.29.280' -AllUsers -Force",
"winget validate --manifest 'packaging\winget\1.0.2' --disable-interactivity"
))
{
if (-not $wingetWorkflow.Contains($required))
{
throw "WinGet workflow is missing required validator boundary '$required'."
}
}
if ($wingetWorkflow.Contains('Repair-WinGetPackageManager -Latest'))
{
throw 'WinGet workflow must pin the manifest validator instead of installing the latest version.'
}

Write-Host 'PASS: stable release workflow security and publication boundaries.' -ForegroundColor Green
}
catch
Expand Down