From a6b27d776b57a50b31028e591fc78de4e967a104 Mon Sep 17 00:00:00 2001 From: Daniel Hiltgen Date: Thu, 12 Mar 2026 16:14:00 -0700 Subject: [PATCH] ci: fix missing windows zip file (#14807) Use 7z compression (better compression rate) if found in path. That alone isn't sufficient to get us under 2G, so MLX is now split out as a discrete download. Fix CI so it will fail if artifacts fail to upload. --- .github/workflows/release.yaml | 14 +++-- docs/windows.mdx | 10 ++-- scripts/build_windows.ps1 | 99 ++++++++++++++++++++++++++++------ 3 files changed, 100 insertions(+), 23 deletions(-) diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml index a51ca1b9c..c9d53d732 100644 --- a/.github/workflows/release.yaml +++ b/.github/workflows/release.yaml @@ -583,11 +583,19 @@ jobs: for payload in dist/*.txt dist/*.zip dist/*.tgz dist/*.tar.zst dist/*.exe dist/*.dmg dist/*.ps1 dist/*.sh ; do echo "Uploading $payload" gh release upload ${GITHUB_REF_NAME} $payload --clobber & - pids[$!]=$! + pids+=($!) sleep 1 done echo "Waiting for uploads to complete" - for pid in "${pids[*]}"; do - wait $pid + failed=0 + for pid in "${pids[@]}"; do + if ! wait $pid; then + echo "::error::Upload failed (pid $pid)" + failed=1 + fi done + if [ $failed -ne 0 ]; then + echo "One or more uploads failed" + exit 1 + fi echo "done" diff --git a/docs/windows.mdx b/docs/windows.mdx index 37fd19730..555efb940 100644 --- a/docs/windows.mdx +++ b/docs/windows.mdx @@ -80,9 +80,13 @@ help you keep up to date. If you'd like to install or integrate Ollama as a service, a standalone `ollama-windows-amd64.zip` zip file is available containing only the Ollama CLI -and GPU library dependencies for Nvidia. If you have an AMD GPU, also download -and extract the additional ROCm package `ollama-windows-amd64-rocm.zip` into the -same directory. This allows for embedding Ollama in existing applications, or +and GPU library dependencies for Nvidia. Depending on your hardware, you may also +need to download and extract additional packages into the same directory: + +- **AMD GPU**: `ollama-windows-amd64-rocm.zip` +- **MLX (CUDA)**: `ollama-windows-amd64-mlx.zip` + +This allows for embedding Ollama in existing applications, or running it as a system service via `ollama serve` with tools such as [NSSM](https://nssm.cc/). diff --git a/scripts/build_windows.ps1 b/scripts/build_windows.ps1 index f162e4f7e..5e797e3d2 100644 --- a/scripts/build_windows.ps1 +++ b/scripts/build_windows.ps1 @@ -425,28 +425,93 @@ function installer { if ($LASTEXITCODE -ne 0) { exit($LASTEXITCODE)} } -function zip { - if (Test-Path -Path "${script:SRC_DIR}\dist\windows-amd64") { - if (Test-Path -Path "${script:SRC_DIR}\dist\windows-amd64\lib\ollama\rocm") { - Write-Output "Generating stand-alone distribution zip file ${script:SRC_DIR}\dist\ollama-windows-amd64-rocm.zip" - # Temporarily adjust paths so we can retain the same directory structure - Remove-Item -ea 0 -r "${script:SRC_DIR}\dist\windows-amd64-rocm" - mkdir -Force -path "${script:SRC_DIR}\dist\windows-amd64-rocm\lib\ollama" - Write-Output "Extract this ROCm zip file to the same location where you extracted ollama-windows-amd64.zip" > "${script:SRC_DIR}\dist\windows-amd64-rocm\README.txt" - Move-Item -path "${script:SRC_DIR}\dist\windows-amd64\lib\ollama\rocm" -destination "${script:SRC_DIR}\dist\windows-amd64-rocm\lib\ollama" -ErrorAction Stop - Compress-Archive -CompressionLevel Optimal -Path "${script:SRC_DIR}\dist\windows-amd64-rocm\*" -DestinationPath "${script:SRC_DIR}\dist\ollama-windows-amd64-rocm.zip" -Force +function newZipJob($sourceDir, $destZip) { + $use7z = [bool](Get-Command 7z -ErrorAction SilentlyContinue) + Start-Job -ScriptBlock { + param($src, $dst, $use7z) + if ($use7z) { + & 7z a -tzip -mx=9 -mmt=on $dst "${src}\*" + if ($LASTEXITCODE -ne 0) { throw "7z failed with exit code $LASTEXITCODE" } + } else { + Compress-Archive -CompressionLevel Optimal -Path "${src}\*" -DestinationPath $dst -Force } + } -ArgumentList $sourceDir, $destZip, $use7z +} - Write-Output "Generating stand-alone distribution zip file ${script:SRC_DIR}\dist\ollama-windows-amd64.zip" - Compress-Archive -CompressionLevel Optimal -Path "${script:SRC_DIR}\dist\windows-amd64\*" -DestinationPath "${script:SRC_DIR}\dist\ollama-windows-amd64.zip" -Force - if (Test-Path -Path "${script:SRC_DIR}\dist\windows-amd64-rocm") { - Move-Item -destination "${script:SRC_DIR}\dist\windows-amd64\lib\ollama\rocm" -path "${script:SRC_DIR}\dist\windows-amd64-rocm\lib\ollama\rocm" -ErrorAction Stop +function stageComponents($mainDir, $stagingDir, $pattern, $readmePrefix) { + $components = Get-ChildItem -Path "${mainDir}\lib\ollama" -Directory -Filter $pattern -ErrorAction SilentlyContinue + if ($components) { + Remove-Item -ea 0 -r $stagingDir + mkdir -Force -path "${stagingDir}\lib\ollama" | Out-Null + Write-Output "Extract this ${readmePrefix} zip file to the same location where you extracted ollama-windows-amd64.zip" > "${stagingDir}\README_${readmePrefix}.txt" + foreach ($dir in $components) { + Write-Output " Staging $($dir.Name)" + Move-Item -path $dir.FullName -destination "${stagingDir}\lib\ollama\$($dir.Name)" + } + return $true + } + return $false +} + +function restoreComponents($mainDir, $stagingDir) { + if (Test-Path -Path "${stagingDir}\lib\ollama") { + foreach ($dir in (Get-ChildItem -Path "${stagingDir}\lib\ollama" -Directory)) { + Move-Item -path $dir.FullName -destination "${mainDir}\lib\ollama\$($dir.Name)" } } + Remove-Item -ea 0 -r $stagingDir +} - if (Test-Path -Path "${script:SRC_DIR}\dist\windows-arm64") { - Write-Output "Generating stand-alone distribution zip file ${script:SRC_DIR}\dist\ollama-windows-arm64.zip" - Compress-Archive -CompressionLevel Optimal -Path "${script:SRC_DIR}\dist\windows-arm64\*" -DestinationPath "${script:SRC_DIR}\dist\ollama-windows-arm64.zip" -Force +function zip { + $jobs = @() + $distDir = "${script:SRC_DIR}\dist" + $amd64Dir = "${distDir}\windows-amd64" + + # Remove any stale zip files before starting + Remove-Item -ea 0 "${distDir}\ollama-windows-*.zip" + + try { + if (Test-Path -Path $amd64Dir) { + # Stage ROCm into its own directory for independent compression + if (stageComponents $amd64Dir "${distDir}\windows-amd64-rocm" "rocm*" "ROCm") { + Write-Output "Generating ${distDir}\ollama-windows-amd64-rocm.zip" + $jobs += newZipJob "${distDir}\windows-amd64-rocm" "${distDir}\ollama-windows-amd64-rocm.zip" + } + + # Stage MLX into its own directory for independent compression + if (stageComponents $amd64Dir "${distDir}\windows-amd64-mlx" "mlx_*" "MLX") { + Write-Output "Generating ${distDir}\ollama-windows-amd64-mlx.zip" + $jobs += newZipJob "${distDir}\windows-amd64-mlx" "${distDir}\ollama-windows-amd64-mlx.zip" + } + + # Compress the main amd64 zip (without rocm/mlx) + Write-Output "Generating ${distDir}\ollama-windows-amd64.zip" + $jobs += newZipJob $amd64Dir "${distDir}\ollama-windows-amd64.zip" + } + + if (Test-Path -Path "${distDir}\windows-arm64") { + Write-Output "Generating ${distDir}\ollama-windows-arm64.zip" + $jobs += newZipJob "${distDir}\windows-arm64" "${distDir}\ollama-windows-arm64.zip" + } + + if ($jobs.Count -gt 0) { + Write-Output "Waiting for $($jobs.Count) parallel zip jobs..." + $jobs | Wait-Job | Out-Null + $failed = $false + foreach ($job in $jobs) { + if ($job.State -eq 'Failed') { + Write-Error "Zip job failed: $($job.ChildJobs[0].JobStateInfo.Reason)" + $failed = $true + } + Receive-Job $job + Remove-Job $job + } + if ($failed) { throw "One or more zip jobs failed" } + } + } finally { + # Always restore staged components back into the main tree + restoreComponents $amd64Dir "${distDir}\windows-amd64-rocm" + restoreComponents $amd64Dir "${distDir}\windows-amd64-mlx" } }