docs(changelog): add v0.1.1.3 download and SHA256 links; add release automation scripts (upload/prune/manage/checksums)
This commit is contained in:
30
scripts/collect_binaries.ps1
Normal file
30
scripts/collect_binaries.ps1
Normal file
@ -0,0 +1,30 @@
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$OutDir
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
New-Item -ItemType Directory -Force -Path $OutDir | Out-Null
|
||||
|
||||
$items = @(
|
||||
@{ Path = 'build/Release/privatebinapi.dll'; Optional = $false }
|
||||
@{ Path = 'build/Release/privatebinapi.lib'; Optional = $true }
|
||||
@{ Path = 'build/Release/privatebinapi.pdb'; Optional = $true }
|
||||
@{ Path = 'build/example/Release/example.exe'; Optional = $true }
|
||||
)
|
||||
|
||||
foreach ($it in $items) {
|
||||
$p = Resolve-Path -LiteralPath $it.Path -ErrorAction SilentlyContinue
|
||||
if ($null -ne $p) {
|
||||
Copy-Item -LiteralPath $p.Path -Destination $OutDir -Force
|
||||
Write-Host ("Collected: " + [IO.Path]::GetFileName($p.Path))
|
||||
} elseif (-not $it.Optional) {
|
||||
throw "Required artifact not found: $($it.Path)"
|
||||
} else {
|
||||
Write-Host ("Skip missing optional: " + $it.Path)
|
||||
}
|
||||
}
|
||||
|
||||
Get-ChildItem -LiteralPath $OutDir -File | Format-Table Name,Length -AutoSize
|
||||
|
||||
|
||||
35
scripts/gen_checksums.ps1
Normal file
35
scripts/gen_checksums.ps1
Normal file
@ -0,0 +1,35 @@
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$ZipPath,
|
||||
[Parameter(Mandatory=$true)][string]$BinDir
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
if (-not (Test-Path -LiteralPath $ZipPath)) {
|
||||
throw "ZIP not found: $ZipPath"
|
||||
}
|
||||
|
||||
if (-not (Test-Path -LiteralPath $BinDir)) {
|
||||
throw "BinDir not found: $BinDir"
|
||||
}
|
||||
|
||||
function Write-ChecksumFile {
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$Path
|
||||
)
|
||||
$hash = (Get-FileHash -Algorithm SHA256 -LiteralPath $Path).Hash.ToLower()
|
||||
$outfile = "$Path.sha256"
|
||||
$line = "$hash $([System.IO.Path]::GetFileName($Path))"
|
||||
Set-Content -Path $outfile -NoNewline -Encoding ASCII -Value $line
|
||||
Write-Host "Wrote $outfile"
|
||||
}
|
||||
|
||||
# ZIP checksum
|
||||
Write-ChecksumFile -Path $ZipPath
|
||||
|
||||
# Binaries checksums
|
||||
Get-ChildItem -LiteralPath $BinDir -File | ForEach-Object {
|
||||
Write-ChecksumFile -Path $_.FullName
|
||||
}
|
||||
|
||||
|
||||
43
scripts/gitea_upload.ps1
Normal file
43
scripts/gitea_upload.ps1
Normal file
@ -0,0 +1,43 @@
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$Server,
|
||||
[Parameter(Mandatory=$true)][string]$Owner,
|
||||
[Parameter(Mandatory=$true)][string]$Repo,
|
||||
[Parameter(Mandatory=$true)][string]$Token,
|
||||
[Parameter(Mandatory=$true)][string]$ZipPath
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
if (-not (Test-Path -LiteralPath $ZipPath)) {
|
||||
throw "ZIP not found: $ZipPath"
|
||||
}
|
||||
|
||||
$headers = @{ Authorization = "token $Token" }
|
||||
|
||||
$latestUrl = "$Server/api/v1/repos/$Owner/$Repo/releases/latest"
|
||||
$latest = Invoke-RestMethod -Headers $headers -Method GET -Uri $latestUrl
|
||||
if (-not $latest -or -not $latest.id) {
|
||||
throw "Failed to get latest release from $latestUrl"
|
||||
}
|
||||
|
||||
$rid = [string]$latest.id
|
||||
$name = [System.IO.Path]::GetFileName($ZipPath)
|
||||
$escapedName = [System.Uri]::EscapeDataString($name)
|
||||
$uploadUrl = "$Server/api/v1/repos/$Owner/$Repo/releases/$rid/assets?name=$escapedName"
|
||||
|
||||
Write-Host "Latest release id: $rid"
|
||||
Write-Host "Uploading $name to $uploadUrl"
|
||||
|
||||
# Use Invoke-WebRequest multipart form upload
|
||||
$form = @{ attachment = Get-Item -LiteralPath $ZipPath }
|
||||
$resp = Invoke-WebRequest -Headers $headers -Method Post -Uri $uploadUrl -Form $form
|
||||
|
||||
if ($resp.StatusCode -ge 200 -and $resp.StatusCode -lt 300) {
|
||||
Write-Host "Upload successful (HTTP $($resp.StatusCode))"
|
||||
} else {
|
||||
Write-Host "Upload failed (HTTP $($resp.StatusCode))" -ForegroundColor Red
|
||||
if ($resp.Content) { Write-Host $resp.Content }
|
||||
exit 1
|
||||
}
|
||||
|
||||
|
||||
45
scripts/gitea_upload_all.ps1
Normal file
45
scripts/gitea_upload_all.ps1
Normal file
@ -0,0 +1,45 @@
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$Server,
|
||||
[Parameter(Mandatory=$true)][string]$Owner,
|
||||
[Parameter(Mandatory=$true)][string]$Repo,
|
||||
[Parameter(Mandatory=$true)][string]$Token,
|
||||
[Parameter(Mandatory=$true)][string]$Directory
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
if (-not (Test-Path -LiteralPath $Directory)) {
|
||||
throw "Directory not found: $Directory"
|
||||
}
|
||||
|
||||
$headers = @{ Authorization = "token $Token" }
|
||||
|
||||
$latestUrl = "$Server/api/v1/repos/$Owner/$Repo/releases/latest"
|
||||
$latest = Invoke-RestMethod -Headers $headers -Method GET -Uri $latestUrl
|
||||
if (-not $latest -or -not $latest.id) {
|
||||
throw "Failed to get latest release from $latestUrl"
|
||||
}
|
||||
$rid = [string]$latest.id
|
||||
Write-Host "Latest release id: $rid"
|
||||
|
||||
$files = Get-ChildItem -LiteralPath $Directory -Recurse -File
|
||||
if (-not $files) {
|
||||
Write-Host "No files to upload in $Directory"
|
||||
exit 0
|
||||
}
|
||||
|
||||
foreach ($f in $files) {
|
||||
$name = $f.Name
|
||||
$escapedName = [System.Uri]::EscapeDataString($name)
|
||||
$uploadUrl = "$Server/api/v1/repos/$Owner/$Repo/releases/$rid/assets?name=$escapedName"
|
||||
Write-Host "Uploading $name ..."
|
||||
try {
|
||||
$resp = Invoke-WebRequest -Headers $headers -Method Post -Uri $uploadUrl -Form @{ attachment = $f }
|
||||
Write-Host " OK ($($resp.StatusCode))"
|
||||
}
|
||||
catch {
|
||||
Write-Host " FAIL: $name -> $($_.Exception.Message)" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
89
scripts/manage_release.ps1
Normal file
89
scripts/manage_release.ps1
Normal file
@ -0,0 +1,89 @@
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$Server,
|
||||
[Parameter(Mandatory=$true)][string]$Owner,
|
||||
[Parameter(Mandatory=$true)][string]$Repo,
|
||||
[Parameter(Mandatory=$true)][string]$Token
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
$headers = @{ Authorization = "token $Token" }
|
||||
|
||||
# Get latest release
|
||||
$latest = Invoke-RestMethod -Headers $headers -Method GET -Uri "$Server/api/v1/repos/$Owner/$Repo/releases/latest"
|
||||
if (-not $latest -or -not $latest.id) {
|
||||
throw "Failed to get latest release"
|
||||
}
|
||||
$rid = [string]$latest.id
|
||||
Write-Host "Operating on release id: $rid"
|
||||
|
||||
# Load full release including attachments/assets list
|
||||
$release = Invoke-RestMethod -Headers $headers -Method GET -Uri "$Server/api/v1/repos/$Owner/$Repo/releases/$rid"
|
||||
$assets = $release.assets
|
||||
if (-not $assets) { $assets = $release.attachments }
|
||||
|
||||
if ($assets) {
|
||||
$groups = $assets | Group-Object -Property name
|
||||
foreach ($g in $groups) {
|
||||
$sorted = $g.Group | Sort-Object -Property id -Descending
|
||||
if ($sorted.Count -gt 1) {
|
||||
$keep = $sorted[0]
|
||||
foreach ($extra in $sorted[1..($sorted.Count-1)]) {
|
||||
if ($null -ne $extra -and $extra.id -ne $keep.id) {
|
||||
$delUrl = "$Server/api/v1/repos/$Owner/$Repo/releases/assets/$($extra.id)"
|
||||
try {
|
||||
Invoke-RestMethod -Headers $headers -Method DELETE -Uri $delUrl | Out-Null
|
||||
Write-Host ("Deleted duplicate asset: " + $extra.name + " (id=" + $extra.id + ")")
|
||||
} catch {
|
||||
Write-Host ("Failed to delete asset id=" + $extra.id + ": " + $_.Exception.Message) -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Write-Host 'No assets found on release.'
|
||||
}
|
||||
|
||||
# Compose release notes with known checksums if they exist locally
|
||||
$zipShaPath = (Resolve-Path 'dist\lib-privatebin-v0.1.1.3-windows-x64.zip.sha256' -ErrorAction SilentlyContinue)
|
||||
$dllShaPath = (Resolve-Path 'dist\windows_bin\privatebinapi.dll.sha256' -ErrorAction SilentlyContinue)
|
||||
$libShaPath = (Resolve-Path 'dist\windows_bin\privatebinapi.lib.sha256' -ErrorAction SilentlyContinue)
|
||||
$exeShaPath = (Resolve-Path 'dist\windows_bin\example.exe.sha256' -ErrorAction SilentlyContinue)
|
||||
|
||||
$lines = @('# Downloadable artifacts', '')
|
||||
$lines += ("- [lib-privatebin-v0.1.1.3-windows-x64.zip]($Server/$Owner/$Repo/releases/download/$tag/lib-privatebin-v0.1.1.3-windows-x64.zip)")
|
||||
$lines += ("- [privatebinapi.dll]($Server/$Owner/$Repo/releases/download/$tag/privatebinapi.dll)")
|
||||
$lines += ("- [privatebinapi.lib]($Server/$Owner/$Repo/releases/download/$tag/privatebinapi.lib)")
|
||||
$lines += ("- [example.exe]($Server/$Owner/$Repo/releases/download/$tag/example.exe)")
|
||||
$lines += ''
|
||||
$lines += '# SHA256 checksums'
|
||||
if ($zipShaPath) { $lines += ("- [lib-privatebin-v0.1.1.3-windows-x64.zip.sha256]($Server/$Owner/$Repo/releases/download/$tag/lib-privatebin-v0.1.1.3-windows-x64.zip.sha256)") }
|
||||
if ($dllShaPath) { $lines += ("- [privatebinapi.dll.sha256]($Server/$Owner/$Repo/releases/download/$tag/privatebinapi.dll.sha256)") }
|
||||
if ($libShaPath) { $lines += ("- [privatebinapi.lib.sha256]($Server/$Owner/$Repo/releases/download/$tag/privatebinapi.lib.sha256)") }
|
||||
if ($exeShaPath) { $lines += ("- [example.exe.sha256]($Server/$Owner/$Repo/releases/download/$tag/example.exe.sha256)") }
|
||||
|
||||
$lines += ''
|
||||
$lines += '# Changes'
|
||||
try {
|
||||
$changelog = Get-Content -Raw -LiteralPath 'CHANGELOG.md'
|
||||
$sections = $changelog -split "\r?\n## "
|
||||
$section = $sections | Where-Object { $_ -like 'v0.1.1.3*' } | Select-Object -First 1
|
||||
if ($section) {
|
||||
$secLines = $section -split "\r?\n"
|
||||
if ($secLines[0] -like 'v0.1.1.3*') { $secLines[0] = 'v0.1.1.3' }
|
||||
$lines += $secLines
|
||||
} else {
|
||||
$lines += 'See CHANGELOG.md'
|
||||
}
|
||||
} catch {
|
||||
$lines += 'See CHANGELOG.md'
|
||||
}
|
||||
|
||||
$bodyText = ($lines -join "`n")
|
||||
$payload = @{ body = $bodyText } | ConvertTo-Json -Depth 3
|
||||
|
||||
Invoke-RestMethod -Headers (@{ Authorization = ("token " + $Token); 'Content-Type' = 'application/json' }) -Method PATCH -Uri "$Server/api/v1/repos/$Owner/$Repo/releases/$rid" -Body $payload | Out-Null
|
||||
Write-Host 'Release notes updated.'
|
||||
|
||||
|
||||
76
scripts/prune_release_assets.ps1
Normal file
76
scripts/prune_release_assets.ps1
Normal file
@ -0,0 +1,76 @@
|
||||
param(
|
||||
[Parameter(Mandatory=$true)][string]$Server,
|
||||
[Parameter(Mandatory=$true)][string]$Owner,
|
||||
[Parameter(Mandatory=$true)][string]$Repo,
|
||||
[Parameter(Mandatory=$true)][string]$Token
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$headers = @{ Authorization = "token $Token" }
|
||||
|
||||
$latest = Invoke-RestMethod -Headers $headers -Method GET -Uri "$Server/api/v1/repos/$Owner/$Repo/releases/latest"
|
||||
if (-not $latest -or -not $latest.id) { throw 'Failed to get latest release' }
|
||||
$rid = [string]$latest.id
|
||||
$tag = $latest.tag_name
|
||||
Write-Host "Pruning assets on release id=$rid (tag=$tag)"
|
||||
|
||||
$release = Invoke-RestMethod -Headers $headers -Method GET -Uri "$Server/api/v1/repos/$Owner/$Repo/releases/$rid"
|
||||
$assets = $release.assets
|
||||
if (-not $assets) { $assets = $release.attachments }
|
||||
|
||||
# Allowed asset names
|
||||
$allowed = @(
|
||||
'lib-privatebin-v0.1.1.3-windows-x64.zip',
|
||||
'lib-privatebin-v0.1.1.3-windows-x64.zip.sha256',
|
||||
'privatebinapi.dll','privatebinapi.dll.sha256',
|
||||
'privatebinapi.lib','privatebinapi.lib.sha256',
|
||||
'example.exe','example.exe.sha256'
|
||||
)
|
||||
|
||||
if ($assets) {
|
||||
foreach ($a in $assets) {
|
||||
if ($allowed -notcontains $a.name) {
|
||||
$delUrl = "$Server/api/v1/repos/$Owner/$Repo/releases/assets/$($a.id)"
|
||||
try {
|
||||
Invoke-RestMethod -Headers $headers -Method DELETE -Uri $delUrl | Out-Null
|
||||
Write-Host ("Deleted: " + $a.name)
|
||||
} catch {
|
||||
Write-Host ("Skip delete (" + $a.name + "): " + $_.Exception.Message) -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Write-Host 'No assets found.'
|
||||
}
|
||||
|
||||
# Re-fetch assets after prune
|
||||
$release = Invoke-RestMethod -Headers $headers -Method GET -Uri "$Server/api/v1/repos/$Owner/$Repo/releases/$rid"
|
||||
$assets = $release.assets; if (-not $assets) { $assets = $release.attachments }
|
||||
|
||||
# Build markdown with links
|
||||
$lines = @('# Downloadable artifacts', '')
|
||||
foreach ($name in $allowed) {
|
||||
$a = $assets | Where-Object { $_.name -eq $name } | Select-Object -First 1
|
||||
if ($a) {
|
||||
# Prefer deterministic download URL pattern
|
||||
$url = "$Server/$Owner/$Repo/releases/download/$tag/$name"
|
||||
$lines += ("- [$name]($url)")
|
||||
}
|
||||
}
|
||||
|
||||
$lines += ''
|
||||
$lines += '# SHA256 checksums'
|
||||
foreach ($name in $allowed | Where-Object { $_.EndsWith('.sha256') }) {
|
||||
$a = $assets | Where-Object { $_.name -eq $name } | Select-Object -First 1
|
||||
if ($a) {
|
||||
$url = "$Server/$Owner/$Repo/releases/download/$tag/$name"
|
||||
$lines += ("- [$name]($url)")
|
||||
}
|
||||
}
|
||||
|
||||
$bodyText = ($lines -join "`n")
|
||||
$payload = @{ body = $bodyText } | ConvertTo-Json -Depth 3
|
||||
Invoke-RestMethod -Headers (@{ Authorization = ("token " + $Token); 'Content-Type' = 'application/json' }) -Method PATCH -Uri "$Server/api/v1/repos/$Owner/$Repo/releases/$rid" -Body $payload | Out-Null
|
||||
Write-Host 'Release notes updated with links.'
|
||||
|
||||
|
||||
Reference in New Issue
Block a user