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