feat: Windows support #4048
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: Build Docker images | |
| concurrency: | |
| cancel-in-progress: true | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| paths: | |
| - "docker-bake.hcl" | |
| - ".github/workflows/docker.yaml" | |
| - "**cgo.go" | |
| - "**Dockerfile" | |
| - "**.c" | |
| - "**.h" | |
| - "**.sh" | |
| - "**.stub.php" | |
| push: | |
| branches: | |
| - main | |
| tags: | |
| - v*.*.* | |
| workflow_dispatch: | |
| inputs: | |
| #checkov:skip=CKV_GHA_7 | |
| version: | |
| description: "FrankenPHP version" | |
| required: false | |
| type: string | |
| schedule: | |
| - cron: "0 4 * * *" | |
| permissions: | |
| contents: read | |
| env: | |
| IMAGE_NAME: ${{ (github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.version) || startsWith(github.ref, 'refs/tags/')) && 'dunglas/frankenphp' || 'dunglas/frankenphp-dev' }} | |
| jobs: | |
| prepare: | |
| runs-on: ubuntu-24.04 | |
| outputs: | |
| # Push if it's a scheduled job, a tag, or if we're committing to the main branch | |
| push: ${{ (github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.version) || startsWith(github.ref, 'refs/tags/') || (github.ref == 'refs/heads/main' && github.event_name != 'pull_request')) && true || false }} | |
| variants: ${{ steps.matrix.outputs.variants }} | |
| platforms: ${{ steps.matrix.outputs.platforms }} | |
| metadata: ${{ steps.matrix.outputs.metadata }} | |
| php_version: ${{ steps.check.outputs.php_version }} | |
| php82_version: ${{ steps.check.outputs.php82_version }} | |
| php83_version: ${{ steps.check.outputs.php83_version }} | |
| php84_version: ${{ steps.check.outputs.php84_version }} | |
| php85_version: ${{ steps.check.outputs.php85_version }} | |
| skip: ${{ steps.check.outputs.skip }} | |
| ref: ${{ steps.check.outputs.ref || (github.event_name == 'workflow_dispatch' && inputs.version) || '' }} | |
| base_fingerprint: ${{ steps.check.outputs.base_fingerprint }} | |
| steps: | |
| - uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Check PHP versions and base image fingerprint | |
| id: check | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: ./.github/scripts/docker-compute-fingerprints.sh | |
| - name: Create variants matrix | |
| if: ${{ !fromJson(steps.check.outputs.skip) }} | |
| id: matrix | |
| shell: bash | |
| run: | | |
| set -e | |
| METADATA="$(docker buildx bake --print | jq -c)" | |
| { | |
| echo metadata="${METADATA}" | |
| echo variants="$(jq -c '.group.default.targets|map(sub("runner-|builder-"; ""))|unique' <<< "${METADATA}")" | |
| echo platforms="$(jq -c 'first(.target[]) | .platforms' <<< "${METADATA}")" | |
| } >> "${GITHUB_OUTPUT}" | |
| env: | |
| SHA: ${{ github.sha }} | |
| VERSION: ${{ (github.ref_type == 'tag' && github.ref_name) || steps.check.outputs.ref || 'dev' }} | |
| PHP_VERSION: ${{ steps.check.outputs.php_version }} | |
| build: | |
| runs-on: ${{ startsWith(matrix.platform, 'linux/arm') && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }} | |
| needs: | |
| - prepare | |
| if: ${{ !fromJson(needs.prepare.outputs.skip) }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| variant: ${{ fromJson(needs.prepare.outputs.variants) }} | |
| platform: ${{ fromJson(needs.prepare.outputs.platforms) }} | |
| include: | |
| - race: "" | |
| - platform: linux/amd64 | |
| race: "-race" # The Go race detector is only supported on amd64 | |
| exclude: | |
| # arm/v6 is only available for Alpine: https://github.com/docker-library/golang/issues/502 | |
| - variant: php-${{ needs.prepare.outputs.php82_version }}-trixie | |
| platform: linux/arm/v6 | |
| - variant: php-${{ needs.prepare.outputs.php83_version }}-trixie | |
| platform: linux/arm/v6 | |
| - variant: php-${{ needs.prepare.outputs.php84_version }}-trixie | |
| platform: linux/arm/v6 | |
| - variant: php-${{ needs.prepare.outputs.php85_version }}-trixie | |
| platform: linux/arm/v6 | |
| - variant: php-${{ needs.prepare.outputs.php82_version }}-bookworm | |
| platform: linux/arm/v6 | |
| - variant: php-${{ needs.prepare.outputs.php83_version }}-bookworm | |
| platform: linux/arm/v6 | |
| - variant: php-${{ needs.prepare.outputs.php84_version }}-bookworm | |
| platform: linux/arm/v6 | |
| - variant: php-${{ needs.prepare.outputs.php85_version }}-bookworm | |
| platform: linux/arm/v6 | |
| steps: | |
| - name: Prepare | |
| id: prepare | |
| run: echo "sanitized_platform=${PLATFORM//\//-}" >> "${GITHUB_OUTPUT}" | |
| env: | |
| PLATFORM: ${{ matrix.platform }} | |
| - uses: actions/checkout@v6 | |
| with: | |
| ref: ${{ needs.prepare.outputs.ref }} | |
| persist-credentials: false | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| with: | |
| platforms: ${{ matrix.platform }} | |
| - name: Login to DockerHub | |
| uses: docker/login-action@v3 | |
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository | |
| with: | |
| username: ${{ secrets.REGISTRY_USERNAME }} | |
| password: ${{ secrets.REGISTRY_PASSWORD }} | |
| - name: Build | |
| id: build | |
| uses: docker/bake-action@v6 | |
| with: | |
| pull: true | |
| load: ${{ !fromJson(needs.prepare.outputs.push) }} | |
| source: . | |
| targets: | | |
| builder-${{ matrix.variant }} | |
| runner-${{ matrix.variant }} | |
| # Remove tags to prevent "can't push tagged ref [...] by digest" error | |
| set: | | |
| ${{ (github.event_name == 'pull_request') && '*.args.NO_COMPRESS=1' || '' }} | |
| *.tags= | |
| *.platform=${{ matrix.platform }} | |
| ${{ fromJson(needs.prepare.outputs.push) && '' || format('builder-{0}.cache-from=type=gha,scope=builder-{0}-{1}-{2}', matrix.variant, needs.prepare.outputs.ref || github.ref, matrix.platform) }} | |
| ${{ fromJson(needs.prepare.outputs.push) && '' || format('builder-{0}.cache-from=type=gha,scope=refs/heads/main-builder-{0}-{1}', matrix.variant, matrix.platform) }} | |
| ${{ fromJson(needs.prepare.outputs.push) && '' || format('builder-{0}.cache-to=type=gha,scope=builder-{0}-{1}-{2},ignore-error=true', matrix.variant, needs.prepare.outputs.ref || github.ref, matrix.platform) }} | |
| ${{ fromJson(needs.prepare.outputs.push) && '' || format('runner-{0}.cache-from=type=gha,scope=runner-{0}-{1}-{2}', matrix.variant, needs.prepare.outputs.ref || github.ref, matrix.platform) }} | |
| ${{ fromJson(needs.prepare.outputs.push) && '' || format('runner-{0}.cache-from=type=gha,scope=refs/heads/main-runner-{0}-{1}', matrix.variant, matrix.platform) }} | |
| ${{ fromJson(needs.prepare.outputs.push) && '' || format('runner-{0}.cache-to=type=gha,scope=runner-{0}-{1}-{2},ignore-error=true', matrix.variant, needs.prepare.outputs.ref || github.ref, matrix.platform) }} | |
| ${{ fromJson(needs.prepare.outputs.push) && format('*.output=type=image,name={0},push-by-digest=true,name-canonical=true,push=true', env.IMAGE_NAME) || '' }} | |
| env: | |
| SHA: ${{ github.sha }} | |
| VERSION: ${{ (github.ref_type == 'tag' && github.ref_name) || needs.prepare.outputs.ref || 'dev' }} | |
| PHP_VERSION: ${{ needs.prepare.outputs.php_version }} | |
| BASE_FINGERPRINT: ${{ needs.prepare.outputs.base_fingerprint }} | |
| - # Workaround for https://github.com/actions/runner/pull/2477#issuecomment-1501003600 | |
| name: Export metadata | |
| if: fromJson(needs.prepare.outputs.push) | |
| run: | | |
| mkdir -p /tmp/metadata/builder /tmp/metadata/runner | |
| builderDigest=$(jq -r ".\"builder-${VARIANT}\".\"containerimage.digest\"" <<< "${METADATA}") | |
| touch "/tmp/metadata/builder/${builderDigest#sha256:}" | |
| runnerDigest=$(jq -r ".\"runner-${VARIANT}\".\"containerimage.digest\"" <<< "${METADATA}") | |
| touch "/tmp/metadata/runner/${runnerDigest#sha256:}" | |
| env: | |
| METADATA: ${{ steps.build.outputs.metadata }} | |
| VARIANT: ${{ matrix.variant }} | |
| - name: Upload builder metadata | |
| if: fromJson(needs.prepare.outputs.push) | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: metadata-builder-${{ matrix.variant }}-${{ steps.prepare.outputs.sanitized_platform }} | |
| path: /tmp/metadata/builder/* | |
| if-no-files-found: error | |
| retention-days: 1 | |
| - name: Upload runner metadata | |
| if: fromJson(needs.prepare.outputs.push) | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: metadata-runner-${{ matrix.variant }}-${{ steps.prepare.outputs.sanitized_platform }} | |
| path: /tmp/metadata/runner/* | |
| if-no-files-found: error | |
| retention-days: 1 | |
| - name: Run tests | |
| if: ${{ !fromJson(needs.prepare.outputs.push) }} | |
| run: | | |
| docker run --platform="${PLATFORM}" --rm \ | |
| "$(jq -r ".\"builder-${VARIANT}\".\"containerimage.config.digest\"" <<< "${METADATA}")" \ | |
| sh -c "./go.sh test ${RACE} -v $(./go.sh list ./... | grep -v github.com/dunglas/frankenphp/internal/testext | grep -v github.com/dunglas/frankenphp/internal/extgen | tr '\n' ' ') && cd caddy && ../go.sh test ${RACE} -v ./..." | |
| env: | |
| METADATA: ${{ steps.build.outputs.metadata }} | |
| PLATFORM: ${{ matrix.platform }} | |
| VARIANT: ${{ matrix.variant }} | |
| RACE: ${{ matrix.race }} | |
| # Adapted from https://docs.docker.com/build/ci/github-actions/multi-platform/ | |
| push: | |
| runs-on: ubuntu-24.04 | |
| needs: | |
| - prepare | |
| - build | |
| if: fromJson(needs.prepare.outputs.push) | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| variant: ${{ fromJson(needs.prepare.outputs.variants) }} | |
| target: ["builder", "runner"] | |
| steps: | |
| - name: Download metadata | |
| uses: actions/download-artifact@v7 | |
| with: | |
| pattern: metadata-${{ matrix.target }}-${{ matrix.variant }}-* | |
| path: /tmp/metadata | |
| merge-multiple: true | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Login to DockerHub | |
| uses: docker/login-action@v3 | |
| if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository | |
| with: | |
| username: ${{ secrets.REGISTRY_USERNAME }} | |
| password: ${{ secrets.REGISTRY_PASSWORD }} | |
| - name: Create manifest list and push | |
| working-directory: /tmp/metadata | |
| run: | | |
| set -x | |
| # shellcheck disable=SC2046,SC2086 | |
| docker buildx imagetools create $(jq -cr ".target.\"${TARGET}-${VARIANT}\".tags | map(\"-t \" + .) | join(\" \")" <<< ${METADATA}) \ | |
| $(printf "${IMAGE_NAME}@sha256:%s " *) | |
| env: | |
| METADATA: ${{ needs.prepare.outputs.metadata }} | |
| TARGET: ${{ matrix.target }} | |
| VARIANT: ${{ matrix.variant }} | |
| - name: Inspect image | |
| run: | | |
| # shellcheck disable=SC2046,SC2086 | |
| docker buildx imagetools inspect $(jq -cr ".target.\"${TARGET}-${VARIANT}\".tags | first" <<< ${METADATA}) | |
| env: | |
| METADATA: ${{ needs.prepare.outputs.metadata }} | |
| TARGET: ${{ matrix.target }} | |
| VARIANT: ${{ matrix.variant }} |