mirror of
https://github.com/hanzoai/chat.git
synced 2026-09-30 20:51:17 +00:00
hanzo.chat ships as a site, not an image
hanzo.chat is the chat2 project on the Sites plane, served by cloud by Host, and nothing runs ghcr.io/hanzoai/chat2. So the lane that matters is the site: build the export, publish it to s3://hanzo-sites/hanzo/chat2. The image and its Dockerfile go. The trigger named master and this repository has only main, so no push has run this lane since the rename. Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
@@ -3,27 +3,12 @@ name: CI/CD
|
||||
# The caller, and deliberately nothing else: triggers plus the import. All real
|
||||
# config is the repo-root hanzo.yml, which platform.hanzo.ai reads too.
|
||||
#
|
||||
# `.hanzo/workflows`, NOT `.github/workflows`, on BOTH sides of the `uses:`.
|
||||
# Gitea collects workflows from the first of WORKFLOW_DIRS present in the commit
|
||||
# and resolves a reusable through the same allowlist, and github.com has zero
|
||||
# self-hosted runners for this org — so a job asking for linux-amd64
|
||||
# there is never claimed, and an unclaimable job does not fail, it waits out the
|
||||
# 24h timeout while the next push queues behind it. Naming the .github path is
|
||||
# what took hanzoai/console's CI down.
|
||||
#
|
||||
# `master`, because that is this repository's default branch — measured, not
|
||||
# assumed (`git remote show origin` → HEAD branch: master). `main` exists too
|
||||
# and currently points at the same commit, which is a duplicate ref rather than
|
||||
# a second lane: listing both would put two runs on one tag, and since the
|
||||
# version comes from hanzoai/ci's bin/imgver deriving max(declared, published)+1
|
||||
# patch, two concurrent runs race to mint the same one. One branch, one lane.
|
||||
# Delete the duplicate and this list stays one entry.
|
||||
# `main` is the only branch this repository has; a trigger naming another one
|
||||
# never fires, which is how this lane sat idle.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
# A `v*` tag is a RELEASE and publishes an image named after it, verbatim.
|
||||
tags: ['v*']
|
||||
branches: [main]
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
|
||||
-40
@@ -1,40 +0,0 @@
|
||||
# syntax=docker/dockerfile:1.7
|
||||
# Hanzo Chat — the Vite SPA built once, served by hanzoai/spa.
|
||||
FROM node:24-alpine AS build
|
||||
WORKDIR /build
|
||||
ENV CI=true PNPM_HOME=/pnpm PATH=$PNPM_HOME:$PATH
|
||||
RUN corepack enable && corepack prepare [email protected] --activate
|
||||
|
||||
# Manifests first so a source edit re-runs the build and not the resolve.
|
||||
#
|
||||
# pnpm-workspace.yaml is REQUIRED even though this repo has no workspace
|
||||
# members: every dependency is `catalog:`, and the catalog lives in that file.
|
||||
# Without it the install resolves nothing and fails on the first `catalog:`.
|
||||
#
|
||||
# FROZEN, and the lockfile ships. A resolver left free to drift builds a tree
|
||||
# nobody ran — hanzoai/id shipped exactly that, where a free resolve moved vite
|
||||
# to a different version than the tested lockfile and the image died on a
|
||||
# missing module while the same commit built cleanly from the lockfile. Frozen,
|
||||
# the image gets the tree the gate passed against, and a stale lockfile fails
|
||||
# here, loudly, instead of silently building something else.
|
||||
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
|
||||
RUN pnpm install --frozen-lockfile
|
||||
|
||||
COPY tsconfig.json vite.config.ts index.html ./
|
||||
COPY src src
|
||||
|
||||
# `pnpm build` is `tsc --noEmit && vite build`, so the typecheck is part of the
|
||||
# image and dead code cannot ship (tsconfig sets noUnusedLocals).
|
||||
#
|
||||
# `&&`, not `;`: with `;` the RUN carries the status of the LAST command and a
|
||||
# failed build would be masked. A vite build that emits nothing still exits 0,
|
||||
# which is what the two file tests are for.
|
||||
RUN pnpm build && [ -s dist/index.html ] && [ -d dist/assets ]
|
||||
|
||||
# hanzoai/spa, not hanzoai/static, and not a webserver of our own: this is a
|
||||
# client-routed SPA, so it needs index.html served for every path. hanzoai/static
|
||||
# defaults to `Content-Security-Policy: default-src 'none'`, which blocks the
|
||||
# bundle the page loads and leaves a blank screen. Defaults: PORT=3000, ROOT=/public.
|
||||
FROM ghcr.io/hanzoai/spa:1.4.13
|
||||
COPY --from=build /build/dist /public
|
||||
EXPOSE 3000
|
||||
@@ -1,21 +1,16 @@
|
||||
# Hanzo CI/CD — chat. All real config is here; .hanzo/workflows/cicd.yml is
|
||||
# Hanzo CI/CD — chat. All real config is here; .github/workflows/cicd.yml is
|
||||
# triggers and an import of hanzoai/ci.
|
||||
|
||||
test:
|
||||
# Frozen, so the gate resolves the same tree the Dockerfile does. The estate
|
||||
# note that this repo needs --no-frozen-lockfile is stale: the lockfile has
|
||||
# caught up with the `catalog:` conversion and a frozen install now resolves
|
||||
# clean.
|
||||
# Frozen, so the gate resolves the same tree the site is built from.
|
||||
- name: install
|
||||
run: |
|
||||
set -e
|
||||
corepack enable
|
||||
pnpm install --frozen-lockfile
|
||||
|
||||
# Verbatim the build line the image runs, run before there is an image, so a
|
||||
# break arrives in a minute instead of after a full layer stack. `pnpm build`
|
||||
# is `tsc --noEmit && vite build`. A vite build that emits nothing still exits
|
||||
# 0, hence the file test.
|
||||
# `pnpm build` is `tsc --noEmit && vite build`. A vite build that emits
|
||||
# nothing still exits 0, hence the file test.
|
||||
- name: build
|
||||
run: |
|
||||
set -e
|
||||
@@ -31,28 +26,11 @@ test:
|
||||
set -e
|
||||
pnpm test
|
||||
|
||||
images:
|
||||
# NOT `ghcr.io/hanzoai/chat`, and the name is the whole reason.
|
||||
#
|
||||
# That name belongs to the LibreChat fork, which is built out of the SEPARATE
|
||||
# repo hanzoai/chat-v1 by its own .hanzo/workflows/deploy.yml, and it is the
|
||||
# image two live Deployments run: universe charts/app/values/hanzo/chat.yaml
|
||||
# (hanzo.chat, 1.0.273) and lux-chat.yaml (lux.chat, 1.0.268). Publishing this
|
||||
# application under that name would put two different programs behind one
|
||||
# reference, and the pods are replicas:1 + strategy:Recreate over an RWO SQLite
|
||||
# claim, so there is no half-rolled state to notice it in — the next pull is
|
||||
# the whole service.
|
||||
#
|
||||
# This name is the package's own (@hanzo/chat2). It stops being needed when
|
||||
# chat-v1 is retired and this repo inherits `chat`; until then two names is the
|
||||
# honest count, because there are two applications.
|
||||
- name: chat2
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
repo: ghcr.io/hanzoai/chat2
|
||||
platforms: [linux/amd64]
|
||||
# No build_secrets, and none belong here. The publishable keys in
|
||||
# src/brand.ts are pk- values, public by construction, and each is held in
|
||||
# its OWN brand record — so the host that selects the brand selects the key
|
||||
# with it. That is what keeps one bundle serving hanzo.chat, lux.chat and
|
||||
# zoolabs.io without filing three brands' traffic under one tenant.
|
||||
# hanzo.chat is this export: the `chat2` project on the Sites plane
|
||||
# (s3://hanzo-sites/hanzo/chat2), served by cloud by Host and calling only
|
||||
# api.hanzo.ai. No image, no pod.
|
||||
site:
|
||||
slug: chat2
|
||||
dir: dist
|
||||
build: corepack enable && pnpm install --frozen-lockfile && pnpm build
|
||||
on: [main]
|
||||
|
||||
Reference in New Issue
Block a user