Changeset 0.17.2 (#77)

This commit is contained in:
2026-02-28 11:58:27 +00:00
parent 856dc9b0ac
commit a008dac488
26 changed files with 3018 additions and 116 deletions

View File

@@ -1,15 +1,24 @@
# .gitea/workflows/ci.yaml
# ============================================
# Chat Switchboard - CI/CD Pipeline (v0.17.1)
# Chat Switchboard - CI/CD Pipeline (v0.17.2)
# ============================================
# Cluster deployments use SEPARATE FE + BE images.
# Unified image is for Docker Hub only (docker-compose use).
#
# Pipeline:
# 1a. Frontend tests (Node.js — contracts, model logic, policy wiring)
# 1b. Go test (Postgres — all PRs and pushes)
# 1c. Go test (SQLite — compilation + store verification)
# 2. Build + Deploy (depends on all test jobs passing)
# 0. Detect changes (path-based gating for all downstream jobs)
# 1a. Frontend tests — skipped if only BE/docs changed
# 1b. Go test (PG) — skipped if only FE/docs changed
# 1c. Go test (SQLite) — skipped if only FE/docs changed
# 2. Build + Deploy — skipped if docs-only change
#
# Path gating rules:
# src/, src/editor/ → frontend tests
# server/, scripts/db-* → backend tests (PG + SQLite)
# Dockerfile*, k8s/, .gitea/ → all tests (infra change)
# docs/, *.md → skip all tests + deploy
# VERSION, scripts/* → frontend + backend tests
# Tags (v*) → always full pipeline
#
# Deployment mapping (single domain, path-based):
# PR → FE + BE :dev → switchboard.DOMAIN/dev/ (DB wipe + fresh schema)
@@ -76,11 +85,99 @@ env:
DOCKERHUB_IMAGE: ${{ vars.DOCKERHUB_IMAGE || 'gobha/chat-switchboard' }}
jobs:
# ── Stage 0: Detect Changed Paths ──────────────
# Sets output flags so downstream jobs can skip when irrelevant.
# Tags always set all flags true (full pipeline for releases).
detect-changes:
runs-on: ubuntu-latest
outputs:
frontend: ${{ steps.filter.outputs.frontend }}
backend: ${{ steps.filter.outputs.backend }}
infra: ${{ steps.filter.outputs.infra }}
docs_only: ${{ steps.filter.outputs.docs_only }}
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0 # need history for diff
- name: Detect changed paths
id: filter
run: |
# Tags = release → run everything
if [[ "${{ gitea.ref }}" == refs/tags/v* ]]; then
echo "frontend=true" >> "$GITHUB_OUTPUT"
echo "backend=true" >> "$GITHUB_OUTPUT"
echo "infra=true" >> "$GITHUB_OUTPUT"
echo "docs_only=false" >> "$GITHUB_OUTPUT"
echo "🏷️ Tag build — running full pipeline"
exit 0
fi
# Determine diff base
if [[ "${{ gitea.event_name }}" == "pull_request" ]]; then
BASE="${{ gitea.event.pull_request.base.sha }}"
HEAD="${{ gitea.event.pull_request.head.sha }}"
else
# Push to main — compare with previous commit
BASE="${{ gitea.event.before }}"
HEAD="${{ gitea.sha }}"
fi
echo "Comparing ${BASE:0:8}..${HEAD:0:8}"
CHANGED=$(git diff --name-only "${BASE}" "${HEAD}" 2>/dev/null || git diff --name-only HEAD~1 HEAD)
echo "Changed files:"
echo "${CHANGED}" | sed 's/^/ /'
# Classify
FE=false; BE=false; INFRA=false; DOCS=false; OTHER=false
while IFS= read -r file; do
[[ -z "$file" ]] && continue
case "$file" in
src/js/*|src/css/*|src/editor/*|src/index.html|src/sw.js|src/manifest.json|src/vendor/*)
FE=true ;;
server/*|scripts/db-*)
BE=true ;;
.gitea/*|k8s/*|Dockerfile*|docker-compose*|docker-entrypoint*|nginx.conf)
INFRA=true ;;
docs/*|*.md|CHANGELOG.md|LICENSE)
DOCS=true ;;
VERSION|scripts/*)
FE=true; BE=true ;;
*)
OTHER=true ;;
esac
done <<< "${CHANGED}"
# Docs-only: only docs changed, nothing else
if [[ "$DOCS" == "true" && "$FE" == "false" && "$BE" == "false" && "$INFRA" == "false" && "$OTHER" == "false" ]]; then
DOCS_ONLY=true
else
DOCS_ONLY=false
fi
echo "frontend=${FE}" >> "$GITHUB_OUTPUT"
echo "backend=${BE}" >> "$GITHUB_OUTPUT"
echo "infra=${INFRA}" >> "$GITHUB_OUTPUT"
echo "docs_only=${DOCS_ONLY}" >> "$GITHUB_OUTPUT"
echo ""
echo "━━━ Change Detection ━━━"
echo " frontend: ${FE}"
echo " backend: ${BE}"
echo " infra: ${INFRA}"
echo " docs_only: ${DOCS_ONLY}"
# ── Stage 1a: Frontend Tests ─────────────────
# API contract tests, model processing, policy wiring audits.
# Uses Node.js built-in test runner (node --test), zero npm deps.
#
# Runs when: frontend files changed, infra changed, or not docs-only.
# Skipped when: only backend or docs changed.
test-frontend:
runs-on: ubuntu-latest
needs: [detect-changes]
if: needs.detect-changes.outputs.frontend == 'true' || needs.detect-changes.outputs.infra == 'true'
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -106,8 +203,13 @@ jobs:
run: node --test src/js/__tests__/*.test.js
# ── Stage 1b: Go Build & Test (Postgres) ─────
#
# Runs when: backend files changed or infra changed.
# Skipped when: only frontend or docs changed.
test:
runs-on: ubuntu-latest
needs: [detect-changes]
if: needs.detect-changes.outputs.backend == 'true' || needs.detect-changes.outputs.infra == 'true'
env:
GOPRIVATE: git.gobha.me/*
GONOSUMCHECK: git.gobha.me/*
@@ -190,8 +292,13 @@ jobs:
# Verifies SQLite backend compiles, stores work, and handler
# integration tests pass against an in-memory SQLite database.
# No external database or provider keys required.
#
# Runs when: backend files changed or infra changed.
# Skipped when: only frontend or docs changed.
test-sqlite:
runs-on: ubuntu-latest
needs: [detect-changes]
if: needs.detect-changes.outputs.backend == 'true' || needs.detect-changes.outputs.infra == 'true'
env:
GOPRIVATE: git.gobha.me/*
GONOSUMCHECK: git.gobha.me/*
@@ -244,9 +351,19 @@ jobs:
echo "✓ SQLite integration tests complete"
# ── Stage 2: Build, Database, Deploy ─────────
#
# Depends on all test jobs. Skipped jobs (due to path gating)
# are treated as successful — no blocking.
#
# Skipped entirely for docs-only changes (nothing to build).
build-and-deploy:
runs-on: ubuntu-latest
needs: [test, test-frontend, test-sqlite]
needs: [detect-changes, test, test-frontend, test-sqlite]
# Run unless: a needed job failed, the workflow was cancelled, or it's docs-only.
# Skipped test jobs (path-gated) are fine — they don't block.
if: |
!cancelled() && !failure() &&
needs.detect-changes.outputs.docs_only != 'true'
steps:
- name: Checkout
uses: actions/checkout@v4