# Forgejo 릴리스(draft)에 산출물을 업로드한다. 릴리스가 없으면 만들고, 동명 자산은 교체한다(재실행 멱등). # 사용: ./build/ci/upload-release-asset.ps1 -Tag v1.0.0 -Files out/a.exe, out/b.exe # 필요 환경: RELEASE_TOKEN + (Actions 기본 제공) GITHUB_SERVER_URL, GITHUB_REPOSITORY # RELEASE_PRERELEASE=true 면 prerelease 로 생성(리허설용) param( [Parameter(Mandatory)][string]$Tag, [Parameter(Mandatory)][string[]]$Files ) $ErrorActionPreference = 'Stop' if (-not $env:RELEASE_TOKEN) { throw "RELEASE_TOKEN 환경변수가 없습니다" } $api = "$($env:GITHUB_SERVER_URL.TrimEnd('/'))/api/v1/repos/$($env:GITHUB_REPOSITORY)" $hdr = @{ Authorization = "token $env:RELEASE_TOKEN" } # draft 릴리스는 tags/ 단건 조회에 안 잡힐 수 있어 목록에서 tag_name 으로 찾는다 function Find-Release { (Invoke-RestMethod -Uri "$api/releases?limit=50" -Headers $hdr) | Where-Object tag_name -eq $Tag | Select-Object -First 1 } $rel = Find-Release if (-not $rel) { $body = @{ tag_name = $Tag; name = $Tag; draft = $true prerelease = ($env:RELEASE_PRERELEASE -eq 'true') } | ConvertTo-Json try { $rel = Invoke-RestMethod -Method Post -Uri "$api/releases" -Headers $hdr -ContentType 'application/json' -Body $body } catch { $rel = Find-Release } # 병렬 잡 동시 생성 경합 대비 } if (-not $rel) { throw "릴리스 확보 실패: $Tag" } Write-Host "릴리스 #$($rel.id) ($Tag)" foreach ($f in $Files) { $item = Get-Item $f (Invoke-RestMethod -Uri "$api/releases/$($rel.id)/assets" -Headers $hdr) | Where-Object name -eq $item.Name | ForEach-Object { Invoke-RestMethod -Method Delete -Uri "$api/releases/$($rel.id)/assets/$($_.id)" -Headers $hdr | Out-Null } Invoke-RestMethod -Method Post -Uri "$api/releases/$($rel.id)/assets?name=$($item.Name)" ` -Headers $hdr -Form @{ attachment = $item } | Out-Null Write-Host ("업로드 완료: {0} ({1:N1} MB)" -f $item.Name, ($item.Length / 1MB)) }