diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ba14aab..43ea9c9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -6,6 +6,8 @@ on: - master paths: - ".github/workflows/release.yml" + - "scripts/publish.ps1" + - "scripts/docker/Dockerfile.release" tags: - "*" @@ -118,41 +120,8 @@ jobs: echo "VERSION=${release_tag#v}" >> "${GITHUB_ENV}" - name: Build release assets - shell: bash - run: | - set -euo pipefail - - build_asset() { - local target_name="$1" - local rust_target="$2" - local platform="$3" - local container_binary="$4" - local output_name="$5" - local image_tag="cdxs-build:${target_name}-${GITHUB_RUN_ID:-manual}" - local container_name="cdxs-build-${target_name}-${GITHUB_RUN_ID:-manual}" - - mkdir -p dist - docker buildx build \ - --platform "${platform}" \ - --target builder \ - --build-arg "RUST_TARGET=${rust_target}" \ - --build-arg "RUST_IMAGE=${RUST_IMAGE}" \ - --build-arg "CARGO_REGISTRY=${CARGO_REGISTRY}" \ - --build-arg "APT_MIRROR=${APT_MIRROR}" \ - --load \ - -t "${image_tag}" \ - -f scripts/docker/Dockerfile.release \ - . - - local container_id - container_id="$(docker create --name "${container_name}" "${image_tag}")" - docker cp "${container_id}:/out/${container_binary}" "dist/${output_name}" - docker rm -f "${container_name}" >/dev/null - } - - build_asset windows-x64 x86_64-pc-windows-gnu linux/amd64 cdxs.exe "cdxs-${VERSION}-windows-x64.exe" - build_asset linux-x64 x86_64-unknown-linux-gnu linux/amd64 cdxs "cdxs-${VERSION}-linux-x64" - build_asset linux-arm64 aarch64-unknown-linux-gnu linux/arm64 cdxs "cdxs-${VERSION}-linux-arm64" + shell: pwsh + run: ./scripts/publish.ps1 -Version "${env:VERSION}" -RustImage "${env:RUST_IMAGE}" -CargoRegistry "${env:CARGO_REGISTRY}" -AptMirror "${env:APT_MIRROR}" -DockerWindows -Clean - name: Upload release assets shell: bash diff --git a/scripts/publish-binaries.ps1 b/scripts/publish-binaries.ps1 deleted file mode 100644 index 023978a..0000000 --- a/scripts/publish-binaries.ps1 +++ /dev/null @@ -1,107 +0,0 @@ -param( - [string]$Version = "", - [string]$OutputDir = "dist", - [ValidateSet("all", "win", "linux-x64", "linux-arm64")] - [string]$Target = "all", - [string]$RustImage = "rust:1-bookworm", - [switch]$SkipDockerLinux, - [switch]$Clean -) - -$ErrorActionPreference = "Stop" - -$repoRoot = Resolve-Path (Join-Path $PSScriptRoot "..") -Set-Location $repoRoot - -if (-not $Version) { - $cargoToml = Get-Content -Raw -Path "Cargo.toml" - if ($cargoToml -notmatch '(?m)^version\s*=\s*"([^"]+)"') { - throw "Cannot read package version from Cargo.toml" - } - $Version = $Matches[1] -} - -$dist = Join-Path $repoRoot $OutputDir -if ($Clean -and (Test-Path $dist)) { - Remove-Item -LiteralPath $dist -Recurse -Force -} -New-Item -ItemType Directory -Force -Path $dist | Out-Null - -if ($SkipDockerLinux) { - $Target = "win" -} - -function Copy-ReleaseFile { - param( - [string]$SourceFile, - [string]$OutputName - ) - - if (-not (Test-Path $SourceFile)) { - throw "Missing release binary: $SourceFile" - } - - $outputPath = Join-Path $dist $OutputName - Copy-Item -LiteralPath $SourceFile -Destination $outputPath -Force - Write-Host "Wrote $outputPath" -} - -if ($Target -eq "all" -or $Target -eq "win") { - Write-Host "Building Windows x64" - cargo build --release --target x86_64-pc-windows-msvc - Copy-ReleaseFile ` - -SourceFile (Join-Path $repoRoot "target/x86_64-pc-windows-msvc/release/cdxs.exe") ` - -OutputName "cdxs-$Version-windows-x64.exe" -} - -$linuxTargets = @( - @{ Name = "linux-x64"; RustTarget = "x86_64-unknown-linux-gnu"; Platform = "linux/amd64" }, - @{ Name = "linux-arm64"; RustTarget = "aarch64-unknown-linux-gnu"; Platform = "linux/arm64" } -) | Where-Object { $Target -eq "all" -or $Target -eq $_.Name } - -foreach ($linuxTarget in $linuxTargets) { - $containerName = "cdxs-build-$($linuxTarget.Name)-$([guid]::NewGuid().ToString('N'))" - $imageTag = "cdxs-build:$($linuxTarget.Name)" - $tmpOutDir = Join-Path $dist ".tmp-$($linuxTarget.Name)" - New-Item -ItemType Directory -Force -Path $tmpOutDir | Out-Null - - Write-Host "Building $($linuxTarget.Name) with Docker platform $($linuxTarget.Platform)" - $buildArgs = @( - "buildx", "build", - "--platform", $linuxTarget.Platform, - "--target", "builder", - "--build-arg", "RUST_TARGET=$($linuxTarget.RustTarget)", - "--build-arg", "RUST_IMAGE=$RustImage", - "--load", - "-t", $imageTag, - "-f", "scripts/docker/Dockerfile.release", - "." - ) - docker @buildArgs - if ($LASTEXITCODE -ne 0) { - throw "Docker build failed for $($linuxTarget.Name)" - } - docker image inspect $imageTag | Out-Null - if ($LASTEXITCODE -ne 0) { - throw "Docker image was not created: $imageTag" - } - $containerId = docker create --name $containerName $imageTag - if ($LASTEXITCODE -ne 0 -or -not $containerId) { - throw "Docker create failed for $imageTag" - } - try { - docker cp "${containerName}:/out/cdxs" (Join-Path $tmpOutDir "cdxs") - if ($LASTEXITCODE -ne 0) { - throw "Docker cp failed for $($linuxTarget.Name)" - } - } finally { - docker rm -f $containerName | Out-Null - } - - Copy-ReleaseFile ` - -SourceFile (Join-Path $tmpOutDir "cdxs") ` - -OutputName "cdxs-$Version-$($linuxTarget.Name)" - Remove-Item -LiteralPath $tmpOutDir -Recurse -Force -} - -Write-Host "Binary release artifacts are in $dist" diff --git a/scripts/publish-docker.ps1 b/scripts/publish-docker.ps1 deleted file mode 100644 index 033a7ba..0000000 --- a/scripts/publish-docker.ps1 +++ /dev/null @@ -1,48 +0,0 @@ -param( - [string]$Registry = "docker.pchuan.top", - [string]$ImageName = "cdxs", - [string]$Tag = "", - [switch]$NoLatest, - [string]$Platform = "" -) - -$ErrorActionPreference = "Stop" - -$repoRoot = Resolve-Path (Join-Path $PSScriptRoot "..") -Set-Location $repoRoot - -if (-not $Tag) { - $cargoToml = Get-Content -Raw -Path "Cargo.toml" - if ($cargoToml -notmatch '(?m)^version\s*=\s*"([^"]+)"') { - throw "Cannot read package version from Cargo.toml" - } - $Tag = $Matches[1] -} - -$image = "$Registry/$ImageName" -$versionTag = "${image}:$Tag" -$latestTag = "${image}:latest" - -Write-Host "Building $versionTag" -$buildArgs = @("build", "-t", $versionTag) -if (-not $NoLatest) { - $buildArgs += @("-t", $latestTag) -} -if ($Platform) { - $buildArgs += @("--platform", $Platform) -} -$buildArgs += "." -docker @buildArgs - -Write-Host "Pushing $versionTag" -docker push $versionTag - -if (-not $NoLatest) { - Write-Host "Pushing $latestTag" - docker push $latestTag -} - -Write-Host "Published $versionTag" -if (-not $NoLatest) { - Write-Host "Published $latestTag" -} diff --git a/scripts/publish.ps1 b/scripts/publish.ps1 new file mode 100644 index 0000000..f9542f8 --- /dev/null +++ b/scripts/publish.ps1 @@ -0,0 +1,133 @@ +param( + [string]$Version = "", + [string]$OutputDir = "dist", + [ValidateSet("all", "win", "linux-x64", "linux-arm64")] + [string]$Target = "all", + [string]$RustImage = "docker.m.daocloud.io/library/rust:1-bookworm", + [string]$CargoRegistry = "sparse+https://rsproxy.cn/index/", + [string]$AptMirror = "https://mirrors.ustc.edu.cn/debian", + [switch]$DockerWindows, + [switch]$Clean +) + +$ErrorActionPreference = "Stop" + +$repoRoot = Resolve-Path (Join-Path $PSScriptRoot "..") +Set-Location $repoRoot + +if (-not $Version) { + $cargoToml = Get-Content -Raw -Path "Cargo.toml" + if ($cargoToml -notmatch '(?m)^version\s*=\s*"([^"]+)"') { + throw "Cannot read package version from Cargo.toml" + } + $Version = $Matches[1] +} + +$dist = Join-Path $repoRoot $OutputDir +if ($Clean -and (Test-Path $dist)) { + Remove-Item -LiteralPath $dist -Recurse -Force +} +New-Item -ItemType Directory -Force -Path $dist | Out-Null + +function Copy-ReleaseFile { + param( + [string]$SourceFile, + [string]$OutputName + ) + + if (-not (Test-Path $SourceFile)) { + throw "Missing release binary: $SourceFile" + } + + $outputPath = Join-Path $dist $OutputName + Copy-Item -LiteralPath $SourceFile -Destination $outputPath -Force + Write-Host "Wrote $outputPath" +} + +function Build-DockerRelease { + param( + [string]$Name, + [string]$RustTarget, + [string]$Platform, + [string]$ContainerBinary = "cdxs", + [string]$OutputName = "cdxs-$Version-$Name" + ) + + $safeRunId = if ($env:GITHUB_RUN_ID) { $env:GITHUB_RUN_ID } else { [guid]::NewGuid().ToString("N") } + $imageTag = "cdxs-build:$Name-$safeRunId" + $containerName = "cdxs-build-$Name-$safeRunId" + + Write-Host "Building $Name with Docker platform $Platform" + docker buildx build ` + --platform $Platform ` + --target builder ` + --build-arg "RUST_TARGET=$RustTarget" ` + --build-arg "RUST_IMAGE=$RustImage" ` + --build-arg "CARGO_REGISTRY=$CargoRegistry" ` + --build-arg "APT_MIRROR=$AptMirror" ` + --load ` + -t $imageTag ` + -f "scripts/docker/Dockerfile.release" ` + . + if ($LASTEXITCODE -ne 0) { + throw "Docker build failed for $Name" + } + + $containerId = docker create --name $containerName $imageTag + if ($LASTEXITCODE -ne 0 -or -not $containerId) { + throw "Docker create failed for $imageTag" + } + + try { + $tmpOutDir = Join-Path $dist ".tmp-$Name" + New-Item -ItemType Directory -Force -Path $tmpOutDir | Out-Null + docker cp "${containerName}:/out/$ContainerBinary" (Join-Path $tmpOutDir $ContainerBinary) + if ($LASTEXITCODE -ne 0) { + throw "Docker cp failed for $Name" + } + Copy-ReleaseFile ` + -SourceFile (Join-Path $tmpOutDir $ContainerBinary) ` + -OutputName $OutputName + } finally { + docker rm -f $containerName | Out-Null + if (Test-Path $tmpOutDir) { + Remove-Item -LiteralPath $tmpOutDir -Recurse -Force + } + } +} + +if ($Target -eq "all" -or $Target -eq "win") { + if ($DockerWindows) { + Build-DockerRelease ` + -Name "windows-x64" ` + -RustTarget "x86_64-pc-windows-gnu" ` + -Platform "linux/amd64" ` + -ContainerBinary "cdxs.exe" ` + -OutputName "cdxs-$Version-windows-x64.exe" + } else { + Write-Host "Building Windows x64" + cargo build --release --target x86_64-pc-windows-msvc + if ($LASTEXITCODE -ne 0) { + throw "Windows build failed" + } + Copy-ReleaseFile ` + -SourceFile (Join-Path $repoRoot "target/x86_64-pc-windows-msvc/release/cdxs.exe") ` + -OutputName "cdxs-$Version-windows-x64.exe" + } +} + +if ($Target -eq "all" -or $Target -eq "linux-x64") { + Build-DockerRelease ` + -Name "linux-x64" ` + -RustTarget "x86_64-unknown-linux-gnu" ` + -Platform "linux/amd64" +} + +if ($Target -eq "all" -or $Target -eq "linux-arm64") { + Build-DockerRelease ` + -Name "linux-arm64" ` + -RustTarget "aarch64-unknown-linux-gnu" ` + -Platform "linux/arm64" +} + +Write-Host "Release artifacts are in $dist"