ci: build each architecture on its own runner #2
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: release | |
| on: | |
| push: | |
| tags: ['v*'] | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: Tag to release | |
| required: true | |
| permissions: | |
| contents: write | |
| packages: write | |
| env: | |
| IMAGE: ghcr.io/${{ github.repository }} | |
| jobs: | |
| build: | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - arch: amd64 | |
| runner: ubuntu-latest | |
| - arch: arm64 | |
| runner: ubuntu-24.04-arm | |
| runs-on: ${{ matrix.runner }} | |
| timeout-minutes: 60 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: docker/setup-buildx-action@v3 | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| # Each architecture builds on a runner of that architecture. Emulating the PHP compile | |
| # instead took close to three hours. | |
| - name: Build and push by digest | |
| id: build | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: docker/Dockerfile | |
| platforms: linux/${{ matrix.arch }} | |
| cache-from: type=gha,scope=${{ matrix.arch }} | |
| cache-to: type=gha,mode=max,scope=${{ matrix.arch }} | |
| outputs: type=image,name=${{ env.IMAGE }},push-by-digest=true,name-canonical=true,push=true | |
| - name: Record the digest | |
| run: | | |
| digest="${{ steps.build.outputs.digest }}" | |
| mkdir -p /tmp/digests | |
| touch "/tmp/digests/${digest#sha256:}" | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: digest-${{ matrix.arch }} | |
| path: /tmp/digests/* | |
| retention-days: 1 | |
| release: | |
| needs: build | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| steps: | |
| - name: Resolve the version | |
| id: version | |
| run: | | |
| tag="${{ inputs.tag || github.ref_name }}" | |
| echo "tag=$tag" >> "$GITHUB_OUTPUT" | |
| echo "version=${tag#v}" >> "$GITHUB_OUTPUT" | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| path: /tmp/digests | |
| pattern: digest-* | |
| merge-multiple: true | |
| - uses: docker/setup-buildx-action@v3 | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Assemble the multi-architecture tags | |
| working-directory: /tmp/digests | |
| run: | | |
| docker buildx imagetools create \ | |
| --tag "${IMAGE}:${{ steps.version.outputs.version }}" \ | |
| --tag "${IMAGE}:latest" \ | |
| $(printf "${IMAGE}@sha256:%s " *) | |
| docker buildx imagetools inspect "${IMAGE}:${{ steps.version.outputs.version }}" | |
| - name: Extract the binaries | |
| run: | | |
| mkdir -p dist | |
| for arch in amd64 arm64; do | |
| image="${IMAGE}:${{ steps.version.outputs.version }}" | |
| docker pull --platform "linux/$arch" "$image" | |
| container=$(docker create --platform "linux/$arch" "$image") | |
| docker cp "$container:/usr/local/bin/stoke" dist/stoke | |
| docker rm "$container" > /dev/null | |
| tar -czf "dist/stoke-${{ steps.version.outputs.version }}-linux-$arch.tar.gz" -C dist stoke | |
| rm dist/stoke | |
| done | |
| ls -la dist | |
| - name: Publish the release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.version.outputs.tag }} | |
| name: ${{ steps.version.outputs.tag }} | |
| generate_release_notes: true | |
| files: dist/*.tar.gz | |
| body: | | |
| ```sh | |
| docker run --rm -p 8080:8080 -v "$PWD/public:/app/public" \ | |
| ${{ env.IMAGE }}:${{ steps.version.outputs.version }} | |
| ``` | |
| The tarballs hold the bare binary. PHP is linked into it, but these system | |
| libraries are not: `libxml2 libssl3 zlib1g libcurl4 libpq5 libonig5`. The image | |
| already carries them. |