# Upload myoffice-publish.tar.gz to a Gitea Release on the public repo. # Usage: # $env:GITEA_TOKEN = '' # .\proxmox\publish.ps1 -Tar # .\proxmox\release.ps1 -GiteaUrl https://gitea.example.com -Owner org -Repo myoffice-public -Tag v1.2.3 # # Token needs write:repository on the public repo. [CmdletBinding()] param( [Parameter(Mandatory = $true)] [string]$GiteaUrl, [Parameter(Mandatory = $true)] [string]$Owner, [string]$Repo = 'myoffice-public', [Parameter(Mandatory = $true)] [string]$Tag, [string]$Token = $env:GITEA_TOKEN, [string]$AssetPath = '', [string]$Title = '', [string]$Body = 'MyOffice published API + SPA (Proxmox CT artifact).', [string]$Target = 'main' ) $ErrorActionPreference = 'Stop' if (-not $Token) { throw 'GITEA_TOKEN (or -Token) is required.' } $scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path $repoRoot = Resolve-Path (Join-Path $scriptDir '..') if (-not $AssetPath) { $AssetPath = Join-Path $repoRoot 'myoffice-publish.tar.gz' } if (-not (Test-Path $AssetPath)) { throw "Asset not found: $AssetPath — run .\proxmox\publish.ps1 -Tar first." } $GiteaUrl = $GiteaUrl.TrimEnd('/') $api = "$GiteaUrl/api/v1" $assetName = 'myoffice-publish.tar.gz' if (-not $Title) { $Title = $Tag } $headers = @{ Authorization = "token $Token" Accept = 'application/json' } function Invoke-GiteaJson { param( [string]$Method, [string]$Uri, [object]$BodyObject = $null ) $params = @{ Method = $Method Uri = $Uri Headers = $headers } if ($null -ne $BodyObject) { $params.ContentType = 'application/json' $params.Body = ($BodyObject | ConvertTo-Json -Depth 6) } return Invoke-RestMethod @params } Write-Host "-----------------------------------------------" Write-Host "Gitea release $Owner/$Repo tag $Tag" Write-Host "-----------------------------------------------" $release = $null try { $release = Invoke-GiteaJson -Method GET -Uri "$api/repos/$Owner/$Repo/releases/tags/$Tag" Write-Host "Release $Tag already exists (id $($release.id))." } catch { Write-Host "Creating release $Tag..." $release = Invoke-GiteaJson -Method POST -Uri "$api/repos/$Owner/$Repo/releases" -BodyObject @{ tag_name = $Tag target_commitish = $Target name = $Title body = $Body draft = $false prerelease = $false } Write-Host "Created release id $($release.id)." } # Remove existing asset with the same name so re-upload works $existing = @($release.assets) | Where-Object { $_.name -eq $assetName } foreach ($a in $existing) { Write-Host "Deleting existing asset id $($a.id) ($($a.name))..." Invoke-GiteaJson -Method DELETE -Uri "$api/repos/$Owner/$Repo/releases/$($release.id)/assets/$($a.id)" | Out-Null } $uploadUrl = "$api/repos/$Owner/$Repo/releases/$($release.id)/assets?name=$assetName" Write-Host "Uploading $AssetPath ..." # Prefer curl multipart (reliable on Windows PowerShell 5 + 7) $curl = Get-Command curl.exe -ErrorAction SilentlyContinue if ($curl) { $args = @( '-fsS', '-X', 'POST', '-H', "Authorization: token $Token", '-F', "attachment=@$AssetPath", $uploadUrl ) & curl.exe @args if ($LASTEXITCODE -ne 0) { throw "curl upload failed with exit code $LASTEXITCODE" } } else { # Fallback: .NET multipart Add-Type -AssemblyName System.Net.Http $handler = [System.Net.Http.HttpClientHandler]::new() $client = [System.Net.Http.HttpClient]::new($handler) $client.DefaultRequestHeaders.Add('Authorization', "token $Token") $content = [System.Net.Http.MultipartFormDataContent]::new() $fs = [System.IO.File]::OpenRead($AssetPath) try { $streamContent = [System.Net.Http.StreamContent]::new($fs) $streamContent.Headers.ContentType = [System.Net.Http.Headers.MediaTypeHeaderValue]::Parse('application/octet-stream') $content.Add($streamContent, 'attachment', $assetName) $resp = $client.PostAsync($uploadUrl, $content).Result if (-not $resp.IsSuccessStatusCode) { $err = $resp.Content.ReadAsStringAsync().Result throw "Upload failed: $($resp.StatusCode) $err" } } finally { $fs.Dispose() $content.Dispose() $client.Dispose() } } $downloadUrl = "$GiteaUrl/$Owner/$Repo/releases/download/$Tag/$assetName" Write-Host "" Write-Host "Uploaded. Download URL:" Write-Host " $downloadUrl" Write-Host "Latest API:" Write-Host " $api/repos/$Owner/$Repo/releases/latest" Write-Host ""