Publish Netbird to Winget #11
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: Publish Netbird to Winget | |
| on: | |
| release: | |
| types: [published] | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Netbird version to publish (e.g., 0.59.9)' | |
| required: true | |
| type: string | |
| jobs: | |
| publish-winget: | |
| runs-on: windows-latest | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| - name: Set up WingetCreate | |
| shell: pwsh | |
| run: Invoke-WebRequest https://aka.ms/wingetcreate/latest -OutFile wingetcreate.exe | |
| - name: Determine version | |
| id: version | |
| shell: pwsh | |
| run: | | |
| if ("${{ github.event_name }}" -eq "workflow_dispatch") { | |
| $version = "${{ github.event.inputs.version }}" | |
| } else { | |
| $version = "${{ github.event.release.tag_name }}".TrimStart('v') | |
| } | |
| "VERSION=$version" >> $env:GITHUB_ENV | |
| "version=$version" >> $env:GITHUB_OUTPUT | |
| - name: Fetch release info & collect installer URLs | |
| id: release_info | |
| shell: pwsh | |
| env: | |
| GH_API: https://api.github.com | |
| WINGET_PAT: ${{ secrets.WINGET_PAT }} | |
| run: | | |
| $ErrorActionPreference = 'Stop' | |
| $headers = @{ | |
| Authorization = "Bearer $env:WINGET_PAT" | |
| "User-Agent" = "netbird-winget-action" | |
| Accept = "application/vnd.github+json" | |
| "X-GitHub-Api-Version" = "2022-11-28" | |
| } | |
| if ("${{ github.event_name }}" -eq "workflow_dispatch") { | |
| $release = Invoke-RestMethod -Headers $headers -Uri "$env:GH_API/repos/netbirdio/netbird/releases/tags/v${{ env.VERSION }}" | |
| } else { | |
| $release = Invoke-RestMethod -Headers $headers -Uri "${{ github.event.release.url }}" | |
| } | |
| $assets = $release.assets | |
| if (-not $assets) { throw "Release v${{ env.VERSION }} has no assets." } | |
| $msi_x64 = $assets | Where-Object { $_.name -like "*windows_amd64.msi" } | Select-Object -ExpandProperty browser_download_url -First 1 | |
| $exe_x64 = $assets | Where-Object { $_.name -like "*windows_amd64.exe" } | Select-Object -ExpandProperty browser_download_url -First 1 | |
| $msi_arm = $assets | Where-Object { $_.name -like "*windows_arm64.msi" } | Select-Object -ExpandProperty browser_download_url -First 1 | |
| $exe_arm = $assets | Where-Object { $_.name -like "*windows_arm64.exe" } | Select-Object -ExpandProperty browser_download_url -First 1 | |
| $any = @($msi_x64, $exe_x64, $msi_arm, $exe_arm) | Where-Object { $_ } | |
| if (-not $any) { throw "No Windows installers (MSI/EXE) found in v${{ env.VERSION }}." } | |
| $qualified = @() | |
| if ($msi_x64) { $qualified += "$msi_x64|x64" } | |
| if ($exe_x64) { $qualified += "$exe_x64|x64" } | |
| if ($msi_arm) { $qualified += "$msi_arm|arm64" } | |
| if ($exe_arm) { $qualified += "$exe_arm|arm64" } | |
| Set-Content -Path installer_urls.txt -Value ($qualified -join "`n") | |
| "installer_urls_file=installer_urls.txt" >> $env:GITHUB_OUTPUT | |
| "installer_url=$($any[0])" >> $env:GITHUB_OUTPUT | |
| # ---------- Fork under PAT owner, then sync ---------- | |
| - name: Install GitHub CLI | |
| shell: pwsh | |
| run: choco install gh -y | |
| - name: Authenticate gh with PAT and resolve PAT owner | |
| id: whoami | |
| shell: pwsh | |
| env: | |
| WINGET_PAT: ${{ secrets.WINGET_PAT }} | |
| run: | | |
| echo "GH_TOKEN=$env:WINGET_PAT" >> $env:GITHUB_ENV | |
| $u = gh api /user --jq "{login: .login, type: .type}" | |
| if (-not $u) { throw "Could not determine PAT owner via /user" } | |
| $obj = $u | ConvertFrom-Json | |
| "FORK_OWNER=$($obj.login)" >> $env:GITHUB_ENV | |
| "FORK_OWNER_TYPE=$($obj.type)" >> $env:GITHUB_ENV | |
| Write-Host "PAT owner: $($obj.login) ($($obj.type))" | |
| - name: Ensure fork exists (create if missing) under PAT owner | |
| shell: pwsh | |
| env: | |
| GH_TOKEN: ${{ env.GH_TOKEN }} | |
| run: | | |
| $owner = "${{ env.FORK_OWNER }}" | |
| $forkSlug = "$owner/winget-pkgs" | |
| Write-Host "Checking for fork $forkSlug ..." | |
| $exists = $false | |
| try { | |
| gh repo view $forkSlug --json name -q .name | Out-Null | |
| if ($LASTEXITCODE -eq 0) { $exists = $true } | |
| } catch { $exists = $false } | |
| if (-not $exists) { | |
| Write-Host "Fork not found; creating under $owner ..." | |
| # POST /repos/{owner}/{repo}/forks; add organization=... if PAT owner is an Organization | |
| if ("${{ env.FORK_OWNER_TYPE }}" -eq "Organization") { | |
| gh api --method POST -H "Accept: application/vnd.github+json" /repos/microsoft/winget-pkgs/forks -f organization="$owner" -F default_branch_only=true | |
| } else { | |
| gh api --method POST -H "Accept: application/vnd.github+json" /repos/microsoft/winget-pkgs/forks -F default_branch_only=true | |
| } | |
| # Forking is async: poll until the repo appears (max ~90s) | |
| $deadline = (Get-Date).AddSeconds(90) | |
| do { | |
| Start-Sleep -Seconds 3 | |
| try { | |
| gh repo view $forkSlug --json defaultBranchRef -q .defaultBranchRef.name | Out-Null | |
| if ($LASTEXITCODE -eq 0) { $exists = $true } | |
| } catch { $exists = $false } | |
| } until ($exists -or (Get-Date) -gt $deadline) | |
| if (-not $exists) { throw "Fork creation did not complete in time for $forkSlug." } | |
| } else { | |
| Write-Host "Fork already exists." | |
| } | |
| - name: Sync PAT-owner fork with upstream (master) | |
| shell: pwsh | |
| env: | |
| GH_TOKEN: ${{ env.GH_TOKEN }} | |
| run: gh repo sync "${{ env.FORK_OWNER }}/winget-pkgs" -b master --force | |
| # ---------- Submit with wingetcreate ---------- | |
| - name: Update Winget Manifest | |
| shell: pwsh | |
| env: | |
| WINGET_PAT: ${{ secrets.WINGET_PAT }} | |
| run: | | |
| Write-Host "Updating Winget manifest for Netbird ${{ env.VERSION }}" | |
| $urls = Get-Content "${{ steps.release_info.outputs.installer_urls_file }}" | Where-Object { $_.Trim() } | |
| if (-not $urls) { throw "No installer URLs to submit." } | |
| .\wingetcreate.exe update Netbird.Netbird ` | |
| --version $env:VERSION ` | |
| --display-version $env:VERSION ` | |
| --urls $urls ` | |
| --submit ` | |
| --token $env:WINGET_PAT | |
| - name: Verify submission | |
| shell: pwsh | |
| run: | | |
| if ($LASTEXITCODE -eq 0) { | |
| Write-Host "✅ Successfully submitted Winget manifest update for Netbird ${{ env.VERSION }}" | |
| } else { | |
| Write-Error "❌ Failed to submit Winget manifest update" | |
| exit 1 | |
| } |