Skip to content

Publish Netbird to Winget #10

Publish Netbird to Winget

Publish Netbird to Winget #10

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
}