Publish Netbird to Winget #10
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 | |
| # --- PAT-owner-based fork handling + 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: | | |
| # Make PAT available to gh | |
| echo "GH_TOKEN=$env:WINGET_PAT" >> $env:GITHUB_ENV | |
| # Use REST to get the PAT owner's login (works for classic & fine-grained PATs) | |
| $user = Invoke-RestMethod -Headers @{ Authorization = "Bearer $env:WINGET_PAT"; "User-Agent"="netbird-winget-action"; Accept="application/vnd.github+json" } -Uri "https://api.github.com/user" | |
| if (-not $user.login) { throw "Could not determine PAT owner via /user" } | |
| "FORK_OWNER=$($user.login)" >> $env:GITHUB_ENV | |
| "login=$($user.login)" >> $env:GITHUB_OUTPUT | |
| - name: Ensure fork exists under PAT owner (create if missing) | |
| shell: pwsh | |
| env: | |
| GH_TOKEN: ${{ env.GH_TOKEN }} | |
| run: | | |
| $fork = "${{ env.FORK_OWNER }}/winget-pkgs" | |
| Write-Host "Checking for fork $fork ..." | |
| $exists = $false | |
| try { | |
| gh repo view $fork --json name -q .name | Out-Null | |
| $exists = $LASTEXITCODE -eq 0 | |
| } catch { $exists = $false } | |
| if (-not $exists) { | |
| Write-Host "Fork not found; creating under ${{ env.FORK_OWNER }} ..." | |
| # Create the fork via REST (equivalent to: POST /repos/microsoft/winget-pkgs/forks) | |
| gh api --method POST -H "Accept: application/vnd.github+json" /repos/microsoft/winget-pkgs/forks -f default_branch_only=true | |
| } 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 | |
| # --- end fork handling --- | |
| - 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 | |
| } |