name: Docker on: push: tags: - "v*" branches: - main pull_request: branches: - main env: IMAGE_NAME: ${{ secrets.DOCKERHUB_USERNAME }}/anyllm-proxy jobs: test: name: Test container runs-on: ubuntu-latest permissions: contents: read steps: - uses: actions/checkout@v4 - uses: docker/setup-buildx-action@v3 # Build locally (no push). Primes the GHA cache for the build matrix jobs. - name: Build test image uses: docker/build-push-action@v6 with: context: . load: true tags: anyllm-proxy:test cache-from: type=gha,scope=test-linux/amd64 cache-to: type=gha,scope=test-linux/amd64,mode=max - name: Smoke test (standalone container) run: | docker run -d --name proxy-test \ -e PROXY_OPEN_RELAY=true \ -p 3000:3000 \ anyllm-proxy:test timeout 30 sh -c 'until curl -sf http://localhost:3000/health; do sleep 1; done' curl -sf http://localhost:3000/health | grep -q '"status":"ok"' docker stop proxy-test && docker rm proxy-test - name: Smoke test (docker compose) run: | printf 'PROXY_OPEN_RELAY=true\nWEBUI=1\n' > .env docker compose up -d timeout 30 sh -c 'until curl -sf http://localhost:3000/health; do sleep 1; done' curl -sf http://localhost:3000/health | grep -q '"status":"ok"' curl -sf http://localhost:3001/admin/health | grep -q '"status":"ok"' docker compose down -v build: name: Build (${{ matrix.platform }}) runs-on: ${{ matrix.runner }} needs: test if: startsWith(github.ref, 'refs/tags/v') permissions: contents: read strategy: fail-fast: false matrix: include: - platform: linux/amd64 runner: ubuntu-latest - platform: linux/arm64 runner: ubuntu-24.04-arm steps: - uses: actions/checkout@v4 - uses: docker/setup-buildx-action@v3 - name: Log in to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ env.IMAGE_NAME }} tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=sha,prefix=sha-,format=short type=raw,value=latest,enable=true - name: Build and push by digest id: build uses: docker/build-push-action@v6 with: context: . platforms: ${{ matrix.platform }} push: true outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true cache-from: type=gha,scope=${{ matrix.platform }} cache-to: type=gha,scope=${{ matrix.platform }},mode=max labels: ${{ steps.meta.outputs.labels }} - name: Export digest run: | mkdir -p /tmp/digests digest="${{ steps.build.outputs.digest }}" touch "/tmp/digests/${digest#sha256:}" - name: Upload digest artifact uses: actions/upload-artifact@v4 with: name: digests-${{ matrix.platform == 'linux/amd64' && 'amd64' || 'arm64' }} path: /tmp/digests/* if-no-files-found: error retention-days: 1 merge: name: Merge multi-arch manifest runs-on: ubuntu-latest needs: build if: startsWith(github.ref, 'refs/tags/v') permissions: contents: read steps: - uses: actions/download-artifact@v4 with: name: digests-amd64 path: /tmp/digests - uses: actions/download-artifact@v4 with: name: digests-arm64 path: /tmp/digests - uses: docker/setup-buildx-action@v3 - name: Log in to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Extract metadata id: meta uses: docker/metadata-action@v5 with: images: ${{ env.IMAGE_NAME }} tags: | type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=sha,prefix=sha-,format=short type=raw,value=latest,enable=true - name: Create and push multi-arch manifest working-directory: /tmp/digests run: | docker buildx imagetools create \ $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< '${{ steps.meta.outputs.json }}') \ $(printf '${{ env.IMAGE_NAME }}@sha256:%s ' *)