Достижение: Добавлены скрипты и документация для релиза PDF Compressor.

- Добавлен release-body.md для подробных заметок о релизе на русском языке.
- Реализован release-gitea.ps1 для автоматизированного релиза Gitea с помощью PowerShell.
- Создан release-gitea.sh для автоматизированного релиза Gitea с помощью Bash.
- Добавлен release.sh для сборки и маркировки релизов с поддержкой нескольких платформ.
- Улучшен пользовательский интерфейс благодаря информативному логированию и обработке ошибок.
- Добавлена ​​поддержка переменных окружения и управления конфигурацией.
- Добавлена ​​функция создания архивов и загрузки ресурсов в Gitea.
This commit is contained in:
Dmitriy Fofanov
2025-11-05 09:33:12 +03:00
parent f328d67080
commit ec65cfd05a
43 changed files with 5792 additions and 2 deletions

73
scripts/release-body.md Normal file
View File

@@ -0,0 +1,73 @@
# PDF Compressor {{VERSION}}
Мощный инструмент для сжатия PDF-файлов с интуитивным текстовым интерфейсом.
## ✨ Новые возможности
- Рекурсивное сканирование директорий для поиска PDF-файлов
- Улучшенный пользовательский интерфейс с прогресс-индикатором
- Оптимизация производительности при обработке больших файлов
- Атомарная замена файлов с резервным копированием
- Поддержка конфигурационных файлов YAML
## 🐛 Исправления и улучшения
- Исправлена обработка файлов с нестандартными именами
- Улучшена стабильность при работе с поврежденными PDF
- Оптимизирован расход памяти при сжатии больших документов
- Исправлены проблемы с кодировкой имен файлов
## 📦 Установка и запуск
### Быстрая установка
1. Скачайте архив для вашей операционной системы
2. Распакуйте в желаемую папку
3. Запустите исполняемый файл
### Системные требования
- Операционная система: Windows 10+, Linux, macOS 10.14+
- Свободное место на диске: минимум 50 МБ
- Оперативная память: рекомендуется 512 МБ
## 💻 Поддерживаемые платформы
| Платформа | Архитектура | Файл для скачивания |
|-----------|-------------|---------------------|
| **Windows** | x64 | `pdf-compressor-{{VERSION}}-windows-amd64.zip` |
| **Linux** | x64 | `pdf-compressor-{{VERSION}}-linux-amd64.zip` |
| **Linux** | ARM64 | `pdf-compressor-{{VERSION}}-linux-arm64.zip` |
| **macOS** | Intel x64 | `pdf-compressor-{{VERSION}}-darwin-amd64.zip` |
| **macOS** | Apple Silicon | `pdf-compressor-{{VERSION}}-darwin-arm64.zip` |
## 🚀 Использование
После установки программу можно запустить несколькими способами:
**Интерактивный режим:**
```bash
./pdf-compressor
```
**Пакетная обработка:**
```bash
./pdf-compressor -input /path/to/pdfs -output /path/to/compressed
```
**Обработка одного файла:**
```bash
./pdf-compressor -file document.pdf
```
## 📖 Документация
- **README.md** - основная документация
- **config.yaml.example** - пример конфигурационного файла
- **RELEASE_GUIDE.md** - руководство по релизам
## 🆘 Поддержка
Если у вас возникли вопросы или проблемы:
1. Проверьте документацию в репозитории
2. Создайте Issue с описанием проблемы
3. Приложите лог-файлы для диагностики
---
**Благодарим за использование PDF Compressor!** 🙏

473
scripts/release-gitea.ps1 Normal file
View 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

369
scripts/release-gitea.sh Normal file
View File

