name: release on: push: tags: - 'v*' env: CGO_CFLAGS: '-O3' CGO_CXXFLAGS: '-O3' jobs: setup-environment: runs-on: ubuntu-latest environment: release outputs: GOFLAGS: ${{ steps.goflags.outputs.GOFLAGS }} steps: - uses: actions/checkout@v4 - name: Set environment id: goflags run: | echo GOFLAGS="'-ldflags=-w -s \"-X=github.com/ollama/ollama/version.Version=${GITHUB_REF_NAME#v}\" \"-X=github.com/ollama/ollama/server.mode=release\"'" >>$GITHUB_OUTPUT darwin-build: runs-on: macos-13 environment: release needs: setup-environment strategy: matrix: os: [darwin] arch: [amd64, arm64] env: GOFLAGS: ${{ needs.setup-environment.outputs.GOFLAGS }} steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version-file: go.mod - run: | go build -o dist/ . env: GOOS: ${{ matrix.os }} GOARCH: ${{ matrix.arch }} CGO_ENABLED: 1 CGO_CPPFLAGS: '-mmacosx-version-min=11.3' - if: matrix.arch == 'amd64' run: | cmake --preset CPU -DCMAKE_OSX_DEPLOYMENT_TARGET=11.3 -DCMAKE_SYSTEM_PROCESSOR=x86_64 -DCMAKE_OSX_ARCHITECTURES=x86_64 cmake --build --parallel --preset CPU cmake --install build --component CPU --strip --parallel 8 - uses: actions/upload-artifact@v4 with: name: build-${{ matrix.os }}-${{ matrix.arch }} path: dist/* darwin-sign: runs-on: macos-13 environment: release needs: darwin-build steps: - uses: actions/checkout@v4 - run: | echo $MACOS_SIGNING_KEY | base64 --decode > certificate.p12 security create-keychain -p password build.keychain security default-keychain -s build.keychain security unlock-keychain -p password build.keychain security import certificate.p12 -k build.keychain -P $MACOS_SIGNING_KEY_PASSWORD -T /usr/bin/codesign security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k password build.keychain security set-keychain-settings -lut 3600 build.keychain env: MACOS_SIGNING_KEY: ${{ secrets.MACOS_SIGNING_KEY }} MACOS_SIGNING_KEY_PASSWORD: ${{ secrets.MACOS_SIGNING_KEY_PASSWORD }} - uses: actions/download-artifact@v4 with: name: build-darwin-amd64 path: dist/darwin-amd64 - uses: actions/download-artifact@v4 with: name: build-darwin-arm64 path: dist/darwin-arm64 - run: | export VERSION=${GITHUB_REF_NAME#v} ./scripts/build_darwin.sh sign macapp env: APPLE_IDENTITY: ${{ secrets.APPLE_IDENTITY }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_TEAM_ID: ${{ vars.APPLE_TEAM_ID }} APPLE_ID: ${{ vars.APPLE_ID }} SDKROOT: /Applications/Xcode_14.1.0.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk DEVELOPER_DIR: /Applications/Xcode_14.1.0.app/Contents/Developer - uses: actions/upload-artifact@v4 with: name: dist-darwin path: | dist/Ollama-darwin.zip dist/ollama-darwin.tgz windows-depends: strategy: matrix: os: [windows] arch: [amd64] preset: ['CPU'] include: - os: windows arch: amd64 preset: 'CUDA 11' install: https://developer.download.nvidia.com/compute/cuda/11.3.1/local_installers/cuda_11.3.1_465.89_win10.exe cuda-version: '11.3' - os: windows arch: amd64 preset: 'CUDA 12' install: https://developer.download.nvidia.com/compute/cuda/12.8.0/local_installers/cuda_12.8.0_571.96_windows.exe cuda-version: '12.8' - os: windows arch: amd64 preset: 'ROCm 6' install: https://download.amd.com/developer/eula/rocm-hub/AMD-Software-PRO-Edition-24.Q4-WinSvr2022-For-HIP.exe rocm-version: '6.2' runs-on: ${{ matrix.arch == 'arm64' && format('{0}-{1}', matrix.os, matrix.arch) || matrix.os }} environment: release env: GOFLAGS: ${{ needs.setup-environment.outputs.GOFLAGS }} steps: - name: Install system dependencies run: | choco install -y --no-progress ccache ninja ccache -o cache_dir=${{ github.workspace }}\.ccache - if: startsWith(matrix.preset, 'CUDA ') || startsWith(matrix.preset, 'ROCm ') id: cache-install uses: actions/cache/restore@v4 with: path: | C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA C:\Program Files\AMD\ROCm key: ${{ matrix.install }} - if: startsWith(matrix.preset, 'CUDA ') name: Install CUDA ${{ matrix.cuda-version }} run: | $ErrorActionPreference = "Stop" if ("${{ steps.cache-install.outputs.cache-hit }}" -ne 'true') { Invoke-WebRequest -Uri "${{ matrix.install }}" -OutFile "install.exe" $subpackages = @("cudart", "nvcc", "cublas", "cublas_dev") | Foreach-Object {"${_}_${{ matrix.cuda-version }}"} Start-Process -FilePath .\install.exe -ArgumentList (@("-s") + $subpackages) -NoNewWindow -Wait } $cudaPath = (Resolve-Path "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\*").path echo "$cudaPath\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - if: startsWith(matrix.preset, 'ROCm') name: Install ROCm ${{ matrix.rocm-version }} run: | $ErrorActionPreference = "Stop" if ("${{ steps.cache-install.outputs.cache-hit }}" -ne 'true') { Invoke-WebRequest -Uri "${{ matrix.install }}" -OutFile "install.exe" Start-Process -FilePath .\install.exe -ArgumentList '-install' -NoNewWindow -Wait } $hipPath = (Resolve-Path "C:\Program Files\AMD\ROCm\*").path echo "$hipPath\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append echo "CC=$hipPath\bin\clang.exe" | Out-File -FilePath $env:GITHUB_ENV -Append echo "CXX=$hipPath\bin\clang++.exe" | Out-File -FilePath $env:GITHUB_ENV -Append - if: matrix.preset == 'CPU' run: | echo "CC=clang.exe" | Out-File -FilePath $env:GITHUB_ENV -Append echo "CXX=clang++.exe" | Out-File -FilePath $env:GITHUB_ENV -Append - if: ${{ !cancelled() && steps.cache-install.outputs.cache-hit != 'true' }} uses: actions/cache/save@v4 with: path: | C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA C:\Program Files\AMD\ROCm key: ${{ matrix.install }} - uses: actions/checkout@v4 - uses: actions/cache@v4 with: path: ${{ github.workspace }}\.ccache key: ccache-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.preset }} - name: Build target "${{ matrix.preset }}" run: | Import-Module 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\Microsoft.VisualStudio.DevShell.dll' Enter-VsDevShell -VsInstallPath 'C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise' -SkipAutomaticLocation -DevCmdArguments '-arch=x64 -no_logo' cmake --preset "${{ matrix.preset }}" cmake --build --parallel --preset "${{ matrix.preset }}" cmake --install build --component "${{ startsWith(matrix.preset, 'CUDA ') && 'CUDA' || startsWith(matrix.preset, 'ROCm ') && 'HIP' || 'CPU' }}" --strip --parallel 8 env: CMAKE_GENERATOR: Ninja - uses: actions/upload-artifact@v4 with: name: depends-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.preset }} path: dist\* windows-build: strategy: matrix: os: [windows] arch: [amd64, arm64] runs-on: ${{ matrix.arch == 'arm64' && format('{0}-{1}', matrix.os, matrix.arch) || matrix.os }} environment: release needs: [setup-environment] env: GOFLAGS: ${{ needs.setup-environment.outputs.GOFLAGS }} steps: - name: Install AMD64 system dependencies if: matrix.arch == 'amd64' run: | $ErrorActionPreference = "Stop" Start-Process "C:\msys64\usr\bin\pacman.exe" -ArgumentList @("-S", "--noconfirm", "mingw-w64-clang-x86_64-gcc-compat", "mingw-w64-clang-x86_64-clang") -NoNewWindow -Wait echo "C:\msys64\usr\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append echo "C:\msys64\clang64\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - name: Install ARM64 system dependencies if: matrix.arch == 'arm64' run: | $ErrorActionPreference = "Stop" Set-ExecutionPolicy Bypass -Scope Process -Force [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072 iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) echo "C:\ProgramData\chocolatey\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append choco install -y --no-progress git gzip echo "C:\Program Files\Git\cmd" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append Invoke-WebRequest -Uri "https://github.com/mstorsjo/llvm-mingw/releases/download/20240619/llvm-mingw-20240619-ucrt-aarch64.zip" -OutFile "${{ runner.temp }}\llvm-mingw-ucrt-aarch64.zip" Expand-Archive -Path ${{ runner.temp }}\llvm-mingw-ucrt-aarch64.zip -DestinationPath "C:\Program Files\" $installPath=(Resolve-Path -Path "C:\Program Files\llvm-mingw-*-ucrt-aarch64").path echo $installPath\bin | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version-file: go.mod - run: | go build -o dist/${{ matrix.os }}-${{ matrix.arch }}/ . - if: matrix.arch == 'arm64' run: | Invoke-WebRequest -Uri "https://aka.ms/vs/17/release/vc_redist.arm64.exe" -OutFile "dist\windows-arm64\vc_redist.arm64.exe" - run: | $env:VERSION='${{ github.ref_name }}' -Replace "v(.*)", '$1' & .\scripts\build_windows.ps1 buildApp env: VCToolsRedistDir: stub - uses: actions/upload-artifact@v4 with: name: build-${{ matrix.os }}-${{ matrix.arch }} path: | dist\${{ matrix.os }}-${{ matrix.arch }}\*.exe dist\${{ matrix.os }}-${{ matrix.arch }}-app.exe windows-sign: runs-on: windows-2022 environment: release needs: [windows-depends, windows-build] steps: - uses: actions/checkout@v4 - uses: google-github-actions/auth@v2 with: project_id: ollama credentials_json: ${{ secrets.GOOGLE_SIGNING_CREDENTIALS }} - run: | $ErrorActionPreference = "Stop" Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/p/?LinkId=323507" -OutFile "${{ runner.temp }}\sdksetup.exe" Start-Process "${{ runner.temp }}\sdksetup.exe" -ArgumentList @("/q") -NoNewWindow -Wait Invoke-WebRequest -Uri "https://github.com/GoogleCloudPlatform/kms-integrations/releases/download/cng-v1.0/kmscng-1.0-windows-amd64.zip" -OutFile "${{ runner.temp }}\plugin.zip" Expand-Archive -Path "${{ runner.temp }}\plugin.zip" -DestinationPath "${{ runner.temp }}\plugin\" & "${{ runner.temp }}\plugin\*\kmscng.msi" /quiet echo "${{ vars.OLLAMA_CERT }}" >ollama_inc.crt - uses: actions/download-artifact@v4 with: pattern: build-windows-* path: dist\ merge-multiple: true - uses: actions/download-artifact@v4 with: pattern: depends-windows-amd64-* path: dist\windows-amd64\ merge-multiple: true - run: | & .\scripts\build_windows.ps1 gatherDependencies sign buildInstaller distZip env: KEY_CONTAINER: ${{ vars.KEY_CONTAINER }} - uses: actions/upload-artifact@v4 with: name: dist-windows path: | dist\OllamaSetup.exe dist\ollama-windows-*.zip linux-build: strategy: matrix: include: - os: linux arch: amd64 target: archive - os: linux arch: amd64 target: rocm - os: linux arch: arm64 target: archive runs-on: ${{ matrix.arch == 'arm64' && format('{0}-{1}', matrix.os, matrix.arch) || matrix.os }} environment: release needs: setup-environment env: GOFLAGS: ${{ needs.setup-environment.outputs.GOFLAGS }} steps: - uses: actions/checkout@v4 - uses: docker/setup-buildx-action@v3 - uses: docker/build-push-action@v6 with: context: . platforms: ${{ matrix.os }}/${{ matrix.arch }} target: ${{ matrix.target }} build-args: | GOFLAGS=${{ env.GOFLAGS }} CGO_CFLAGS=${{ env.CGO_CFLAGS }} CGO_CXXFLAGS=${{ env.CGO_CXXFLAGS }} outputs: type=local,dest=dist/${{ matrix.os }}-${{ matrix.arch }} cache-from: type=registry,ref=ollama/ollama:latest cache-to: type=inline - run: | for COMPONENT in bin/* lib/ollama/*; do case "$COMPONENT" in bin/ollama) echo $COMPONENT >>ollama-${{ matrix.os }}-${{ matrix.arch }}.tar.in ;; lib/ollama/*.so) echo $COMPONENT >>ollama-${{ matrix.os }}-${{ matrix.arch }}.tar.in ;; lib/ollama/cuda_v11) echo $COMPONENT >>ollama-${{ matrix.os }}-${{ matrix.arch }}.tar.in ;; lib/ollama/cuda_v12) echo $COMPONENT >>ollama-${{ matrix.os }}-${{ matrix.arch }}.tar.in ;; lib/ollama/cuda_jetpack5) echo $COMPONENT >>ollama-${{ matrix.os }}-${{ matrix.arch }}-jetpack5.tar.in ;; lib/ollama/cuda_jetpack6) echo $COMPONENT >>ollama-${{ matrix.os }}-${{ matrix.arch }}-jetpack6.tar.in ;; lib/ollama/rocm) echo $COMPONENT >>ollama-${{ matrix.os }}-${{ matrix.arch }}-rocm.tar.in ;; esac done working-directory: dist/${{ matrix.os }}-${{ matrix.arch }} - run: | for ARCHIVE in dist/${{ matrix.os }}-${{ matrix.arch }}/*.tar.in; do tar c -C dist/${{ matrix.os }}-${{ matrix.arch }} -T $ARCHIVE --owner 0 --group 0 | pigz -9vc >$(basename ${ARCHIVE//.*/}.tgz); done - uses: actions/upload-artifact@v4 with: name: dist-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.target }} path: | *.tgz # Build each Docker variant (OS, arch, and flavor) separately. Using QEMU is unreliable and slower. docker-build-push: strategy: matrix: include: - os: linux arch: arm64 build-args: | CGO_CFLAGS CGO_CXXFLAGS GOFLAGS - os: linux arch: amd64 build-args: | CGO_CFLAGS CGO_CXXFLAGS GOFLAGS - os: linux arch: amd64 suffix: '-rocm' build-args: | CGO_CFLAGS CGO_CXXFLAGS GOFLAGS FLAVOR=rocm runs-on: ${{ matrix.arch == 'arm64' && format('{0}-{1}', matrix.os, matrix.arch) || matrix.os }} environment: release needs: setup-environment env: GOFLAGS: ${{ needs.setup-environment.outputs.GOFLAGS }} steps: - uses: actions/checkout@v4 - uses: docker/setup-buildx-action@v3 - uses: docker/login-action@v3 with: username: ${{ vars.DOCKER_USER }} password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - id: build-push uses: docker/build-push-action@v6 with: context: . platforms: ${{ matrix.os }}/${{ matrix.arch }} build-args: ${{ matrix.build-args }} outputs: type=image,name=ollama/ollama,push-by-digest=true,name-canonical=true,push=true cache-from: type=registry,ref=ollama/ollama:latest cache-to: type=inline - run: | mkdir -p ${{ matrix.os }}-${{ matrix.arch }} echo "${{ steps.build-push.outputs.digest }}" >${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.suffix }}.txt working-directory: ${{ runner.temp }} - uses: actions/upload-artifact@v4 with: name: digest-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.suffix }} path: | ${{ runner.temp }}/${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.suffix }}.txt # Merge Docker images for the same flavor into a single multi-arch manifest docker-merge-push: strategy: matrix: suffix: ['', '-rocm'] runs-on: linux environment: release needs: [docker-build-push] steps: - uses: docker/login-action@v3 with: username: ${{ vars.DOCKER_USER }} password: ${{ secrets.DOCKER_ACCESS_TOKEN }} - id: metadata uses: docker/metadata-action@v4 with: flavor: | latest=false suffix=${{ matrix.suffix }} images: | ollama/ollama tags: | type=ref,enable=true,priority=600,prefix=pr-,event=pr type=semver,pattern={{version}} - uses: actions/download-artifact@v4 with: pattern: digest-* path: ${{ runner.temp }} merge-multiple: true - run: | docker buildx imagetools create $(echo '${{ steps.metadata.outputs.json }}' | jq -cr '.tags | map("-t", .) | join(" ")') $(cat *-${{ matrix.suffix }}.txt | xargs printf 'ollama/ollama@%s ') docker buildx imagetools inspect ollama/ollama:${{ steps.metadata.outputs.version }} working-directory: ${{ runner.temp }} # Trigger downstream release process trigger: runs-on: ubuntu-latest environment: release needs: [darwin-build, windows-build, windows-depends] steps: - name: Trigger downstream release process run: | curl -L \ -X POST \ -H "Accept: application/vnd.github+json" \ -H "Authorization: Bearer ${{ secrets.RELEASE_TOKEN }}" \ -H "X-GitHub-Api-Version: 2022-11-28" \ https://api.github.com/repos/ollama/${{ vars.RELEASE_REPO }}/dispatches \ -d "{\"event_type\": \"trigger-workflow\", \"client_payload\": {\"run_id\": \"${GITHUB_RUN_ID}\", \"version\": \"${GITHUB_REF_NAME#v}\"}}" # Aggregate all the assets and ship a release release: needs: [darwin-sign, windows-sign, linux-build] runs-on: linux environment: release permissions: contents: write env: GH_TOKEN: ${{ github.token }} steps: - uses: actions/checkout@v4 - uses: actions/download-artifact@v4 with: name: dist-darwin path: dist - uses: actions/download-artifact@v4 with: name: dist-windows path: dist - uses: actions/download-artifact@v4 with: pattern: dist-linux-* path: dist merge-multiple: true - run: find . -type f -not -name 'sha256sum.txt' | xargs sha256sum | tee sha256sum.txt working-directory: dist - name: Create or update Release run: | RELEASE_VERSION="$(echo ${GITHUB_REF_NAME} | cut -f1 -d-)" echo "Looking for existing release for ${RELEASE_VERSION}" OLD_TAG=$(gh release ls --json name,tagName | jq -r ".[] | select(.name == \"${RELEASE_VERSION}\") | .tagName") if [ -n "$OLD_TAG" ]; then echo "Updating release ${RELEASE_VERSION} to point to new tag ${GITHUB_REF_NAME}" gh release edit ${OLD_TAG} --tag ${GITHUB_REF_NAME} else echo "Creating new release ${RELEASE_VERSION} pointing to tag ${GITHUB_REF_NAME}" gh release create ${GITHUB_REF_NAME} \ --title ${RELEASE_VERSION} \ --draft \ --generate-notes \ --prerelease fi echo "Uploading artifacts for tag ${GITHUB_REF_NAME}" gh release upload ${GITHUB_REF_NAME} dist/* --clobber