# McpMux Release Setup Script
#
# This script helps set up the release signing infrastructure.
# Run once to generate signing keys for Tauri auto-updater.
#
# Usage:
# .\setup-release.ps1 # Generate new Tauri updater signing key
# .\setup-release.ps1 -ShowPubkey # Show public key for tauri.conf.json
# .\setup-release.ps1 -SetupHomebrew # Set up Homebrew tap token in GitHub
# .\setup-release.ps1 -ShowSecrets # Show all required GitHub secrets and their status
param(
[switch]$ShowPubkey,
[switch]$SetupHomebrew,
[switch]$ShowSecrets
)
$keyPath = "$env:USERPROFILE\.tauri\mcpmux.key"
$pubkeyPath = "$env:USERPROFILE\.tauri\mcpmux.key.pub"
$repo = "mcpmux/mcp-mux"
$tapRepo = "mcpmux/homebrew-mcpmux"
# ── Show all secrets status ──────────────────────────────────
if ($ShowSecrets) {
Write-Host ""
Write-Host "McpMux GitHub Secrets Status" -ForegroundColor Cyan
Write-Host "============================" -ForegroundColor Cyan
Write-Host ""
Write-Host "Repository: https://github.com/$repo/settings/secrets/actions" -ForegroundColor Gray
Write-Host ""
# Check which secrets exist via gh CLI
$existingSecrets = @()
try {
$existingSecrets = gh secret list --repo $repo --json name --jq '.[].name' 2>$null | ForEach-Object { $_.Trim() }
} catch {}
$allSecrets = @(
@{ Name = "TAURI_SIGNING_PRIVATE_KEY"; Category = "Updater (required)"; Note = "Generated by: .\setup-release.ps1" }
@{ Name = "TAURI_SIGNING_PRIVATE_KEY_PASSWORD"; Category = "Updater (optional)"; Note = "Password for the signing key" }
@{ Name = "HOMEBREW_TAP_TOKEN"; Category = "Homebrew (required)"; Note = "Generated by: .\setup-release.ps1 -SetupHomebrew" }
@{ Name = "APPLE_SIGNING_IDENTITY"; Category = "macOS (optional)"; Note = "Leave empty for ad-hoc signing (-)" }
@{ Name = "APPLE_CERTIFICATE"; Category = "macOS (optional)"; Note = "Base64 .p12 — only with Apple Developer ID" }
@{ Name = "APPLE_CERTIFICATE_PASSWORD"; Category = "macOS (optional)"; Note = ".p12 password" }
@{ Name = "APPLE_ID"; Category = "macOS notarize (optional)"; Note = "Apple ID email" }
@{ Name = "APPLE_PASSWORD"; Category = "macOS notarize (optional)"; Note = "App-specific password" }
@{ Name = "APPLE_TEAM_ID"; Category = "macOS notarize (optional)"; Note = "10-char team ID" }
@{ Name = "KEYCHAIN_PASSWORD"; Category = "macOS (optional)"; Note = "Temp keychain password for CI" }
)
foreach ($secret in $allSecrets) {
$status = if ($existingSecrets -contains $secret.Name) { "SET" } else { "NOT SET" }
$color = if ($status -eq "SET") { "Green" } else {
if ($secret.Category -match "optional") { "DarkGray" } else { "Yellow" }
}
$icon = if ($status -eq "SET") { "[OK]" } else { "[ ]" }
Write-Host " $icon " -NoNewline -ForegroundColor $color
Write-Host "$($secret.Name)" -NoNewline -ForegroundColor White
Write-Host " — $($secret.Note)" -ForegroundColor DarkGray
}
Write-Host ""
Write-Host "macOS ad-hoc signing:" -ForegroundColor Cyan
Write-Host " No secrets needed! The release workflow defaults to ad-hoc signing (-)" -ForegroundColor Gray
Write-Host " when APPLE_SIGNING_IDENTITY is not set. This is sufficient for" -ForegroundColor Gray
Write-Host " distribution via Homebrew tap (postflight removes quarantine)." -ForegroundColor Gray
Write-Host ""
exit 0
}
# ── Setup Homebrew tap token ─────────────────────────────────
if ($SetupHomebrew) {
Write-Host ""
Write-Host "Homebrew Tap Token Setup" -ForegroundColor Cyan
Write-Host "========================" -ForegroundColor Cyan
Write-Host ""
Write-Host "This creates a fine-grained GitHub token for the release workflow" -ForegroundColor Gray
Write-Host "to push cask updates to $tapRepo." -ForegroundColor Gray
Write-Host ""
# Check if gh is available
if (-not (Get-Command gh -ErrorAction SilentlyContinue)) {
Write-Host "GitHub CLI (gh) is required. Install: https://cli.github.com" -ForegroundColor Red
exit 1
}
# Check auth
$authStatus = gh auth status 2>&1
if ($LASTEXITCODE -ne 0) {
Write-Host "Not authenticated with GitHub CLI. Run: gh auth login" -ForegroundColor Red
exit 1
}
Write-Host "Creating fine-grained PAT for $tapRepo..." -ForegroundColor Gray
Write-Host ""
Write-Host "Since 'gh' cannot create fine-grained tokens via CLI yet," -ForegroundColor Yellow
Write-Host "please create one manually:" -ForegroundColor Yellow
Write-Host ""
Write-Host " 1. Go to: https://github.com/settings/personal-access-tokens/new" -ForegroundColor White
Write-Host " 2. Token name: mcpmux-homebrew-tap" -ForegroundColor White
Write-Host " 3. Expiration: 90 days (or custom)" -ForegroundColor White
Write-Host " 4. Repository: $tapRepo (only)" -ForegroundColor White
Write-Host " 5. Permissions: Contents — Read and write" -ForegroundColor White
Write-Host " 6. Click 'Generate token' and copy it" -ForegroundColor White
Write-Host ""
$token = Read-Host "Paste the token here (or press Enter to skip)"
if ([string]::IsNullOrWhiteSpace($token)) {
Write-Host "Skipped. Set it manually:" -ForegroundColor Yellow
Write-Host " gh secret set HOMEBREW_TAP_TOKEN --repo $repo" -ForegroundColor White
Write-Host ""
exit 0
}
# Set the secret
Write-Host ""
Write-Host "Setting HOMEBREW_TAP_TOKEN secret on $repo..." -ForegroundColor Gray
$token | gh secret set HOMEBREW_TAP_TOKEN --repo $repo
if ($LASTEXITCODE -eq 0) {
Write-Host "Done! HOMEBREW_TAP_TOKEN is now set." -ForegroundColor Green
} else {
Write-Host "Failed to set secret. Try manually:" -ForegroundColor Red
Write-Host " gh secret set HOMEBREW_TAP_TOKEN --repo $repo" -ForegroundColor White
}
Write-Host ""
exit 0
}
if ($ShowPubkey) {
if (Test-Path $pubkeyPath) {
Write-Host ""
Write-Host "Public key for tauri.conf.json:" -ForegroundColor Cyan
Write-Host ""
Get-Content $pubkeyPath
Write-Host ""
} else {
Write-Host "No public key found. Run without -ShowPubkey to generate." -ForegroundColor Yellow
}
exit 0
}
Write-Host ""
Write-Host "McpMux Release Setup" -ForegroundColor Cyan
Write-Host "====================" -ForegroundColor Cyan
Write-Host ""
# Check if key already exists
if (Test-Path $keyPath) {
Write-Host "Signing key already exists at: $keyPath" -ForegroundColor Yellow
Write-Host ""
$response = Read-Host "Overwrite? (y/N)"
if ($response -ne 'y' -and $response -ne 'Y') {
Write-Host "Aborted." -ForegroundColor Gray
exit 0
}
}
# Create directory if needed
$keyDir = Split-Path $keyPath
if (-not (Test-Path $keyDir)) {
New-Item -ItemType Directory -Path $keyDir -Force | Out-Null
}
Write-Host "Generating Tauri signing key..." -ForegroundColor Gray
Write-Host ""
# Generate the key
Push-Location (Join-Path $PSScriptRoot "..")
try {
pnpm --filter @mcpmux/desktop tauri signer generate -w $keyPath
if ($LASTEXITCODE -eq 0) {
Write-Host ""
Write-Host "Success!" -ForegroundColor Green
Write-Host ""
Write-Host "Files created:" -ForegroundColor Gray
Write-Host " Private key: $keyPath" -ForegroundColor White
Write-Host " Public key: $pubkeyPath" -ForegroundColor White
Write-Host ""
Write-Host "Next steps:" -ForegroundColor Cyan
Write-Host ""
Write-Host "1. Copy the PUBLIC key to tauri.conf.json:" -ForegroundColor Gray
Write-Host " .\setup-release.ps1 -ShowPubkey" -ForegroundColor White
Write-Host ""
Write-Host "2. Add the PRIVATE key to GitHub secrets:" -ForegroundColor Gray
Write-Host " - Go to: https://github.com/mcpmux/mcp-mux/settings/secrets/actions" -ForegroundColor White
Write-Host " - Add secret: TAURI_SIGNING_PRIVATE_KEY" -ForegroundColor White
Write-Host " - Value: contents of $keyPath" -ForegroundColor White
Write-Host ""
Write-Host "3. (Optional) Add password to GitHub secrets:" -ForegroundColor Gray
Write-Host " - Add secret: TAURI_SIGNING_PRIVATE_KEY_PASSWORD" -ForegroundColor White
Write-Host ""
}
} finally {
Pop-Location
}