static.yaml 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. ---
  2. name: Build binary releases
  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. version:
  15. description: 'FrankenPHP version'
  16. required: false
  17. type: string
  18. schedule:
  19. - cron: '0 0 * * *'
  20. jobs:
  21. prepare:
  22. runs-on: ubuntu-latest
  23. outputs:
  24. push: ${{ toJson((steps.check.outputs.ref || (github.event_name == 'workflow_dispatch' && inputs.version) || startsWith(github.ref, 'refs/tags/') || (github.ref == 'refs/heads/main' && github.event_name != 'pull_request')) && true || false) }}
  25. platforms: ${{ steps.matrix.outputs.platforms }}
  26. metadata: ${{ steps.matrix.outputs.metadata }}
  27. ref: ${{ steps.check.outputs.ref }}
  28. steps:
  29. -
  30. name: Get version
  31. id: check
  32. if: github.event_name == 'schedule'
  33. run: |
  34. ref="${{ (github.ref_type == 'tag' && github.ref_name) || (github.event_name == 'workflow_dispatch' && inputs.version) || '' }}"
  35. if [[ -z "${ref}" ]]; then
  36. ref="$(gh release view --repo dunglas/frankenphp --json tagName --jq '.tagName')"
  37. fi
  38. echo "ref=${ref}" >> "${GITHUB_OUTPUT}"
  39. env:
  40. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  41. -
  42. uses: actions/checkout@v4
  43. with:
  44. ref: ${{ steps.check.outputs.ref }}
  45. -
  46. name: Set up Docker Buildx
  47. uses: docker/setup-buildx-action@v3
  48. with:
  49. version: latest
  50. -
  51. name: Create platforms matrix
  52. id: matrix
  53. run: |
  54. METADATA="$(docker buildx bake --print static-builder | jq -c)"
  55. {
  56. echo metadata="${METADATA}"
  57. echo platforms="$(jq -c 'first(.target[]) | .platforms' <<< "${METADATA}")"
  58. } >> "${GITHUB_OUTPUT}"
  59. env:
  60. SHA: ${{ github.sha }}
  61. VERSION: ${{ steps.check.outputs.ref || github.sha }}
  62. build-linux:
  63. strategy:
  64. fail-fast: false
  65. matrix:
  66. platform: ${{ fromJson(needs.prepare.outputs.platforms) }}
  67. include:
  68. - race: ""
  69. qemu: true
  70. - platform: linux/amd64
  71. qemu: false
  72. name: Build ${{ matrix.platform }} static binary
  73. runs-on: ubuntu-latest
  74. needs: [ prepare ]
  75. steps:
  76. -
  77. uses: actions/checkout@v4
  78. with:
  79. ref: ${{ needs.prepare.outputs.ref }}
  80. -
  81. name: Set up QEMU
  82. if: matrix.qemu
  83. uses: docker/setup-qemu-action@v3
  84. with:
  85. platforms: ${{ matrix.platform }}
  86. -
  87. name: Set up Docker Buildx
  88. uses: docker/setup-buildx-action@v3
  89. with:
  90. platforms: ${{ matrix.platform }}
  91. version: latest
  92. -
  93. name: Login to DockerHub
  94. if: ${{ fromJson(needs.prepare.outputs.push) }}
  95. uses: docker/login-action@v3
  96. with:
  97. username: ${{ secrets.REGISTRY_USERNAME }}
  98. password: ${{ secrets.REGISTRY_PASSWORD }}
  99. -
  100. name: Build
  101. id: build
  102. uses: docker/bake-action@v4
  103. with:
  104. pull: true
  105. load: ${{ !fromJson(needs.prepare.outputs.push) }}
  106. targets: static-builder
  107. set: |
  108. *.tags=
  109. *.platform=${{ matrix.platform }}
  110. *.cache-from=type=gha,scope=${{ needs.prepare.outputs.ref || github.ref }}-static-builder
  111. *.cache-from=type=gha,scope=refs/heads/main-static-builder
  112. *.cache-to=type=gha,scope=${{ needs.prepare.outputs.ref || github.ref }}-static-builder,ignore-error=true
  113. ${{ fromJson(needs.prepare.outputs.push) && '*.output=type=image,name=dunglas/frankenphp,push-by-digest=true,name-canonical=true,push=true' || '' }}
  114. env:
  115. SHA: ${{ github.sha }}
  116. VERSION: ${{ (github.ref_type == 'tag' && github.ref_name) || needs.prepare.outputs.ref || github.sha}}
  117. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  118. -
  119. # Workaround for https://github.com/actions/runner/pull/2477#issuecomment-1501003600
  120. name: Export metadata
  121. if: fromJson(needs.prepare.outputs.push)
  122. run: |
  123. mkdir -p /tmp/metadata
  124. # shellcheck disable=SC2086
  125. digest=$(jq -r '."static-builder"."containerimage.digest"' <<< ${METADATA})
  126. touch "/tmp/metadata/${digest#sha256:}"
  127. env:
  128. METADATA: ${{ steps.build.outputs.metadata }}
  129. -
  130. name: Upload metadata
  131. if: fromJson(needs.prepare.outputs.push)
  132. uses: actions/upload-artifact@v3
  133. with:
  134. name: metadata-static-builder
  135. path: /tmp/metadata/*
  136. if-no-files-found: error
  137. retention-days: 1
  138. -
  139. name: Copy binary
  140. if: ${{ !fromJson(needs.prepare.outputs.push) }}
  141. run: |
  142. image=$(jq -r '."static-builder"."containerimage.config.digest"' <<< "${METADATA}")
  143. container=$(docker create --platform=${{ matrix.platform }} --name static-builder "${image}")
  144. docker cp "${container}:/go/src/app/dist/${BINARY}" "${BINARY}"
  145. env:
  146. METADATA: ${{ needs.prepare.outputs.metadata }}
  147. BINARY: frankenphp-linux-${{ matrix.platform == 'linux/amd64' && 'x86_64' || 'aarch64' }}
  148. -
  149. name: Upload artifact
  150. if: ${{ !fromJson(needs.prepare.outputs.push) }}
  151. uses: actions/upload-artifact@v3
  152. with:
  153. name: frankenphp-linux-${{ matrix.platform == 'linux/amd64' && 'x86_64' || 'aarch64' }}
  154. path: frankenphp-linux-${{ matrix.platform == 'linux/amd64' && 'x86_64' || 'aarch64' }}
  155. # Adapted from https://docs.docker.com/build/ci/github-actions/multi-platform/
  156. push:
  157. runs-on: ubuntu-latest
  158. needs:
  159. - prepare
  160. - build-linux
  161. if: fromJson(needs.prepare.outputs.push)
  162. #if: fromJson(needs.prepare.outputs.push) && (needs.prepare.outputs.ref || github.ref_type == 'tag')
  163. steps:
  164. -
  165. name: Download metadata
  166. uses: actions/download-artifact@v4
  167. with:
  168. name: metadata-static-builder
  169. path: /tmp/metadata
  170. -
  171. name: Set up Docker Buildx
  172. uses: docker/setup-buildx-action@v3
  173. with:
  174. version: latest
  175. -
  176. name: Login to DockerHub
  177. uses: docker/login-action@v3
  178. with:
  179. username: ${{ secrets.REGISTRY_USERNAME }}
  180. password: ${{ secrets.REGISTRY_PASSWORD }}
  181. -
  182. name: Create manifest list and push
  183. working-directory: /tmp/metadata
  184. run: |
  185. # shellcheck disable=SC2046,SC2086
  186. docker buildx imagetools create $(jq -cr '.target."static-builder".tags | map("-t " + .) | join(" ")' <<< "${METADATA}") \
  187. $(printf 'dunglas/frankenphp@sha256:%s ' *)
  188. env:
  189. METADATA: ${{ needs.prepare.outputs.metadata }}
  190. -
  191. name: Inspect image
  192. run: |
  193. # shellcheck disable=SC2046,SC2086
  194. docker buildx imagetools inspect "$(jq -cr '.target."static-builder".tags | first' <<< "${METADATA}")"
  195. env:
  196. METADATA: ${{ needs.prepare.outputs.metadata }}
  197. -
  198. name: Copy binary
  199. run: |
  200. tag=$(jq -cr '.target."static-builder".tags | first' <<< "${METADATA}")
  201. docker cp "$(docker create --platform=linux/amd64 --name static-builder "${tag}"):/go/src/app/dist/frankenphp-linux-x86_64" frankenphp-linux-x86_64 ; docker rm static-builder
  202. docker cp "$(docker create --platform=linux/arm64 --name static-builder "${tag}"):/go/src/app/dist/frankenphp-linux-aarch64" frankenphp-linux-aarch64 ; docker rm static-builder
  203. env:
  204. METADATA: ${{ needs.prepare.outputs.metadata }}
  205. -
  206. name: Upload asset
  207. if: needs.prepare.outputs.ref || github.ref_type == 'tag'
  208. run: gh release upload "${{ (github.ref_type == 'tag' && github.ref_name) || needs.prepare.outputs.ref }}" frankenphp-linux-x86_64 frankenphp-linux-aarch64 --repo dunglas/frankenphp --clobber
  209. env:
  210. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  211. build-mac:
  212. name: Build macOS x86_64 binaries
  213. runs-on: macos-latest
  214. needs: [ prepare ]
  215. env:
  216. HOMEBREW_NO_AUTO_UPDATE: 1
  217. steps:
  218. -
  219. uses: actions/checkout@v4
  220. with:
  221. ref: ${{ needs.prepare.outputs.ref }}
  222. -
  223. uses: actions/setup-go@v5
  224. with:
  225. go-version: '1.21'
  226. cache-dependency-path: |
  227. go.sum
  228. caddy/go.sum
  229. -
  230. name: Set FRANKENPHP_VERSION
  231. run: |
  232. if [ "${GITHUB_REF_TYPE}" == "tag" ]; then
  233. export FRANKENPHP_VERSION=${GITHUB_REF_NAME:1}
  234. elif [ "${GITHUB_EVENT_NAME}" == "schedule" ]; then
  235. export FRANKENPHP_VERSION="${{ needs.prepare.outputs.ref }}"
  236. else
  237. export FRANKENPHP_VERSION=${GITHUB_SHA}
  238. fi
  239. echo "FRANKENPHP_VERSION=${FRANKENPHP_VERSION}" >> "${GITHUB_ENV}"
  240. -
  241. name: Build FrankenPHP
  242. run: ./build-static.sh
  243. env:
  244. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  245. RELEASE: ${{ (needs.prepare.outputs.ref || github.ref_type == 'tag') && '1' || '' }}
  246. -
  247. name: Upload artifact
  248. if: github.ref_type == 'branch'
  249. uses: actions/upload-artifact@v3
  250. with:
  251. name: frankenphp-mac-x86_64
  252. path: dist/frankenphp-mac-x86_64