param( [string]$Version = "", [string]$ForgejoBase = "https://git.avelo.top", [string]$Owner = "hansjone", [string]$Repo = "netx", [string]$Token = "", [string]$ReleaseDir = "" ) # Publish Windows Setup.exe to Forgejo/Gitea (mirror sync does NOT copy GitHub Release files). # Requires a Forgejo token with repo write (Settings → Applications → Generate New Token). # Default: https://git.avelo.top (public domain). LAN IP only when explicitly reachable. # # Example: # $env:NETX_FORGEJO_TOKEN = "..." # or User env NETX_FORGEJO_TOKEN # .\packaging\publish_forgejo_release.ps1 -Version 0.4.11 # # Optional LAN (when 10.0.0.131 is reachable): # .\packaging\publish_forgejo_release.ps1 -Version 0.4.11 -ForgejoBase "http://10.0.0.131:3000" $ErrorActionPreference = "Stop" . "$PSScriptRoot\_common.ps1" $repoRoot = Get-NetxRepoRoot if (-not $Version) { $Version = Get-NetxVersion -ProgramRoot $repoRoot } $tag = "v$Version" $relDir = if ($ReleaseDir) { $ReleaseDir } else { Join-Path $PSScriptRoot "release" } $setup = Join-Path $relDir "NetX-Setup-$Version.exe" if (-not $Token) { $Token = $env:NETX_FORGEJO_TOKEN if (-not $Token) { $Token = $env:FORGEJO_TOKEN } } if (-not $Token) { throw "forgejo_token_required: set NETX_FORGEJO_TOKEN or pass -Token" } if (-not (Test-Path $setup)) { throw "missing_setup: $setup (run build_release.ps1 + ISCC first)" } $apiBase = "$ForgejoBase/api/v1/repos/$Owner/$Repo" $headers = @{ "Authorization" = "token $Token" "Accept" = "application/json" } function Invoke-ForgejoJson { param( [string]$Method, [string]$Url, [object]$Body = $null ) $params = @{ Method = $Method Uri = $Url Headers = $headers ContentType = "application/json" } if ($null -ne $Body) { $params["Body"] = ($Body | ConvertTo-Json -Depth 5) } return Invoke-RestMethod @params } Write-Host "==> Forgejo publish $tag -> $ForgejoBase/$Owner/$Repo" # Ensure git tag exists on Forgejo (mirror usually already has it). try { $null = Invoke-ForgejoJson -Method GET -Url "$apiBase/git/refs/tags/$tag" Write-Host " tag $tag present on Forgejo" } catch { Write-Host "[WARN] tag $tag not found on Forgejo yet — run mirror-sync or push tag first" -ForegroundColor Yellow } $existing = $null try { $existing = Invoke-ForgejoJson -Method GET -Url "$apiBase/releases/tags/$tag" } catch { $existing = $null } $notes = @" NetX $Version Windows installer (published from GitHub release build). - NetX-Setup-$Version.exe "@ if ($existing -and $existing.id) { Write-Host "==> Release $tag already exists (id=$($existing.id)); deleting old release to re-upload assets" Invoke-ForgejoJson -Method DELETE -Url "$apiBase/releases/$($existing.id)" | Out-Null } Write-Host "==> Creating release $tag" $rel = Invoke-ForgejoJson -Method POST -Url "$apiBase/releases" -Body @{ tag_name = $tag target = "main" name = "NetX $Version" body = $notes draft = $false prerelease = $false } $relId = $rel.id if (-not $relId) { throw "forgejo_create_release_failed" } function Upload-ForgejoAsset { param([string]$Path) if (-not (Test-Path $Path)) { return } $name = Split-Path -Leaf $Path Write-Host "==> Uploading $name ..." $url = "$apiBase/releases/$relId/assets" $curl = Get-Command curl.exe -ErrorAction SilentlyContinue if (-not $curl) { throw "curl.exe required for asset upload" } # --ssl-no-revoke: schannel CRYPT_E_REVOCATION_OFFLINE often fails via proxy/offline CA. & $curl.Source -f -sS --ssl-no-revoke -X POST ` -H "Authorization: token $Token" ` -F "attachment=@$Path" ` $url if ($LASTEXITCODE -ne 0) { throw "upload_failed: $name" } Write-Host " OK $name" -ForegroundColor Green } Upload-ForgejoAsset -Path $setup $releaseUrl = "$ForgejoBase/$Owner/$Repo/releases/tag/$tag" Write-Host "" Write-Host "==> Forgejo release ready: $releaseUrl" -ForegroundColor Green Write-Host " Update API: $ForgejoBase/api/v1/repos/$Owner/$Repo/releases/latest"