docker.yaml 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. ---
  2. name: Build Docker images
  3. on:
  4. pull_request:
  5. branches:
  6. - main
  7. push:
  8. branches:
  9. - main
  10. tags:
  11. - v*.*.*
  12. workflow_dispatch:
  13. inputs: {}
  14. jobs:
  15. prepare:
  16. runs-on: ubuntu-latest
  17. outputs:
  18. # Push only if it's a tag or if we're committing in the main branch
  19. push: ${{toJson(startsWith(github.ref, 'refs/tags/') || (github.ref == 'refs/heads/main' && github.event_name != 'pull_request'))}}
  20. variants: ${{ steps.matrix.outputs.variants }}
  21. platforms: ${{ steps.matrix.outputs.platforms }}
  22. metadata: ${{ steps.matrix.outputs.metadata }}
  23. steps:
  24. -
  25. uses: actions/checkout@v4
  26. -
  27. name: Set up Docker Buildx
  28. uses: docker/setup-buildx-action@v3
  29. with:
  30. version: latest
  31. -
  32. name: Create variants matrix
  33. id: matrix
  34. run: |
  35. METADATA="$(docker buildx bake --print | jq -c)"
  36. {
  37. echo metadata="$METADATA"
  38. echo variants="$(jq -c '.group.default.targets|map(sub("runner-|builder-"; ""))|unique' <<< "$METADATA")"
  39. echo platforms="$(jq -c 'first(.target[]) | .platforms' <<< "$METADATA")"
  40. } >> "$GITHUB_OUTPUT"
  41. env:
  42. LATEST: '1' # TODO: unset this variable when releasing the first stable version
  43. SHA: ${{github.sha}}
  44. VERSION: ${{github.ref_type == 'tag' && github.ref_name || github.sha}}
  45. build:
  46. runs-on: ubuntu-latest
  47. needs:
  48. - prepare
  49. strategy:
  50. fail-fast: false
  51. matrix:
  52. variant: ${{ fromJson(needs.prepare.outputs.variants) }}
  53. platform: ${{ fromJson(needs.prepare.outputs.platforms) }}
  54. include:
  55. - race: ""
  56. qemu: true
  57. - platform: linux/amd64
  58. qemu: false
  59. race: "-race" # The Go race detector is only supported on amd64
  60. - platform: linux/386
  61. qemu: false
  62. steps:
  63. -
  64. uses: actions/checkout@v4
  65. -
  66. name: Set up QEMU
  67. if: matrix.qemu
  68. uses: docker/setup-qemu-action@v3
  69. with:
  70. platforms: ${{matrix.platform}}
  71. -
  72. name: Set up Docker Buildx
  73. uses: docker/setup-buildx-action@v3
  74. with:
  75. platforms: ${{matrix.platform}}
  76. version: latest
  77. -
  78. name: Login to DockerHub
  79. if: fromJson(needs.prepare.outputs.push)
  80. uses: docker/login-action@v3
  81. with:
  82. username: ${{secrets.REGISTRY_USERNAME}}
  83. password: ${{secrets.REGISTRY_PASSWORD}}
  84. -
  85. name: Build
  86. id: build
  87. uses: docker/bake-action@v4
  88. with:
  89. pull: true
  90. load: ${{!fromJson(needs.prepare.outputs.push)}}
  91. targets: |
  92. builder-${{matrix.variant}}
  93. runner-${{matrix.variant}}
  94. # Remove tags to prevent "can't push tagged ref [...] by digest" error
  95. set: |
  96. *.tags=
  97. *.platform=${{matrix.platform}}
  98. *.cache-from=type=gha,scope=${{github.ref}}-${{matrix.platform}}
  99. *.cache-from=type=gha,scope=refs/heads/main-${{matrix.platform}}
  100. *.cache-to=type=gha,scope=${{github.ref}}-${{matrix.platform}}
  101. ${{fromJson(needs.prepare.outputs.push) && '*.output=type=image,name=dunglas/frankenphp,push-by-digest=true,name-canonical=true,push=true' || ''}}
  102. env:
  103. LATEST: '1' # TODO: unset this variable when releasing the first stable version
  104. SHA: ${{github.sha}}
  105. VERSION: ${{github.ref_type == 'tag' && github.ref_name || github.sha}}
  106. -
  107. # Workaround for https://github.com/actions/runner/pull/2477#issuecomment-1501003600
  108. name: Export metadata
  109. if: fromJson(needs.prepare.outputs.push)
  110. run: |
  111. mkdir -p /tmp/metadata/builder /tmp/metadata/runner
  112. builderDigest="$(jq -r '."builder-${{matrix.variant}}"."containerimage.digest"' <<< "$METADATA")"
  113. touch "/tmp/metadata/builder/${builderDigest#sha256:}"
  114. runnerDigest="$(jq -r '."runner-${{matrix.variant}}"."containerimage.digest"' <<< "$METADATA")"
  115. touch "/tmp/metadata/runner/${runnerDigest#sha256:}"
  116. env:
  117. METADATA: ${{steps.build.outputs.metadata}}
  118. -
  119. name: Upload runner metadata
  120. if: fromJson(needs.prepare.outputs.push)
  121. uses: actions/upload-artifact@v3
  122. with:
  123. name: metadata-builder-${{matrix.variant}}
  124. path: /tmp/metadata/builder/*
  125. if-no-files-found: error
  126. retention-days: 1
  127. -
  128. name: Upload runner metadata
  129. if: fromJson(needs.prepare.outputs.push)
  130. uses: actions/upload-artifact@v3
  131. with:
  132. name: metadata-runner-${{matrix.variant}}
  133. path: /tmp/metadata/runner/*
  134. if-no-files-found: error
  135. retention-days: 1
  136. -
  137. name: Run tests
  138. if: '!matrix.qemu'
  139. continue-on-error: ${{fromJson(needs.prepare.outputs.push)}}
  140. run: |
  141. docker run --platform=${{matrix.platform}} --rm \
  142. "$(jq -r '."builder-${{matrix.variant}}"."containerimage.config.digest"' <<< "$METADATA")" \
  143. sh -c 'go test ${{matrix.race}} -v ./... && cd caddy && go test ${{matrix.race}} -v ./...'
  144. env:
  145. METADATA: ${{steps.build.outputs.metadata}}
  146. # Adapted from https://docs.docker.com/build/ci/github-actions/multi-platform/
  147. push:
  148. runs-on: ubuntu-latest
  149. needs:
  150. - prepare
  151. - build
  152. if: fromJson(needs.prepare.outputs.push)
  153. strategy:
  154. fail-fast: false
  155. matrix:
  156. variant: ${{ fromJson(needs.prepare.outputs.variants) }}
  157. target: ['builder', 'runner']
  158. steps:
  159. -
  160. name: Download metadata
  161. uses: actions/download-artifact@v3
  162. with:
  163. name: metadata-${{matrix.target}}-${{matrix.variant}}
  164. path: /tmp/metadata
  165. -
  166. name: Set up Docker Buildx
  167. uses: docker/setup-buildx-action@v3
  168. with:
  169. version: latest
  170. -
  171. name: Login to DockerHub
  172. uses: docker/login-action@v3
  173. with:
  174. username: ${{secrets.REGISTRY_USERNAME}}
  175. password: ${{secrets.REGISTRY_PASSWORD}}
  176. -
  177. name: Create manifest list and push
  178. working-directory: /tmp/metadata
  179. run: |
  180. docker buildx imagetools create "$(jq -cr '.target."${{matrix.target}}-${{matrix.variant}}".tags | map("-t " + .) | join(" ")' <<< "$METADATA")" \
  181. "$(printf 'dunglas/frankenphp@sha256:%s ' *)"
  182. env:
  183. METADATA: ${{needs.prepare.outputs.metadata}}
  184. -
  185. name: Inspect image
  186. run: docker buildx imagetools inspect "$(jq -cr '.target."${{matrix.target}}-${{matrix.variant}}".tags | first' <<< "$METADATA")"
  187. env:
  188. METADATA: ${{needs.prepare.outputs.metadata}}