static.yaml 12 KB

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