Files
zeekayandHanzo Dev e35c8879dc ci: build the three tenant images on our runners
The image workflow sat under .github/workflows, which no runner here reads, so
no lux, zoo or hanzo image has been built from this app since July. It now lives
in .hanzo/workflows, where the forge runner picks it up on every push to main.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-10 20:22:10 -07:00

111 lines
4.1 KiB
YAML

name: Image
# What lux.vote, zoo.vote and hanzo.vote run is built here, from this
# repository.
#
# ONE SOURCE, THREE TENANTS. The three sites are this bundle built three times
# with a different VITE_VOTE_HOME. A fork per DAO is the alternative and it
# drifts: the app being replaced was forked twice and the copies stopped
# agreeing about what a proposal was.
#
# Each image lands in its OWN org's registry, so a tenant pulls from the org
# that owns it and a namespace's pull secret only has to reach its own
# registry. That costs one thing, and it is written here rather than found out:
# the credential below pushes to all three, so it belongs to an account with
# package:write in luxfi, zooai and hanzoai. A refusal from one registry fails
# that leg alone — `fail-fast: false` — and the other two still publish.
#
# pars.vote is NOT built here. Pars runs its own fork of this source and its CI
# publishes ghcr.io/parsdao/vote. The `pars` venue and brand stay declared in
# this tree because that fork inherits them; the image and the deploy are the
# fork's.
#
# The tag is what each org's declaration pins:
# ghcr.io/luxfi/vote luxfi/universe deploy/lux-vote/lux-vote.yaml
# ghcr.io/zooai/vote zooai/universe deploy/zoo-mainnet/zoo-vote.yaml
# ghcr.io/hanzoai/vote hanzoai/universe charts/app/values/hanzo/hanzo-vote.yaml
# A declaration reads a tag, not a branch, and an image published where no
# declaration reads is invisible.
on:
workflow_dispatch:
push:
branches: [main]
permissions:
contents: read
packages: write
jobs:
build:
# linux-amd64, not linux-amd64: the second is not a label any
# runner advertises (hanzoai/.github RUNNERS.md lists linux-amd64,
# lux-amd64, linux-amd64 and lux-build-amd64), so a job asking for
# it queues forever while looking like CI that has not got round to it.
runs-on: [linux-amd64]
strategy:
# A registry refusing one org must not withhold the other two.
fail-fast: false
matrix:
include:
- home: lux
image: ghcr.io/luxfi/vote
- home: zoo
image: ghcr.io/zooai/vote
- home: hanzo
image: ghcr.io/hanzoai/vote
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver: docker-container
driver-opts: |
network=host
- name: Login to GHCR
uses: docker/login-action@v3
with:
registry: ghcr.io
# GHCR_USER/GHCR_TOKEN, which is what every other luxfi workflow
# that publishes to ghcr.io uses. GITHUB_TOKEN is minted by the forge
# and authenticates to the forge; it is not a GitHub credential and
# cannot push to GitHub's registry. github.repository_owner is a
# repository owner, not a registry account.
username: ${{ secrets.GHCR_USER }}
password: ${{ secrets.GHCR_TOKEN }}
- name: Image metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ matrix.image }}
# No floating tag. A cluster pins a version; `latest` on a registry is
# a moving target that makes "what is deployed" unanswerable.
flavor: |
latest=false
# The tenant stays in the tag even though each image has a registry to
# itself. A tag that says which DAO it opens on can be read off a pod,
# a pull log or a declaration without going back to the workflow that
# made it.
tags: |
type=sha,format=short,prefix=${{ matrix.home }}-
- name: Build & push
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile
platforms: linux/amd64
push: true
build-args: |
VITE_VOTE_HOME=${{ matrix.home }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Say what to pin
run: |
echo "Built ${{ matrix.home }}.vote: ${{ steps.meta.outputs.tags }}"
echo "Nothing deploys until that org's declaration names this tag."