@@ -0,0 +1,369 @@
#!/bin/bash
# Скрипт автоматической генерации релиза на Gitea для PDF Compressor
# Автор: PDF Compressor Team
# Версия: 1.0.0
set -e # Остановка при ошибках
# Цвета для вывода
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Переменные конфигурации
BINARY_NAME="pdf-compressor"
BUILD_DIR="releases"
GITEA_SERVER="" # Заполните URL вашего Gitea сервера
GITEA_TOKEN="" # Заполните токен доступа Gitea
GITEA_OWNER="" # Заполните владельца репозитория
GITEA_REPO="pdf-compressor"
# Функция вывода сообщений
log() {
echo -e "${GREEN}[INFO]${NC} $1"
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
error() {
echo -e "${RED}[ERROR]${NC} $1"
exit 1
}
# Функция проверки зависимостей
check_dependencies() {
log "Проверка зависимостей..."
# Проверяем Go
if ! command -v go &> /dev/null; then
error "Go не установлен"
fi
# Проверяем git
if ! command -v git &> /dev/null; then
error "Git не установлен"
fi
# Проверяем curl для API запросов
if ! command -v curl &> /dev/null; then
error "curl не установлен"
fi
# Проверяем zip
if ! command -v zip &> /dev/null; then
error "zip не установлен"
fi
log "Все зависимости найдены"
}
# Функция проверки переменных окружения
check_env() {
log "Проверка переменных окружения..."
if [ -z "$GITEA_SERVER" ]; then
error "GITEA_SERVER не установлен"
fi
if [ -z "$GITEA_TOKEN" ]; then
error "GITEA_TOKEN не установлен"
fi
if [ -z "$GITEA_OWNER" ]; then
error "GITEA_OWNER не установлен"
fi
log "Переменные окружения проверены"
}
# Функция получения версии
get_version() {
if [ -n "$1" ]; then
VERSION="$1"
elif [ -f "VERSION" ]; then
VERSION=$(cat VERSION)
else
VERSION=$(git describe --tags --abbrev=0 2>/dev/null || echo "v1.0.0")
fi
# Добавляем префикс v если его нет
if [[ ! $VERSION =~ ^v ]]; then
VERSION="v$VERSION"
fi
log "Версия релиза: $VERSION"
}
# Функция проверки git статуса
check_git_status() {
log "Проверка состояния git..."
# Проверяем что мы в git репозитории
if ! git rev-parse --git-dir > /dev/null 2>&1; then
error "Не найден git репозиторий"
fi
# Проверяем что нет незафиксированных изменений
if ! git diff-index --quiet HEAD --; then
warn "Есть незафиксированные изменения"
read -p "Продолжить? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
# Проверяем что мы на master/main ветке
CURRENT_BRANCH=$(git branch --show-current)
if [[ "$CURRENT_BRANCH" != "master" && "$CURRENT_BRANCH" != "main" ]]; then
warn "Вы не на master/main ветке (текущая: $CURRENT_BRANCH)"
read -p "Продолжить? (y/N): " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi
}
# Функция запуска тестов
run_tests() {
log "Запуск тестов..."
if ! go test ./...; then
error "Тесты не прошли"
fi
log "Все тесты прошли успешно"
}
# Функция создания тега
create_tag() {
log "Создание тега $VERSION..."
# Проверяем что тег еще не существует
if git rev-parse "$VERSION" >/dev/null 2>&1; then
warn "Тег $VERSION уже существует"
read -p "Перезаписать? (y/N): " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
git tag -d "$VERSION"
else
exit 1
fi
fi
# Создаем аннотированный тег
RELEASE_NOTES="Release $VERSION
✨ Новые возможности:
- Обновления и улучшения интерфейса
- Оптимизация производительности
🐛 Исправления:
- Различные багфиксы и улучшения стабильности
📦 Поддерживаемые платформы:
- Windows (64-bit)
- Linux (64-bit, ARM64)
- macOS (Intel 64-bit, Apple Silicon ARM64)"
git tag -a "$VERSION" -m "$RELEASE_NOTES"
# Отправляем тег в origin
git push origin "$VERSION"
log "Тег $VERSION создан и отправлен"
}
# Функция сборки бинарников
build_binaries() {
log "Сборка бинарников для разных платформ..."
# Создаем директорию для релиза
RELEASE_DIR="$BUILD_DIR/$VERSION"
mkdir -p "$RELEASE_DIR"
# Массив платформ
platforms=(
"windows/amd64"
"linux/amd64"
"linux/arm64"
"darwin/amd64"
"darwin/arm64"
)
for platform in "${platforms[@]}"; do
IFS='/' read -r GOOS GOARCH <<< "$platform"
output="$RELEASE_DIR/${BINARY_NAME}-${VERSION}-${GOOS}-${GOARCH}"
if [ "$GOOS" = "windows" ]; then
output="${output}.exe"
fi
log "Сборка для $GOOS/$GOARCH"
# Сборка с флагами оптимизации
GOOS=$GOOS GOARCH=$GOARCH go build \
-ldflags="-s -w -X main.version=$VERSION -X main.buildTime=$(date -u '+%Y-%m-%d_%H:%M:%S')" \
-o "$output" \
cmd/main.go
if [ $? -eq 0 ]; then
log "$GOOS/$GOARCH построен успешно"
else
error "❌ Ошибка сборки для $GOOS/$GOARCH"
fi
done
}
# Функция создания архивов
create_archives() {
log "Создание архивов..."
cd "$BUILD_DIR/$VERSION"
# Windows - ZIP архивы
for file in *windows*.exe; do
if [ -f "$file" ]; then
archive="${file%.exe}.zip"
zip "$archive" "$file"
rm "$file"
log "Создан архив: $archive"
fi
done
# Linux и macOS - TAR.GZ архивы
for file in *linux* *darwin*; do
if [ -f "$file" ] && [[ ! "$file" == *.zip ]] && [[ ! "$file" == *.tar.gz ]]; then
archive="${file}.tar.gz"
tar -czf "$archive" "$file"
rm "$file"
log "Создан архив: $archive"
fi
done
cd - > /dev/null
}
# Функция создания релиза в Gitea
create_gitea_release() {
log "Создание релиза в Gitea..."
# JSON для создания релиза
RELEASE_JSON=$(cat <<EOF
{
"tag_name": "$VERSION",
"name": "PDF Compressor $VERSION",
"body": "# 🔥 PDF Compressor $VERSION\n\n## ✨ Новые возможности\n- Обновления и улучшения\n- Оптимизация производительности\n\n## 🐛 Исправления\n- Различные багфиксы\n- Улучшения стабильности\n\n## 📦 Установка\n1. Скачайте архив для вашей платформы\n2. Распакуйте и запустите\n\n## 📖 Документация\nПолная документация доступна в README.md",
"draft": false,
"prerelease": false
}
EOF
)
# Создаем релиз через API
RESPONSE=$(curl -s -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d "$RELEASE_JSON" \
"$GITEA_SERVER/api/v1/repos/$GITEA_OWNER/$GITEA_REPO/releases")
# Получаем ID релиза
RELEASE_ID=$(echo "$RESPONSE" | grep -o '"id":[0-9]*' | cut -d':' -f2 | head -n1)
if [ -z "$RELEASE_ID" ]; then
error "Не удалось создать релиз. Ответ: $RESPONSE"
fi
log "Релиз создан с ID: $RELEASE_ID"
# Загружаем архивы
log "Загрузка архивов..."
for archive in "$BUILD_DIR/$VERSION"/*; do
if [ -f "$archive" ]; then
filename=$(basename "$archive")
log "Загрузка $filename..."
curl -s -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-F "attachment=@$archive" \
"$GITEA_SERVER/api/v1/repos/$GITEA_OWNER/$GITEA_REPO/releases/$RELEASE_ID/assets"
if [ $? -eq 0 ]; then
log "$filename загружен"
else
warn "❌ Ошибка загрузки $filename"
fi
fi
done
}
# Функция очистки
cleanup() {
log "Очистка временных файлов..."
# Здесь можно добавить очистку при необходимости
}
# Функция показа справки
show_help() {
echo -e "${BLUE}Скрипт генерации релиза PDF Compressor${NC}"
echo ""
echo "Использование: $0 [версия]"
echo ""
echo "Параметры:"
echo " версия Версия релиза (например: v1.2.0)"
echo " Если не указана, используется VERSION файл или последний git тег"
echo ""
echo "Переменные окружения:"
echo " GITEA_SERVER URL Gitea сервера"
echo " GITEA_TOKEN Токен доступа Gitea"
echo " GITEA_OWNER Владелец репозитория"
echo ""
echo "Примеры:"
echo " $0 # Автоматическое определение версии"
echo " $0 v1.2.0 # Конкретная версия"
echo ""
}
# Основная функция
main() {
echo -e "${BLUE}🚀 PDF Compressor Release Generator${NC}"
echo ""
# Обработка аргументов
case "${1:-}" in
-h|--help|help)
show_help
exit 0
;;
esac
# Основной процесс
check_dependencies
check_env
get_version "$1"
check_git_status
run_tests
create_tag
build_binaries
create_archives
create_gitea_release
cleanup
log "🎉 Релиз $VERSION успешно создан!"
echo ""
echo -e "${GREEN}Релиз доступен по адресу:${NC}"
echo "$GITEA_SERVER/$GITEA_OWNER/$GITEA_REPO/releases/tag/$VERSION"
echo ""
}
# Обработка сигналов
trap cleanup EXIT
# Запуск основной функции
main "$@"

90
scripts/release.sh Normal file
View File

@@ -0,0 +1,90 @@
#!/bin/bash
# Скрипт для создания релиза PDF Compressor в Gitea
# Использование: ./scripts/release.sh v1.0.0
set -e
VERSION=$1
if [ -z "$VERSION" ]; then
echo "Использование: $0 <version>"
echo "Пример: $0 v1.0.0"
exit 1
fi
echo "🚀 Создание релиза $VERSION для PDF Compressor"
# Проверяем что мы в правильной директории
if [ ! -f "go.mod" ]; then
echo "❌ Ошибка: Запустите скрипт из корня проекта"
exit 1
fi
# Проверяем что все изменения закоммичены
if [ -n "$(git status --porcelain)" ]; then
echo "❌ Ошибка: Есть незакоммиченные изменения"
git status
exit 1
fi
# Запускаем тесты
echo "🧪 Запуск тестов..."
go test ./... || {
echo "❌ Тесты не прошли"
exit 1
}
# Собираем для разных платформ
echo "🔨 Сборка бинарников..."
mkdir -p releases
# Windows
GOOS=windows GOARCH=amd64 go build -ldflags="-s -w" -o releases/pdf-compressor-${VERSION}-windows-amd64.exe cmd/main.go
# Linux
GOOS=linux GOARCH=amd64 go build -ldflags="-s -w" -o releases/pdf-compressor-${VERSION}-linux-amd64 cmd/main.go
# macOS
GOOS=darwin GOARCH=amd64 go build -ldflags="-s -w" -o releases/pdf-compressor-${VERSION}-darwin-amd64 cmd/main.go
# ARM64 versions
GOOS=linux GOARCH=arm64 go build -ldflags="-s -w" -o releases/pdf-compressor-${VERSION}-linux-arm64 cmd/main.go
GOOS=darwin GOARCH=arm64 go build -ldflags="-s -w" -o releases/pdf-compressor-${VERSION}-darwin-arm64 cmd/main.go
# Создаем архивы
echo "📦 Создание архивов..."
cd releases
# Windows
zip pdf-compressor-${VERSION}-windows-amd64.zip pdf-compressor-${VERSION}-windows-amd64.exe
rm pdf-compressor-${VERSION}-windows-amd64.exe
# Linux
tar -czf pdf-compressor-${VERSION}-linux-amd64.tar.gz pdf-compressor-${VERSION}-linux-amd64
rm pdf-compressor-${VERSION}-linux-amd64
# macOS
tar -czf pdf-compressor-${VERSION}-darwin-amd64.tar.gz pdf-compressor-${VERSION}-darwin-amd64
rm pdf-compressor-${VERSION}-darwin-amd64
# ARM64
tar -czf pdf-compressor-${VERSION}-linux-arm64.tar.gz pdf-compressor-${VERSION}-linux-arm64
rm pdf-compressor-${VERSION}-linux-arm64
tar -czf pdf-compressor-${VERSION}-darwin-arm64.tar.gz pdf-compressor-${VERSION}-darwin-arm64
rm pdf-compressor-${VERSION}-darwin-arm64
cd ..
# Создаем и пушим тег
echo "🏷️ Создание тега..."
git tag -a "$VERSION" -m "Release $VERSION"
git push origin "$VERSION"
echo "✅ Релиз подготовлен!"
echo "📁 Файлы релиза находятся в папке releases/"
echo "🌐 Теперь создайте релиз в Gitea веб-интерфейсе:"
echo " 1. Перейдите в ваш репозиторий в Gitea"
echo " 2. Нажмите 'Releases' → 'New Release'"
echo " 3. Выберите тег: $VERSION"
echo " 4. Загрузите файлы из папки releases/"