Build and publish the image from GitHub through hanzoai/ci

.github/workflows/cicd.yml is the canonical caller of hanzoai/ci
build.yml@v2, which runs on the linux-amd64 JIT runners. hanzo.yml keeps
its build gate and now declares the image, so a push to main publishes
ghcr.io/hanzoai/sign as sha-<short7>-amd64 plus a semver from bin/imgver.
`version: 0.2.0` sets the series above the 0.1.x tags already published,
because package.json carries the upstream 2.7.1.

The two .hanzo/workflows build callers go: the forge copy is a mirror
with Actions off, and either one would publish the same commit a second
time if it ran.

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
zooqueen
2026-10-16 01:57:32 -07:00
co-authored by Hanzo Dev
parent ecee5e40aa
commit e0ea095e6d
4 changed files with 34 additions and 82 deletions
+14
View File
@@ -0,0 +1,14 @@
# Canonical caller — every knob lives in /hanzo.yml, none here.
# github.com is canonical and its linux-amd64 jobs run on the JIT runners in
# AWS (ns hanzo-ci); the image is built by the build door.
name: CI/CD
on:
push:
branches: [main]
tags: ['v*']
pull_request:
workflow_dispatch:
jobs:
cicd:
uses: hanzoai/ci/.github/workflows/build.yml@v2
secrets: inherit
-15
View File
@@ -1,15 +0,0 @@
# Canonical caller — every knob lives in /hanzo.yml, none here.
# Runs on the git-runner fleet at git.hanzo.ai, the only pool serving these
# labels. github.com resolves only .github/workflows and has no runner for
# them, so a caller placed there is a gate that cannot be scheduled.
name: CI/CD
on:
push:
branches: [main]
tags: ['v*']
pull_request:
workflow_dispatch:
jobs:
cicd:
uses: hanzoai/ci/.github/workflows/build.yml@v1
secrets: inherit
-64
View File
@@ -1,64 +0,0 @@
# Build the image and push it. Nothing else.
#
# The previous pipeline called buildctl-daemonless.sh, absent from the job image
# (catthehacker/ubuntu:act-24.04) — exit 127 — and read secrets.GIT_CLONE_TOKEN,
# which exists nowhere. It had never produced an image.
#
# TARGET: this repo has FIVE Dockerfiles (apps/remix/{Dockerfile,.bun,.pnpm},
# docker/{Dockerfile,.chromium}). docker/Dockerfile is the app image — it is the
# multi-stage node:22-alpine build that `COPY . .` from the repo root, and the
# cluster runs ghcr.io/hanzoai/sign:0.1.0, so that is the name it owes.
# NOTE the image is `sign`, not `esign`: the GitHub repo was renamed (hanzoai/sign
# 307s to hanzoai/esign) but the published image name did not follow.
#
# No deploy step: kubectl is absent from the job image, and cd.hanzo.ai selfHeal
# restores the App CR from the reviewed pin in hanzoai/universe within minutes.
name: deploy
on:
push:
branches: [main]
workflow_dispatch:
concurrency:
group: deploy-esign-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: [linux-amd64]
steps:
- uses: actions/checkout@v4
- id: meta
run: echo "tag=sha-$(echo "$GITHUB_SHA" | cut -c1-7)" >> "$GITHUB_OUTPUT"
- uses: docker/setup-buildx-action@v3
with: { driver: docker-container, driver-opts: network=host }
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ secrets.GHCR_USER }}
password: ${{ secrets.GHCR_TOKEN }}
- uses: docker/build-push-action@v6
with:
context: .
file: ./docker/Dockerfile
platforms: linux/amd64
push: true
provenance: false
# No `secrets:`. docker/Dockerfile is Node all the way down and mounts
# nothing, and this repo's go.mod requires no module at all — so the
# credential was reaching a build that had nothing to fetch with it.
tags: ghcr.io/hanzoai/sign:${{ steps.meta.outputs.tag }}
- name: Verify the pushed image resolves
run: |
set -euo pipefail
img="ghcr.io/hanzoai/sign:${{ steps.meta.outputs.tag }}"
for i in 1 2 3 4 5 6; do
docker buildx imagetools inspect "$img" >/dev/null 2>&1 && { echo "resolved $img"; exit 0; }
sleep 5
done
echo "::error::pushed image never resolved: $img"; exit 1
+20 -3
View File
@@ -1,8 +1,10 @@
# Hanzo eSign — a turborepo whose deployable artifact is the remix app. # Hanzo eSign — a turborepo whose deployable artifact is the remix app.
# #
# Gate only. The image is already built and pushed by the native builder in this # GitHub runs .github/workflows/cicd.yml (hanzoai/ci build.yml@v2) against this
# repo (.hanzo/workflows/deploy.yml → ghcr.io/hanzoai/sign:<tag>), so declaring # file on every push to main, tag v* and pull request. `test:` gates; `images:`
# `images:` here would publish a second copy of the same commit. # builds docker/Dockerfile and publishes ghcr.io/hanzoai/sign as
# sha-<short7>-amd64 plus the semver the pin in hanzoai/universe
# (charts/app/values/hanzo/sign.yaml) names.
# #
# The gate is the real build of the app the cluster runs: npm ci against the # The gate is the real build of the app the cluster runs: npm ci against the
# committed lockfile (postinstall generates the Prisma client), then turbo's # committed lockfile (postinstall generates the Prisma client), then turbo's
@@ -17,6 +19,13 @@
# client. Base SQLite serves one write connection, so such a call waits on a # client. Base SQLite serves one write connection, so such a call waits on a
# lock the transaction holds and the transaction dies (`P2028`) — at runtime, # lock the transaction holds and the transaction dies (`P2028`) — at runtime,
# with a green build. See packages/eslint-config/transaction.cjs. # with a green build. See packages/eslint-config/transaction.cjs.
# The image series. bin/imgver publishes max(this, the highest semver already on
# ghcr.io/hanzoai/sign) plus a patch, and exactly this when it is the higher. It
# is stated here because package.json carries 2.7.1, the upstream Documenso
# release, which is not this image's series.
version: 0.2.0
test: test:
- name: build - name: build
run: | run: |
@@ -25,3 +34,11 @@ test:
npm ci --no-audit --no-fund npm ci --no-audit --no-fund
npm run lint:tx npm run lint:tx
npx turbo run build --filter=@hanzo/esign-remix npx turbo run build --filter=@hanzo/esign-remix
images:
- name: sign
context: .
dockerfile: docker/Dockerfile
repo: ghcr.io/hanzoai/sign
# One architecture: the live image and its pin are amd64.
platforms: [linux/amd64]