Enhance branding and release workflows
- Updated README.md to include a reference to branding and releases documentation. - Modified brand_config.py to support multi-brand packaging, including functions for collecting local release data and merging release manifests. - Adjusted build_macos.sh to set a default brand if none is specified and updated DMG naming conventions. - Enhanced create_release.ps1 and create_release.sh scripts to support dry-run functionality and improved artifact handling. - Added a new template for brand configuration in build/brands/template.jsonc. - Created comprehensive branding and releases documentation in docs/BRANDING_AND_RELEASES.md. - Added unit tests for new branding functionalities in test_brand_config.py.
This commit is contained in:
parent
fd69996c53
commit
67bfe4a600
8 changed files with 923 additions and 82 deletions
|
|
@ -3,7 +3,7 @@ param(
|
|||
[string]$Version,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string[]]$Brands = @("agravity"),
|
||||
[string[]]$Brands,
|
||||
|
||||
[Parameter(Mandatory = $false)]
|
||||
[string]$ForgejoUser,
|
||||
|
|
@ -12,6 +12,7 @@ param(
|
|||
[string]$ForgejoPW,
|
||||
|
||||
[switch]$ClearCredentials,
|
||||
[switch]$DryRun,
|
||||
|
||||
[string]$ForgejoUrl = "https://git.him-tools.de",
|
||||
[string]$Repo = "HIM-public/webdrop-bridge"
|
||||
|
|
@ -26,11 +27,32 @@ if (-not (Test-Path $pythonExe)) {
|
|||
|
||||
$brandHelper = Join-Path $projectRoot "build\scripts\brand_config.py"
|
||||
$manifestOutput = Join-Path $projectRoot "build\dist\release-manifest.json"
|
||||
$localManifestPath = Join-Path $projectRoot "build\dist\release-manifest.local.json"
|
||||
$existingManifestPath = Join-Path $projectRoot "build\dist\release-manifest.existing.json"
|
||||
|
||||
function Get-CurrentVersion {
|
||||
return (& $pythonExe -c "from pathlib import Path; import sys; sys.path.insert(0, str(Path(r'$projectRoot/build/scripts').resolve())); from version_utils import get_current_version; print(get_current_version())").Trim()
|
||||
}
|
||||
|
||||
function Get-LocalReleaseData {
|
||||
$arguments = @($brandHelper, "local-release-data", "--platform", "windows", "--version", $Version)
|
||||
if ($Brands) {
|
||||
$arguments += "--brands"
|
||||
$arguments += $Brands
|
||||
}
|
||||
return (& $pythonExe @arguments | ConvertFrom-Json)
|
||||
}
|
||||
|
||||
function Get-AssetMap {
|
||||
param([object[]]$Assets)
|
||||
|
||||
$map = @{}
|
||||
foreach ($asset in ($Assets | Where-Object { $_ })) {
|
||||
$map[$asset.name] = $asset
|
||||
}
|
||||
return $map
|
||||
}
|
||||
|
||||
if ($ClearCredentials) {
|
||||
Remove-Item env:FORGEJO_USER -ErrorAction SilentlyContinue
|
||||
Remove-Item env:FORGEJO_PASS -ErrorAction SilentlyContinue
|
||||
|
|
@ -38,6 +60,44 @@ if ($ClearCredentials) {
|
|||
exit 0
|
||||
}
|
||||
|
||||
if (-not $Version) {
|
||||
$Version = Get-CurrentVersion
|
||||
}
|
||||
|
||||
$localData = Get-LocalReleaseData
|
||||
$artifactPaths = New-Object System.Collections.Generic.List[string]
|
||||
|
||||
foreach ($artifact in $localData.artifacts) {
|
||||
$artifactPaths.Add([string]$artifact)
|
||||
if ((Test-Path $artifact) -and ((Get-Item $artifact).Extension -eq ".msi")) {
|
||||
$msiSize = (Get-Item $artifact).Length / 1MB
|
||||
Write-Host "Windows artifact: $([System.IO.Path]::GetFileName($artifact)) ($([math]::Round($msiSize, 2)) MB)"
|
||||
}
|
||||
}
|
||||
|
||||
if ($artifactPaths.Count -eq 0) {
|
||||
Write-Host "ERROR: No local Windows artifacts found" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
$localData.manifest | ConvertTo-Json -Depth 10 | Set-Content -Path $localManifestPath -Encoding utf8
|
||||
|
||||
if ($DryRun) {
|
||||
Copy-Item $localManifestPath $manifestOutput -Force
|
||||
$brandsText = if ($localData.brands.Count -gt 0) { $localData.brands -join ", " } else { "<none>" }
|
||||
|
||||
Write-Host "[DRY RUN] No network requests or uploads will be performed." -ForegroundColor Yellow
|
||||
Write-Host "[DRY RUN] Release tag: v$Version"
|
||||
Write-Host "[DRY RUN] Release URL: $ForgejoUrl/$Repo/releases/tag/v$Version"
|
||||
Write-Host "[DRY RUN] Discovered brands: $brandsText"
|
||||
Write-Host "[DRY RUN] Artifacts that would be uploaded:"
|
||||
foreach ($artifact in $artifactPaths) {
|
||||
Write-Host " - $artifact"
|
||||
}
|
||||
Write-Host "[DRY RUN] Local manifest preview: $manifestOutput"
|
||||
exit 0
|
||||
}
|
||||
|
||||
if (-not $ForgejoUser) {
|
||||
$ForgejoUser = $env:FORGEJO_USER
|
||||
}
|
||||
|
|
@ -58,36 +118,6 @@ if (-not $ForgejoUser -or -not $ForgejoPW) {
|
|||
$env:FORGEJO_PASS = $ForgejoPW
|
||||
}
|
||||
|
||||
if (-not $Version) {
|
||||
$Version = Get-CurrentVersion
|
||||
}
|
||||
|
||||
$artifactPaths = New-Object System.Collections.Generic.List[string]
|
||||
foreach ($brand in $Brands) {
|
||||
$brandJson = & $pythonExe $brandHelper show --brand $brand | ConvertFrom-Json
|
||||
$msiPath = Join-Path $projectRoot "build\dist\windows\$($brandJson.brand_id)\$($brandJson.asset_prefix)-$Version-win-x64.msi"
|
||||
$checksumPath = "$msiPath.sha256"
|
||||
|
||||
if (Test-Path $msiPath) {
|
||||
$artifactPaths.Add($msiPath)
|
||||
if (Test-Path $checksumPath) {
|
||||
$artifactPaths.Add($checksumPath)
|
||||
}
|
||||
$msiSize = (Get-Item $msiPath).Length / 1MB
|
||||
Write-Host "Windows artifact: $([System.IO.Path]::GetFileName($msiPath)) ($([math]::Round($msiSize, 2)) MB)"
|
||||
}
|
||||
}
|
||||
|
||||
& $pythonExe $brandHelper release-manifest --version $Version --output $manifestOutput --brands $Brands | Out-Null
|
||||
if (Test-Path $manifestOutput) {
|
||||
$artifactPaths.Add($manifestOutput)
|
||||
}
|
||||
|
||||
if ($artifactPaths.Count -eq 0) {
|
||||
Write-Host "ERROR: No Windows artifacts found for the requested brands" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
$auth = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("${ForgejoUser}:${ForgejoPW}"))
|
||||
$headers = @{
|
||||
"Authorization" = "Basic $auth"
|
||||
|
|
@ -105,28 +135,46 @@ $releaseData = @{
|
|||
} | ConvertTo-Json
|
||||
|
||||
try {
|
||||
$lookupResponse = Invoke-WebRequest -Uri $releaseLookupUrl -Method GET -Headers $headers -TimeoutSec 30 -UseBasicParsing -ErrorAction Stop
|
||||
$releaseInfo = $lookupResponse.Content | ConvertFrom-Json
|
||||
$releaseInfo = Invoke-RestMethod -Uri $releaseLookupUrl -Method GET -Headers $headers -TimeoutSec 30 -ErrorAction Stop
|
||||
$releaseId = $releaseInfo.id
|
||||
Write-Host "[OK] Using existing release (ID: $releaseId)" -ForegroundColor Green
|
||||
}
|
||||
catch {
|
||||
$response = Invoke-WebRequest -Uri $releaseUrl -Method POST -Headers $headers -Body $releaseData -TimeoutSec 30 -UseBasicParsing -ErrorAction Stop
|
||||
$releaseInfo = $response.Content | ConvertFrom-Json
|
||||
$releaseInfo = Invoke-RestMethod -Uri $releaseUrl -Method POST -Headers $headers -Body $releaseData -TimeoutSec 30 -ErrorAction Stop
|
||||
$releaseId = $releaseInfo.id
|
||||
Write-Host "[OK] Release created (ID: $releaseId)" -ForegroundColor Green
|
||||
}
|
||||
|
||||
$assetMap = Get-AssetMap -Assets $releaseInfo.assets
|
||||
if ($assetMap.ContainsKey("release-manifest.json")) {
|
||||
Invoke-WebRequest -Uri $assetMap["release-manifest.json"].browser_download_url -Method GET -Headers $headers -TimeoutSec 30 -OutFile $existingManifestPath | Out-Null
|
||||
|
||||
& $pythonExe $brandHelper merge-manifests --base $existingManifestPath --overlay $localManifestPath --output $manifestOutput | Out-Null
|
||||
}
|
||||
else {
|
||||
Copy-Item $localManifestPath $manifestOutput -Force
|
||||
}
|
||||
|
||||
$artifactPaths.Add($manifestOutput)
|
||||
$assetMap = Get-AssetMap -Assets $releaseInfo.assets
|
||||
|
||||
$curlAuth = "$ForgejoUser`:$ForgejoPW"
|
||||
$uploadUrl = "$ForgejoUrl/api/v1/repos/$Repo/releases/$releaseId/assets"
|
||||
|
||||
foreach ($artifact in $artifactPaths) {
|
||||
$assetName = [System.IO.Path]::GetFileName($artifact)
|
||||
if ($assetMap.ContainsKey($assetName)) {
|
||||
$existingAsset = $assetMap[$assetName]
|
||||
Invoke-RestMethod -Uri "$ForgejoUrl/api/v1/repos/$Repo/releases/$releaseId/assets/$($existingAsset.id)" -Method DELETE -Headers $headers -TimeoutSec 30 | Out-Null
|
||||
Write-Host "[OK] Replaced existing asset $assetName" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
$response = curl.exe -s -X POST -u $curlAuth -F "attachment=@$artifact" $uploadUrl
|
||||
if ($response -like "*error*" -or $response -like "*404*") {
|
||||
Write-Host "WARNING: Could not upload $artifact : $response" -ForegroundColor Yellow
|
||||
}
|
||||
else {
|
||||
Write-Host "[OK] Uploaded $([System.IO.Path]::GetFileName($artifact))" -ForegroundColor Green
|
||||
Write-Host "[OK] Uploaded $assetName" -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue