From 69b0d9a9a80b597c9d167c81a6d4d362163a4dc3 Mon Sep 17 00:00:00 2001 From: Fadhli Azhari Date: Tue, 28 Apr 2026 12:53:04 +0800 Subject: [PATCH] build: add build script for manual process --- build-and-push.ps1 | 110 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 build-and-push.ps1 diff --git a/build-and-push.ps1 b/build-and-push.ps1 new file mode 100644 index 0000000..abc39c3 --- /dev/null +++ b/build-and-push.ps1 @@ -0,0 +1,110 @@ +#Requires -Version 5.1 +<# +.SYNOPSIS + Build and push a CI image to the Harbor registry using podman. + +.EXAMPLE + .\build-and-push.ps1 -Image ci/java-builder +#> +[CmdletBinding()] +param( + [Parameter(Mandatory = $true)] + [string]$Image, + + [Parameter(Mandatory = $false)] + [string]$Version +) + +$ErrorActionPreference = 'Stop' + +# --- Load .env --- +$envFile = Join-Path $PSScriptRoot '.env' +if (-not (Test-Path $envFile)) { throw ".env not found at $envFile" } + +Get-Content $envFile | ForEach-Object { + if ($_ -match '^\s*([^#=\s]+)\s*=\s*(.*?)\s*$') { + $value = $matches[2].TrimEnd("`r") + if ($value.StartsWith('"') -and $value.EndsWith('"')) { $value = $value.Substring(1, $value.Length - 2) } + elseif ($value.StartsWith("'") -and $value.EndsWith("'")) { $value = $value.Substring(1, $value.Length - 2) } + [Environment]::SetEnvironmentVariable($matches[1], $value) + } +} + +foreach ($v in 'REGISTRY', 'REGISTRY_USER', 'REGISTRY_PASS') { + if (-not (Get-Item "env:$v" -ErrorAction SilentlyContinue).Value) { + throw "$v not set in .env" + } +} + +# --- Resolve paths --- +# $Image is the path to the image directory relative to the repo root, and +# also the image name pushed to the registry (e.g. "ci/java-builder"). +$regHost = $env:REGISTRY -replace '^https?://', '' -replace '/$', '' +$imageName = ($Image -replace '\\', '/').Trim('/') +$imageDir = Join-Path $PSScriptRoot ($imageName -replace '/', [IO.Path]::DirectorySeparatorChar) +if (-not (Test-Path $imageDir)) { throw "Image directory not found: $imageDir" } + +$repo = "$regHost/kollect-tools/$imageName" +$date = Get-Date -Format 'yyyyMMdd' + +# --- Resolve version --- +# If -Version isn't given, parse the Dockerfile: find the variable referenced +# in the FROM line and read its ARG default (e.g. JAVA_VERSION=25 -> "25"). +if (-not $Version) { + $dockerfile = Join-Path $imageDir 'Dockerfile' + $content = Get-Content $dockerfile -Raw + if ($content -match '(?m)^\s*FROM\s+\S*?\$\{(\w+)\}') { + $varName = $matches[1] + if ($content -match "(?m)^\s*ARG\s+$varName\s*=\s*`"?([^`"\s]+)`"?") { + $Version = $matches[1] + } + } + if (-not $Version) { + throw "Could not auto-detect version from $dockerfile. Pass -Version explicitly." + } + Write-Host "=> Auto-detected version: $Version (from $varName)" +} + +$tags = @('latest', $Version, $date) + +# --- Login --- +# Use .NET Process so stdin gets the raw password with no trailing newline +# (PowerShell's native pipe appends CRLF, which breaks --password-stdin). +Write-Host "=> Logging in to $regHost" +$psi = New-Object System.Diagnostics.ProcessStartInfo +$psi.FileName = 'podman' +$psi.Arguments = "login $regHost --username `"$($env:REGISTRY_USER)`" --password-stdin" +$psi.RedirectStandardInput = $true +$psi.UseShellExecute = $false +$proc = [System.Diagnostics.Process]::Start($psi) +$proc.StandardInput.Write($env:REGISTRY_PASS) +$proc.StandardInput.Close() +$proc.WaitForExit() +if ($proc.ExitCode -ne 0) { throw "podman login failed (exit $($proc.ExitCode))" } + +# --- Build --- +Write-Host "=> Building ${repo}:latest" +$buildArgs = @('build', '-t', "${repo}:latest") +if ($env:NVD_API_KEY) { + $buildArgs += @('--build-arg', "NVD_API_KEY=$env:NVD_API_KEY") +} +$buildArgs += $imageDir + +& podman @buildArgs +if ($LASTEXITCODE -ne 0) { throw "podman build failed" } + +# --- Tag --- +foreach ($tag in $Version, $date) { + Write-Host "=> Tagging ${repo}:$tag" + podman tag "${repo}:latest" "${repo}:$tag" + if ($LASTEXITCODE -ne 0) { throw "podman tag failed for $tag" } +} + +# --- Push --- +foreach ($tag in $tags) { + Write-Host "=> Pushing ${repo}:$tag" + podman push "${repo}:$tag" + if ($LASTEXITCODE -ne 0) { throw "podman push failed for $tag" } +} + +Write-Host "Done. Pushed $($tags.Count) tags to $repo"