Достижение: Добавлены скрипты и документация для релиза PDF Compressor.
- Добавлен release-body.md для подробных заметок о релизе на русском языке. - Реализован release-gitea.ps1 для автоматизированного релиза Gitea с помощью PowerShell. - Создан release-gitea.sh для автоматизированного релиза Gitea с помощью Bash. - Добавлен release.sh для сборки и маркировки релизов с поддержкой нескольких платформ. - Улучшен пользовательский интерфейс благодаря информативному логированию и обработке ошибок. - Добавлена поддержка переменных окружения и управления конфигурацией. - Добавлена функция создания архивов и загрузки ресурсов в Gitea.
This commit is contained in:
473
scripts/release-gitea.ps1
Normal file
473
scripts/release-gitea.ps1
Normal file
@@ -0,0 +1,473 @@
|
||||
# PDF Compressor Release Generator for Gitea
|
||||
# PowerShell version with Russian release описаниями
|
||||
# Author: PDF Compressor Team
|
||||
# Version: 1.0.0
|
||||
|
||||
param(
|
||||
[Parameter(Position=0)]
|
||||
[string]$Version,
|
||||
|
||||
[Parameter()]
|
||||
[switch]$Help
|
||||
)
|
||||
|
||||
# Ensure console uses UTF-8 to display Russian correctly
|
||||
try { [Console]::OutputEncoding = [System.Text.Encoding]::UTF8 } catch {}
|
||||
# Переменные конфигурации
|
||||
$BINARY_NAME = "pdf-compressor"
|
||||
$BUILD_DIR = "releases"
|
||||
# Prefer environment variables; do not hardcode secrets
|
||||
$GITEA_SERVER = $env:GITEA_SERVER
|
||||
$GITEA_USER = $env:GITEA_USER
|
||||
$GITEA_PASSWORD = $env:GITEA_PASSWORD
|
||||
$GITEA_OWNER = $env:GITEA_OWNER
|
||||
$GITEA_REPO = if ($env:GITEA_REPO) { $env:GITEA_REPO } else { "pdf-compressor" }
|
||||
|
||||
# Цвета для вывода
|
||||
$Colors = @{
|
||||
Red = "Red"
|
||||
Green = "Green"
|
||||
Yellow = "Yellow"
|
||||
Blue = "Blue"
|
||||
White = "White"
|
||||
}
|
||||
|
||||
# Функции вывода сообщений
|
||||
function Write-Log {
|
||||
param([string]$Message)
|
||||
Write-Host "[INFO] $Message" -ForegroundColor $Colors.Green
|
||||
}
|
||||
|
||||
function Write-Warn {
|
||||
param([string]$Message)
|
||||
Write-Host "[WARNING] $Message" -ForegroundColor $Colors.Yellow
|
||||
}
|
||||
|
||||
function Write-Error-Custom {
|
||||
param([string]$Message)
|
||||
Write-Host "[ERROR] $Message" -ForegroundColor $Colors.Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Функция справки
|
||||
function Show-Help {
|
||||
Write-Host "PDF Compressor Release Generator" -ForegroundColor $Colors.Blue
|
||||
Write-Host ""
|
||||
Write-Host "Usage: .\release-gitea.ps1 [version]"
|
||||
Write-Host ""
|
||||
Write-Host "Parameters:"
|
||||
Write-Host " -Version Release version (e.g.: v1.2.0)"
|
||||
Write-Host " If not specified, uses VERSION file or latest git tag"
|
||||
Write-Host " -Help Show this help"
|
||||
Write-Host ""
|
||||
Write-Host "Environment variables:"
|
||||
Write-Host " GITEA_SERVER Gitea server URL"
|
||||
Write-Host " GITEA_USER Gitea username"
|
||||
Write-Host " GITEA_PASSWORD Gitea password"
|
||||
Write-Host " GITEA_OWNER Repository owner"
|
||||
Write-Host " GITEA_REPO Repository name"
|
||||
Write-Host " .env Automatically loaded from project root (KEY=VALUE)"
|
||||
Write-Host ""
|
||||
Write-Host "Examples:"
|
||||
Write-Host " .\release-gitea.ps1 # Auto-detect version"
|
||||
Write-Host " .\release-gitea.ps1 -Version v1.2.0 # Specific version"
|
||||
Write-Host ""
|
||||
}
|
||||
|
||||
# Load variables from a .env file into the current process environment
|
||||
function Load-DotEnv {
|
||||
param(
|
||||
[string]$Path = ".env",
|
||||
[switch]$Override
|
||||
)
|
||||
try {
|
||||
$candidates = @()
|
||||
# current working directory
|
||||
$candidates += (Join-Path -Path (Get-Location) -ChildPath $Path)
|
||||
# script directory
|
||||
if ($PSScriptRoot) {
|
||||
$candidates += (Join-Path -Path $PSScriptRoot -ChildPath $Path)
|
||||
# repository root (one level up from scripts)
|
||||
$candidates += (Join-Path -Path (Split-Path -Parent $PSScriptRoot) -ChildPath $Path)
|
||||
}
|
||||
$envFile = $candidates | Where-Object { Test-Path $_ } | Select-Object -First 1
|
||||
if (-not $envFile) { return }
|
||||
Write-Log "Loading .env from $envFile"
|
||||
$lines = Get-Content -Path $envFile -Encoding UTF8 -ErrorAction Stop
|
||||
foreach ($raw in $lines) {
|
||||
$line = $raw.Trim()
|
||||
if (-not $line) { continue }
|
||||
if ($line.StartsWith('#') -or $line.StartsWith(';')) { continue }
|
||||
# Remove inline comments that start with # after a space
|
||||
$hashIdx = $line.IndexOf(' # ')
|
||||
if ($hashIdx -gt 0) { $line = $line.Substring(0, $hashIdx).TrimEnd() }
|
||||
# Support optional leading 'export '
|
||||
if ($line -like 'export *') { $line = $line.Substring(7).TrimStart() }
|
||||
$eq = $line.IndexOf('=')
|
||||
if ($eq -lt 1) { continue }
|
||||
$key = $line.Substring(0, $eq).Trim()
|
||||
$val = $line.Substring($eq + 1).Trim()
|
||||
if ($val.StartsWith('"') -and $val.EndsWith('"') -and $val.Length -ge 2) {
|
||||
$val = $val.Substring(1, $val.Length - 2)
|
||||
$val = $val -replace "\\n", "`n" -replace "\\r", "" -replace "\\t", "`t" -replace "\\\\", "\\"
|
||||
} elseif ($val.StartsWith("'") -and $val.EndsWith("'") -and $val.Length -ge 2) {
|
||||
$val = $val.Substring(1, $val.Length - 2)
|
||||
}
|
||||
$existing = [Environment]::GetEnvironmentVariable($key, 'Process')
|
||||
if ($Override -or [string]::IsNullOrEmpty($existing)) {
|
||||
[Environment]::SetEnvironmentVariable($key, $val, 'Process')
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
Write-Warn "Failed to load .env: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
|
||||
# Функция проверки зависимостей
|
||||
function Test-Dependencies {
|
||||
Write-Log "Checking dependencies..."
|
||||
|
||||
# Check Go
|
||||
if (!(Get-Command "go" -ErrorAction SilentlyContinue)) {
|
||||
Write-Error-Custom "Go is not installed"
|
||||
}
|
||||
|
||||
# Check git
|
||||
if (!(Get-Command "git" -ErrorAction SilentlyContinue)) {
|
||||
Write-Error-Custom "Git is not installed"
|
||||
}
|
||||
|
||||
Write-Log "All dependencies found"
|
||||
}
|
||||
|
||||
# Функция проверки переменных окружения
|
||||
function Test-Environment {
|
||||
Write-Log "Checking environment variables..."
|
||||
|
||||
# Refresh from environment (after Load-DotEnv) so .env overrides take effect
|
||||
$script:GITEA_SERVER = $env:GITEA_SERVER
|
||||
$script:GITEA_USER = $env:GITEA_USER
|
||||
$script:GITEA_PASSWORD = $env:GITEA_PASSWORD
|
||||
$script:GITEA_OWNER = $env:GITEA_OWNER
|
||||
if (-not $script:GITEA_REPO -and $env:GITEA_REPO) { $script:GITEA_REPO = $env:GITEA_REPO }
|
||||
|
||||
if ([string]::IsNullOrEmpty($script:GITEA_SERVER)) { Write-Error-Custom "GITEA_SERVER is not set" }
|
||||
if ([string]::IsNullOrEmpty($script:GITEA_USER)) { Write-Error-Custom "GITEA_USER is not set" }
|
||||
if ([string]::IsNullOrEmpty($script:GITEA_PASSWORD)) { Write-Error-Custom "GITEA_PASSWORD is not set" }
|
||||
if ([string]::IsNullOrEmpty($script:GITEA_OWNER)) { Write-Error-Custom "GITEA_OWNER is not set" }
|
||||
|
||||
# Normalize values (strip quotes/spaces, remove trailing slash)
|
||||
$script:GITEA_SERVER = ($script:GITEA_SERVER).ToString().Trim().Trim('"', "'").TrimEnd('/')
|
||||
$script:GITEA_USER = ($script:GITEA_USER).ToString().Trim().Trim('"', "'")
|
||||
$script:GITEA_PASSWORD = ($script:GITEA_PASSWORD).ToString().Trim()
|
||||
$script:GITEA_OWNER = ($script:GITEA_OWNER).ToString().Trim().Trim('"', "'")
|
||||
$script:GITEA_REPO = ($script:GITEA_REPO).ToString().Trim().Trim('"', "'")
|
||||
|
||||
Write-Log "Environment variables checked"
|
||||
Write-Log "Server: $($script:GITEA_SERVER) | Repo: $($script:GITEA_OWNER)/$($script:GITEA_REPO)"
|
||||
}
|
||||
|
||||
# Quick preflight checks against Gitea API
|
||||
function Test-GiteaApi {
|
||||
$apiBase = "$($script:GITEA_SERVER)/api/v1"
|
||||
Write-Log "API base: $apiBase"
|
||||
try {
|
||||
$v = Invoke-RestMethod -Uri "$apiBase/version" -Method Get -ErrorAction Stop
|
||||
Write-Log "Gitea version: $($v.version)"
|
||||
} catch {
|
||||
Write-Error-Custom "API check failed: $($_.Exception.Message). URL: $apiBase/version"
|
||||
}
|
||||
try {
|
||||
$auth = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("$($script:GITEA_USER):$($script:GITEA_PASSWORD)"))
|
||||
Invoke-RestMethod -Uri "$apiBase/repos/$($script:GITEA_OWNER)/$($script:GITEA_REPO)" -Method Get -Headers @{ Authorization = "Basic $auth" } -ErrorAction Stop | Out-Null
|
||||
Write-Log "Repo access OK"
|
||||
} catch {
|
||||
Write-Error-Custom "Repo check failed: $($_.Exception.Message). URL: $apiBase/repos/$($script:GITEA_OWNER)/$($script:GITEA_REPO)"
|
||||
}
|
||||
}
|
||||
|
||||
# Функция определения версии
|
||||
function Get-ReleaseVersion {
|
||||
param([string]$InputVersion)
|
||||
|
||||
if (![string]::IsNullOrEmpty($InputVersion)) {
|
||||
$script:Version = $InputVersion
|
||||
} elseif (Test-Path "VERSION") {
|
||||
$script:Version = (Get-Content "VERSION" -Raw).Trim()
|
||||
} else {
|
||||
try {
|
||||
$script:Version = git describe --tags --abbrev=0 2>$null
|
||||
if ([string]::IsNullOrEmpty($script:Version)) { $script:Version = "v1.0.0" }
|
||||
} catch { $script:Version = "v1.0.0" }
|
||||
}
|
||||
|
||||
if (!$script:Version.StartsWith("v")) { $script:Version = "v$($script:Version)" }
|
||||
Write-Log "Release version: $($script:Version)"
|
||||
}
|
||||
|
||||
# Проверка статуса git
|
||||
function Test-GitStatus {
|
||||
Write-Log "Checking git status..."
|
||||
try { git rev-parse --git-dir | Out-Null } catch { Write-Error-Custom "Git repository not found" }
|
||||
|
||||
$status = git status --porcelain
|
||||
if (![string]::IsNullOrEmpty($status)) {
|
||||
Write-Warn "There are uncommitted changes"
|
||||
$response = Read-Host "Continue? (y/N)"
|
||||
if ($response -notin @('y','Y')) { exit 1 }
|
||||
}
|
||||
|
||||
$currentBranch = git branch --show-current
|
||||
if ($currentBranch -notin @('master','main')) {
|
||||
Write-Warn "You are not on master/main branch (current: $currentBranch)"
|
||||
$response = Read-Host "Continue? (y/N)"
|
||||
if ($response -notin @('y','Y')) { exit 1 }
|
||||
}
|
||||
}
|
||||
|
||||
# Запуск тестов
|
||||
function Invoke-Tests {
|
||||
Write-Log "Running tests..."
|
||||
$result = go test ./...
|
||||
if ($LASTEXITCODE -ne 0) { Write-Error-Custom "Tests failed" }
|
||||
Write-Log "All tests passed successfully"
|
||||
}
|
||||
|
||||
# Создание тега
|
||||
function New-GitTag {
|
||||
Write-Log "Creating tag $($script:Version)..."
|
||||
$existingTag = git tag -l $script:Version
|
||||
if (![string]::IsNullOrEmpty($existingTag)) {
|
||||
Write-Warn "Tag $($script:Version) already exists locally"
|
||||
$response = Read-Host "Overwrite? (y/N)"
|
||||
if ($response -in @('y','Y')) {
|
||||
git tag -d $script:Version
|
||||
Write-Log "Deleted local tag $($script:Version)"
|
||||
} else { exit 1 }
|
||||
}
|
||||
|
||||
$releaseNotes = @"
|
||||
Release $($script:Version)
|
||||
|
||||
New Features:
|
||||
- Interface updates and improvements
|
||||
- Performance optimization
|
||||
|
||||
Bug Fixes:
|
||||
- Various fixes and stability improvements
|
||||
|
||||
Supported Platforms:
|
||||
- Windows (64-bit)
|
||||
- Linux (64-bit, ARM64)
|
||||
- macOS (Intel 64-bit, Apple Silicon ARM64)
|
||||
"@;
|
||||
|
||||
git tag -a $script:Version -m $releaseNotes
|
||||
git push origin $script:Version --force
|
||||
Write-Log "Tag $($script:Version) created and pushed"
|
||||
}
|
||||
|
||||
# Сборка бинарников
|
||||
function Build-Binaries {
|
||||
Write-Log "Building binaries for different platforms..."
|
||||
$releaseDir = "$BUILD_DIR\$($script:Version)"
|
||||
New-Item -ItemType Directory -Force -Path $releaseDir | Out-Null
|
||||
|
||||
$platforms = @(
|
||||
@{GOOS="windows"; GOARCH="amd64"},
|
||||
@{GOOS="linux"; GOARCH="amd64"},
|
||||
@{GOOS="linux"; GOARCH="arm64"},
|
||||
@{GOOS="darwin"; GOARCH="amd64"},
|
||||
@{GOOS="darwin"; GOARCH="arm64"}
|
||||
)
|
||||
|
||||
foreach ($platform in $platforms) {
|
||||
$output = "$releaseDir\$BINARY_NAME-$($script:Version)-$($platform.GOOS)-$($platform.GOARCH)"
|
||||
if ($platform.GOOS -eq "windows") { $output += ".exe" }
|
||||
Write-Log "Building for $($platform.GOOS)/$($platform.GOARCH)"
|
||||
$env:GOOS = $platform.GOOS; $env:GOARCH = $platform.GOARCH
|
||||
$buildTime = Get-Date -Format "yyyy-MM-dd_HH:mm:ss"
|
||||
$ldflags = "-s -w -X main.version=$($script:Version) -X main.buildTime=$buildTime"
|
||||
go build -ldflags="$ldflags" -o $output cmd\main.go
|
||||
if ($LASTEXITCODE -ne 0) { Write-Error-Custom "Error: Build failed for $($platform.GOOS)/$($platform.GOARCH)" }
|
||||
Write-Log "Success: $($platform.GOOS)/$($platform.GOARCH) built successfully"
|
||||
}
|
||||
Remove-Item Env:GOOS -ErrorAction SilentlyContinue
|
||||
Remove-Item Env:GOARCH -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
# Создание архивов
|
||||
function New-Archives {
|
||||
Write-Log "Creating archives..."
|
||||
Push-Location "$BUILD_DIR\$($script:Version)"
|
||||
try {
|
||||
Get-ChildItem "*windows*.exe" | ForEach-Object {
|
||||
$archive = $_.Name -replace '\.exe$', '.zip'
|
||||
Compress-Archive -Path $_.Name -DestinationPath $archive -Force
|
||||
Remove-Item $_.Name
|
||||
Write-Log "Created archive: $archive"
|
||||
}
|
||||
Get-ChildItem "*linux*", "*darwin*" | Where-Object { $_.Extension -ne ".zip" -and $_.Extension -ne ".gz" } | ForEach-Object {
|
||||
$archive = "$($_.Name).zip"
|
||||
Compress-Archive -Path $_.Name -DestinationPath $archive -Force
|
||||
Remove-Item $_.Name
|
||||
Write-Log "Created archive: $archive"
|
||||
}
|
||||
} finally { Pop-Location }
|
||||
}
|
||||
|
||||
# Создание релиза в Gitea
|
||||
function New-GiteaRelease {
|
||||
Write-Log "Creating release in Gitea..."
|
||||
$apiBase = "$GITEA_SERVER/api/v1"
|
||||
# Load Russian body from external UTF-8 file to avoid PS source encoding issues
|
||||
$bodyTemplatePath = Join-Path $PSScriptRoot 'release-body-ru.md'
|
||||
if (-not (Test-Path $bodyTemplatePath)) { Write-Error-Custom "Release body template not found: $bodyTemplatePath" }
|
||||
$releaseBody = [System.IO.File]::ReadAllText($bodyTemplatePath, (New-Object System.Text.UTF8Encoding($false)))
|
||||
$releaseBody = $releaseBody -replace "{{VERSION}}", "$($script:Version)"
|
||||
|
||||
# Авторизация
|
||||
$credentials = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes("$($GITEA_USER):$($GITEA_PASSWORD)"))
|
||||
$headers = @{ "Authorization" = "Basic $credentials"; "Content-Type" = "application/json; charset=utf-8" }
|
||||
|
||||
$releaseId = $null
|
||||
|
||||
# Проверяем существующий релиз
|
||||
try {
|
||||
$existing = Invoke-RestMethod -Uri "$apiBase/repos/$GITEA_OWNER/$GITEA_REPO/releases/tags/$($script:Version)" -Method Get -Headers $headers
|
||||
if ($existing -and $existing.id) {
|
||||
Write-Log "Release for tag $($script:Version) already exists (ID: $($existing.id)). Will upload assets."
|
||||
$releaseId = $existing.id
|
||||
# Если описание короткое — обновим полным русским
|
||||
if (-not $existing.body -or $existing.body.Length -lt 100) {
|
||||
$updateJson = @{ name = "PDF Compressor $($script:Version)"; body = $releaseBody } | ConvertTo-Json -Depth 3
|
||||
$tempUpdate = "temp-update-$($script:Version).json"
|
||||
# $updateJson | Out-File -FilePath $tempUpdate -Encoding UTF8
|
||||
[System.IO.File]::WriteAllText($tempUpdate, $updateJson, (New-Object System.Text.UTF8Encoding($false)))
|
||||
if (Get-Command "curl.exe" -ErrorAction SilentlyContinue) {
|
||||
& curl.exe -s -X PATCH -H "Authorization: Basic $credentials" -H "Content-Type: application/json; charset=utf-8" --data-binary "@$tempUpdate" "$apiBase/repos/$GITEA_OWNER/$GITEA_REPO/releases/$releaseId" | Out-Null
|
||||
} else {
|
||||
$updateBytes = [System.Text.Encoding]::UTF8.GetBytes($updateJson)
|
||||
Invoke-RestMethod -Uri "$apiBase/repos/$GITEA_OWNER/$GITEA_REPO/releases/$releaseId" -Method Patch -Body $updateBytes -Headers $headers | Out-Null
|
||||
}
|
||||
Remove-Item $tempUpdate -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
} catch { Write-Log "No existing release found for tag $($script:Version), will create new one." }
|
||||
|
||||
# Создаём релиз
|
||||
if (-not $releaseId) {
|
||||
$releaseObj = @{ tag_name = $script:Version; name = "PDF Compressor $($script:Version)"; body = $releaseBody; draft = $false; prerelease = $false }
|
||||
$releaseJson = ($releaseObj | ConvertTo-Json -Depth 4)
|
||||
$tempJsonFile = "temp-release-$($script:Version).json"
|
||||
[System.IO.File]::WriteAllText($tempJsonFile, $releaseJson, (New-Object System.Text.UTF8Encoding($false)))
|
||||
Start-Sleep -Seconds 1
|
||||
if (Get-Command "curl.exe" -ErrorAction SilentlyContinue) {
|
||||
try {
|
||||
Write-Log "Creating release via curl..."
|
||||
$releaseUrl = "$apiBase/repos/$GITEA_OWNER/$GITEA_REPO/releases"
|
||||
$curlResult = & curl.exe -s -X POST -H "Authorization: Basic $credentials" -H "Content-Type: application/json; charset=utf-8" --data-binary "@$tempJsonFile" "$releaseUrl"
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
$response = $curlResult | ConvertFrom-Json
|
||||
$releaseId = $response.id
|
||||
Write-Log "Release created with ID: $releaseId via curl"
|
||||
} else { throw "Curl failed with exit code $LASTEXITCODE (URL: $releaseUrl)" }
|
||||
} catch {
|
||||
Write-Warn "Curl method failed: $($_.Exception.Message)"
|
||||
$minimalJson = @{ tag_name = $script:Version; name = "PDF Compressor $($script:Version)"; body = "Release $($script:Version)" } | ConvertTo-Json -Depth 2
|
||||
$minimalBytes = [System.Text.Encoding]::UTF8.GetBytes($minimalJson)
|
||||
try {
|
||||
$response = Invoke-RestMethod -Uri "$apiBase/repos/$GITEA_OWNER/$GITEA_REPO/releases" -Method Post -Body $minimalBytes -Headers $headers
|
||||
$releaseId = $response.id
|
||||
Write-Log "Minimal release created with ID: $releaseId"
|
||||
} catch { Write-Error-Custom "Failed to create release: $($_.Exception.Message)" }
|
||||
}
|
||||
} else {
|
||||
$releaseBytes = [System.Text.Encoding]::UTF8.GetBytes($releaseJson)
|
||||
try {
|
||||
$response = Invoke-RestMethod -Uri "$apiBase/repos/$GITEA_OWNER/$GITEA_REPO/releases" -Method Post -Body $releaseBytes -Headers $headers
|
||||
$releaseId = $response.id
|
||||
Write-Log "Release created with ID: $releaseId via PowerShell"
|
||||
} catch { Write-Error-Custom "Failed to create release: $($_.Exception.Message)" }
|
||||
}
|
||||
Remove-Item $tempJsonFile -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
# Fallback: resolve release ID if creation didn't return it
|
||||
if (-not $releaseId) {
|
||||
try {
|
||||
$check = Invoke-RestMethod -Uri "$apiBase/repos/$GITEA_OWNER/$GITEA_REPO/releases/tags/$($script:Version)" -Method Get -Headers $headers
|
||||
if ($check -and $check.id) {
|
||||
$releaseId = $check.id
|
||||
Write-Log "Release ID resolved via GET: $releaseId"
|
||||
}
|
||||
} catch {
|
||||
Write-Warn "Could not resolve release ID after creation: $($_.Exception.Message)"
|
||||
}
|
||||
}
|
||||
if (-not $releaseId) { Write-Error-Custom "Release created but ID not found. Aborting uploads." }
|
||||
|
||||
# Загрузка архивов
|
||||
Write-Log "Uploading archives..."
|
||||
Get-ChildItem "$BUILD_DIR\$($script:Version)\*" | ForEach-Object {
|
||||
Write-Log "Uploading file $($_.Name)..."
|
||||
try {
|
||||
$filePath = $_.FullName
|
||||
if (Get-Command "curl.exe" -ErrorAction SilentlyContinue) {
|
||||
Write-Log "Using curl for upload..."
|
||||
& curl.exe -s -X POST -H "Authorization: Basic $credentials" -F "attachment=@$filePath" "$apiBase/repos/$GITEA_OWNER/$GITEA_REPO/releases/$releaseId/assets" | Out-Null
|
||||
if ($LASTEXITCODE -eq 0) { Write-Log "Success: file $($_.Name) uploaded via curl" } else { Write-Warn "Curl upload failed for $($_.Name)" }
|
||||
} else {
|
||||
$boundary = [System.Guid]::NewGuid().ToString()
|
||||
$LF = "`r`n"
|
||||
$fileContent = [System.IO.File]::ReadAllBytes($filePath)
|
||||
# Build multipart body header with proper PowerShell escaping
|
||||
$bodyHeader = @(
|
||||
"--$boundary$LF"
|
||||
"Content-Disposition: form-data; name=`"attachment`"; filename=`"$($_.Name)`"$LF"
|
||||
"Content-Type: application/octet-stream$LF$LF"
|
||||
) -join ""
|
||||
$bodyBytes = [System.Text.Encoding]::UTF8.GetBytes($bodyHeader)
|
||||
$endBytes = [System.Text.Encoding]::UTF8.GetBytes("$LF--$boundary--$LF")
|
||||
# Concatenate bytes efficiently
|
||||
$fullBody = New-Object byte[] ($bodyBytes.Length + $fileContent.Length + $endBytes.Length)
|
||||
[Array]::Copy($bodyBytes, 0, $fullBody, 0, $bodyBytes.Length)
|
||||
[Array]::Copy($fileContent, 0, $fullBody, $bodyBytes.Length, $fileContent.Length)
|
||||
[Array]::Copy($endBytes, 0, $fullBody, $bodyBytes.Length + $fileContent.Length, $endBytes.Length)
|
||||
$uploadHeaders = @{ "Authorization" = "Basic $credentials"; "Content-Type" = "multipart/form-data; boundary=$boundary" }
|
||||
Invoke-RestMethod -Uri "$apiBase/repos/$GITEA_OWNER/$GITEA_REPO/releases/$releaseId/assets" -Method Post -Body $fullBody -Headers $uploadHeaders | Out-Null
|
||||
Write-Log "Success: file $($_.Name) uploaded via PowerShell"
|
||||
}
|
||||
} catch { Write-Warn "Error uploading file $($_.Name): $($_.Exception.Message)" }
|
||||
}
|
||||
}
|
||||
|
||||
# Главная функция
|
||||
function Main {
|
||||
Write-Host "PDF Compressor Release Generator" -ForegroundColor $Colors.Blue
|
||||
Write-Host ""
|
||||
if ($Help) { Show-Help; return }
|
||||
try {
|
||||
# Load variables from .env before validating environment
|
||||
Load-DotEnv -Override
|
||||
Test-Dependencies
|
||||
Test-Environment
|
||||
Test-GiteaApi
|
||||
Get-ReleaseVersion $Version
|
||||
Test-GitStatus
|
||||
Invoke-Tests
|
||||
New-GitTag
|
||||
Build-Binaries
|
||||
New-Archives
|
||||
New-GiteaRelease
|
||||
Write-Log "Release $($script:Version) successfully created!"
|
||||
Write-Host ""
|
||||
Write-Host "Release available at:" -ForegroundColor $Colors.Green
|
||||
Write-Host "$GITEA_SERVER/$GITEA_OWNER/$GITEA_REPO/releases/tag/$($script:Version)"
|
||||
Write-Host ""
|
||||
Write-Host "Done! Release published and ready to use." -ForegroundColor $Colors.Green
|
||||
} catch { Write-Error-Custom "An error occurred: $($_.Exception.Message)" }
|
||||
}
|
||||
|
||||
# Запуск
|
||||
Main
|
||||
Reference in New Issue
Block a user