static.yaml 12 KB

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