release-image.yml 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. name: release-image
  2. # Builds + publishes the briven self-host container images on every
  3. # `v*` tag pushed to main. Five separate images — one per app — under
  4. # ghcr.io/flndrn/briven-<app>:<version>. Multi-arch (amd64 + arm64) so
  5. # M-series Mac developers and ARM VPS can pull without QEMU.
  6. #
  7. # Required repo permissions: `packages: write` (granted by the
  8. # permissions block below — uses the workflow's GITHUB_TOKEN, no PAT
  9. # needed).
  10. #
  11. # Tag strategy:
  12. # v0.3.1 → :0.3.1, :0.3, :0 (stable) and :latest
  13. # v0.3.1-beta.2 → :0.3.1-beta.2 only (no :latest, no major/minor float)
  14. # (metadata-action handles the differentiation via flavor.latest=auto +
  15. # the semver/match patterns below).
  16. on:
  17. push:
  18. tags:
  19. - 'v*'
  20. # workflow_dispatch lets you re-build a release from the Actions UI
  21. # without retagging — useful if a build node was flaky.
  22. workflow_dispatch:
  23. inputs:
  24. tag:
  25. description: 'Tag to build (e.g. v0.3.1)'
  26. required: true
  27. concurrency:
  28. group: ${{ github.workflow }}-${{ github.event.inputs.tag || github.ref }}
  29. cancel-in-progress: false
  30. permissions:
  31. contents: read
  32. packages: write
  33. env:
  34. REGISTRY: ghcr.io
  35. IMAGE_OWNER: flndrn
  36. jobs:
  37. publish:
  38. name: publish · ${{ matrix.app }}
  39. runs-on: ubuntu-latest
  40. strategy:
  41. fail-fast: false
  42. matrix:
  43. app: [api, runtime, realtime, web, docs]
  44. steps:
  45. - name: checkout
  46. uses: actions/checkout@v6
  47. with:
  48. ref: ${{ github.event.inputs.tag || github.ref }}
  49. - name: set up qemu (for arm64 cross-build)
  50. uses: docker/setup-qemu-action@v3
  51. with:
  52. platforms: arm64
  53. - name: set up buildx
  54. uses: docker/setup-buildx-action@v3
  55. - name: login to ghcr.io
  56. uses: docker/login-action@v3
  57. with:
  58. registry: ${{ env.REGISTRY }}
  59. username: ${{ github.actor }}
  60. password: ${{ secrets.GITHUB_TOKEN }}
  61. - name: extract metadata
  62. id: meta
  63. uses: docker/metadata-action@v5
  64. with:
  65. images: ${{ env.REGISTRY }}/${{ env.IMAGE_OWNER }}/briven-${{ matrix.app }}
  66. # Tag the image with: full semver, major.minor, major (when
  67. # stable), and `latest` (when stable, controlled by
  68. # flavor.latest=auto). Pre-releases get only the full version.
  69. tags: |
  70. type=semver,pattern={{version}}
  71. type=semver,pattern={{major}}.{{minor}}
  72. type=semver,pattern={{major}}
  73. flavor: |
  74. latest=auto
  75. - name: build + push
  76. uses: docker/build-push-action@v6
  77. with:
  78. context: .
  79. file: apps/${{ matrix.app }}/Dockerfile
  80. # arm64 build is slower (qemu-emulated) but worth it — a
  81. # majority of self-hosters run amd64 VPS, the ARM minority is
  82. # macOS local + raspberry-pi-class boxes which still need an
  83. # image. If build time becomes painful, drop arm64 from the
  84. # release matrix and offer a separate "request arm build"
  85. # workflow_dispatch path.
  86. platforms: linux/amd64,linux/arm64
  87. push: true
  88. tags: ${{ steps.meta.outputs.tags }}
  89. labels: ${{ steps.meta.outputs.labels }}
  90. # Cache layers between matrix runs + across tags — keyed on
  91. # the app so api's cache doesn't bleed into web's.
  92. cache-from: type=gha,scope=${{ matrix.app }}
  93. cache-to: type=gha,scope=${{ matrix.app }},mode=max
  94. # Provenance + SBOM attestations land in the OCI manifest.
  95. # Useful for downstream security scans + verifiable builds.
  96. provenance: true
  97. sbom: true