WinGet #53
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: WinGet | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| release_tag: | |
| description: "Release tag - eg v1.0-v1.18-r2 (default: latest)" | |
| required: false | |
| type: string | |
| permissions: | |
| contents: write | |
| env: | |
| POWERSHELLYAMLVERSION: 0.4.12 | |
| WINGETPKGS_ID: mlocati.GetText | |
| WINGETPKGS_REPO_UPSTREAM: microsoft/winget-pkgs | |
| WINGETPKGS_REPO_HEAD: master | |
| WINGETPKGS_REPO_FORK: mlocati-forks/winget-pkgs | |
| WINGETPKGS_REPO_FORK_HADEPLOYKEY: ${{ secrets.WINGET_PKGS_FORK_DEPLOYKEY != '' }} | |
| defaults: | |
| run: | |
| shell: pwsh | |
| jobs: | |
| winget: | |
| name: Submit to WinGet | |
| runs-on: windows-2025 | |
| steps: | |
| - | |
| name: Checkout | |
| if: env.WINGETPKGS_REPO_FORK_HADEPLOYKEY == 'true' | |
| uses: actions/checkout@v6 | |
| - | |
| name: Create directory structure | |
| if: env.WINGETPKGS_REPO_FORK_HADEPLOYKEY == 'true' | |
| run: | | |
| New-Item -ItemType Directory -Force -ErrorAction Stop -Path @( | |
| 'downloads' | |
| 'tmp' | |
| ) | Out-Null | |
| - | |
| name: Restore cache | |
| if: env.WINGETPKGS_REPO_FORK_HADEPLOYKEY == 'true' | |
| id: restore-cache | |
| uses: actions/cache/restore@v5 | |
| with: | |
| key: winget-prepare | |
| path: downloads | |
| - | |
| name: Retrieve release data | |
| if: env.WINGETPKGS_REPO_FORK_HADEPLOYKEY == 'true' | |
| id: init | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| $tagName = '${{ inputs.release_tag }}'.Trim() | |
| if ($tagName -eq '') { | |
| $tagName = & gh api 'repos/${{ github.repository }}/releases/latest' --jq '.tag_name' | |
| if (-not($?)) { | |
| throw "Failed to get latest release: $($Error[0])" | |
| } | |
| $tagName = $tagName.Trim() | |
| } | |
| $jsonData = & gh release view --repo=${{ github.repository }} $tagName --json tagName,isDraft,isPrerelease,publishedAt,url,body,assets | |
| if (-not($?)) { | |
| throw "Failed to get release data for tag '$tagName': $($Error[0])" | |
| } | |
| $releaseData = $jsonData | ConvertFrom-Json | |
| if ($releaseData.isDraft) { | |
| Write-Host -Object "Release '$($releaseData.tagName)' is a draft, skipping." | |
| } elseif ($releaseData.isPrerelease) { | |
| Write-Host -Object "Release '$($releaseData.tagName)' is a pre-release, skipping." | |
| } else { | |
| $jsonData | Set-Content -LiteralPath tmp/release.json -Encoding utf8 | |
| 'submit=yes' | Add-Content -Path $env:GITHUB_OUTPUT -Encoding utf8 | |
| } | |
| - | |
| name: Download powershell-yaml module | |
| if: steps.init.outputs.submit == 'yes' | |
| run: > | |
| ./service/download-archive.ps1 | |
| -Url "https://www.powershellgallery.com/api/v2/package/powershell-yaml/${env:POWERSHELLYAMLVERSION}" | |
| -LocalFilePath "downloads\powershell-yaml.${env:POWERSHELLYAMLVERSION}.nupkg" | |
| - | |
| name: Extract powershell-yaml | |
| if: steps.init.outputs.submit == 'yes' | |
| working-directory: tmp | |
| run: Expand-Archive -Path "..\downloads\powershell-yaml.${env:POWERSHELLYAMLVERSION}.nupkg" -DestinationPath .\powershell-yaml | |
| - | |
| name: Prepare winget-pkgs repository | |
| if: steps.init.outputs.submit == 'yes' | |
| run: | | |
| git init tmp/winget-pkgs | |
| git -C tmp/winget-pkgs sparse-checkout init --cone | |
| git -C tmp/winget-pkgs sparse-checkout set "manifests/$($env:WINGETPKGS_ID[0].ToString().ToLower())/$(($env:WINGETPKGS_ID -split '\.')[0])/" | |
| git -C tmp/winget-pkgs remote add upstream "https://github.com/$($env:WINGETPKGS_REPO_UPSTREAM).git" | |
| git -C tmp/winget-pkgs remote add fork "git@github.com:$($env:WINGETPKGS_REPO_FORK).git" | |
| git -C tmp/winget-pkgs fetch --depth=1 upstream $env:WINGETPKGS_REPO_HEAD | |
| git -C tmp/winget-pkgs checkout -b "gettext-$(Get-Date -UFormat %s -Millisecond 0)" upstream/$env:WINGETPKGS_REPO_HEAD | |
| - | |
| name: Create manifest | |
| if: steps.init.outputs.submit == 'yes' | |
| id: create-manifest | |
| run: | | |
| Import-Module -Name .\tmp\powershell-yaml\ -Force | |
| $releaseData = Get-Content -LiteralPath tmp/release.json | ConvertFrom-Json | |
| $manifestPath, $packageVersion, $versionOperation = ./service/create-winget-manifest.ps1 ` -PackageIdentifier $env:WINGETPKGS_ID -ReleaseData $releaseData -ManifestsPath tmp/winget-pkgs/manifests | |
| Write-Host "Manifest created at: $manifestPath" | |
| Get-ChildItem -LiteralPath $manifestPath -Recurse -File | ForEach-Object { | |
| Write-Host "::group::$($_.Name)" | |
| Get-Content -LiteralPath $_.FullName -Raw | Write-Host | |
| Write-Host '::endgroup::' | |
| } | |
| "manifest-path=$manifestPath" | Add-Content -Path $env:GITHUB_OUTPUT -Encoding utf8 | |
| "package-version=$packageVersion" | Add-Content -Path $env:GITHUB_OUTPUT -Encoding utf8 | |
| "version-operation=$versionOperation" | Add-Content -Path $env:GITHUB_OUTPUT -Encoding utf8 | |
| - | |
| name: Validate manifest | |
| if: steps.init.outputs.submit == 'yes' | |
| # We need --ignore-warnings because winget validate doesn't yet support the new 1.12.0 manifest version: we have these warnings: | |
| # Manifest validation succeeded with warnings. | |
| # Manifest Warning: The schema header URL does not match the expected pattern. Value: # yaml-language-server: $schema=https://aka.ms/winget-manifest.installer.1.12.0.schema.json Line: 1, Column: 25 File: mlocati.GetText.installer.yaml | |
| run: winget validate --manifest '${{ steps.create-manifest.outputs.manifest-path }}' --ignore-warnings --disable-interactivity | |
| - | |
| name: Test installing with winget | |
| if: steps.init.outputs.submit == 'yes' | |
| run: | | |
| winget settings --enable LocalManifestFiles | |
| winget install --disable-interactivity --accept-package-agreements --accept-source-agreements --manifest '${{ steps.create-manifest.outputs.manifest-path }}' | |
| - | |
| name: Check changes | |
| id: check-changes | |
| if: steps.init.outputs.submit == 'yes' | |
| working-directory: tmp/winget-pkgs | |
| run: | | |
| $status = git status --porcelain "manifests/$($env:WINGETPKGS_ID[0].ToString().ToLower())/$(($env:WINGETPKGS_ID -split '\.')[0])/" | |
| if (-not $status) { | |
| Write-Host 'No changes to commit.' | |
| } else { | |
| Write-Host 'Changes detected, will commit and push to fork.' | |
| 'commit=yes' | Add-Content -Path $env:GITHUB_OUTPUT -Encoding utf8 | |
| } | |
| - | |
| name: Save deploy key | |
| if: steps.check-changes.outputs.commit == 'yes' | |
| run: | | |
| $sshDir = "$env:USERPROFILE\.ssh" | |
| $keyPath = "$sshDir\id_ed25519" | |
| $privateKey = "${{ secrets.WINGET_PKGS_FORK_DEPLOYKEY }}" -replace "`r`n","`n" | |
| New-Item -ItemType Directory -Force -Path $sshDir | Out-Null | |
| Set-Content -Path $keyPath -Value $privateKey -Encoding utf8NoBOM -NoNewline | |
| icacls $keyPath /inheritance:r /grant:r "$($env:USERNAME):(R)" | |
| ssh-keygen -l -f $keyPath | |
| - | |
| name: Push changes to winget-pkgs fork | |
| if: steps.check-changes.outputs.commit == 'yes' | |
| working-directory: tmp/winget-pkgs | |
| run: | | |
| $env:GIT_SSH_COMMAND = 'ssh -o StrictHostKeyChecking=no' | |
| git config user.name 'GitHub Actions' | |
| git config user.email 'actions@github.com' | |
| $branchName = & git rev-parse --abbrev-ref HEAD | |
| if (-not($?)) { | |
| throw "Failed to get current branch name: $($Error[0])" | |
| } | |
| git add -A "manifests/$($env:WINGETPKGS_ID[0].ToString().ToLower())/$(($env:WINGETPKGS_ID -split '\.')[0])/" | |
| if (-not($?)) { | |
| throw "Failed to stage changes: $($Error[0])" | |
| } | |
| switch ('${{ steps.create-manifest.outputs.version-operation }}') { | |
| 'updated' { | |
| $commitSubject = "Update version: $($env:WINGETPKGS_ID) version ${{ steps.create-manifest.outputs.package-version }}" | |
| } | |
| 'created' { | |
| $commitSubject = "New version: $($env:WINGETPKGS_ID) version ${{ steps.create-manifest.outputs.package-version }}" | |
| } | |
| default { | |
| throw 'Unknown version operation: ${{ steps.create-manifest.outputs.version-operation }}' | |
| } | |
| } | |
| git commit -m $commitSubject -m "Commit created by GitHub Action https://github.com/$($env:GITHUB_REPOSITORY)/actions/runs/$($env:GITHUB_RUN_ID)" | |
| if (-not($?)) { | |
| throw "Failed to commit changes: $($Error[0])" | |
| } | |
| $commitHash = git rev-parse HEAD | |
| if (-not($?)) { | |
| throw "Failed to get commit hash: $($Error[0])" | |
| } | |
| git push fork $branchName | |
| if (-not($?)) { | |
| throw "Failed to push changes to fork: $($Error[0])" | |
| } | |
| @" | |
| ### Changes pushed to fork $($env:WINGETPKGS_REPO_FORK) | |
| Branch created: | |
| $branchName | |
| Commit hash: | |
| $commitHash | |
| View changes in fork: | |
| https://github.com/$($env:WINGETPKGS_REPO_FORK)/commits/$branchName | |
| Open pull request: | |
| https://github.com/$($env:WINGETPKGS_REPO_UPSTREAM)/compare/$($env:WINGETPKGS_REPO_HEAD)...$($env:WINGETPKGS_REPO_FORK -replace '/',':'):$($branchName)?expand=1 | |
| "@ | Add-Content -Path $env:GITHUB_STEP_SUMMARY -Encoding utf8 | |
| - | |
| name: Persist cache | |
| if: always() && steps.restore-cache.outputs.cache-hit != 'true' | |
| uses: actions/cache/save@v5 | |
| with: | |
| key: winget-prepare | |
| path: downloads |