Skip to content

fix(chat): structured output vs grounding and output masking (#52) #230

fix(chat): structured output vs grounding and output masking (#52)

fix(chat): structured output vs grounding and output masking (#52) #230

Workflow file for this run

name: ci
on:
push:
branches: [main]
tags: ["v*"]
pull_request:
# Least privilege: every job here only reads the repo (checkout/build/test) —
# none comment on PRs, upload SARIF, or publish. Setting the token to read-only
# at the top level applies to all jobs (a job may widen it locally if ever needed).
permissions:
contents: read
# One live run per ref: a force-push or rapid re-push cancels the superseded
# run instead of stacking duplicates (and a PR branch no longer runs twice via
# push + pull_request).
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
# GitHub's DEFAULT shell is `bash -e {0}` — WITHOUT pipefail. Steps that pipe a
# command into `tee` (e.g. `pnpm test | tee log`) would otherwise take tee's
# exit code (0), so a FAILING test suite would pass the step. Forcing an explicit
# `bash` shell adds `-o pipefail`, so the pipeline fails when the left side does.
defaults:
run:
shell: bash
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: modelgov
ports:
- 55432:5432
options: >-
--health-cmd "pg_isready -U postgres"
--health-interval 5s
--health-timeout 3s
--health-retries 12
env:
DATABASE_URL: postgres://postgres:postgres@localhost:55432/modelgov
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 10.19.0
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Audit production dependencies
# Gating: a PR must not introduce a production dependency with a known
# HIGH+ advisory. If a newly-disclosed upstream advisory reds main, that
# is the intended signal to bump the dependency (or add a reviewed
# `pnpm.auditConfig.ignoreCves` entry) — not to merge around it.
run: pnpm audit --prod --audit-level high
- name: Wait for Postgres
run: npx wait-on tcp:localhost:55432 --timeout 60000
- run: pnpm generate-sdk-types
- name: Generated SDK types are committed
run: |
git diff --exit-code packages/sdk-typescript/src/generated/config-types.ts \
|| (echo "::error::Run pnpm generate-sdk-types and commit the result" && exit 1)
- run: pnpm build
- run: pnpm typecheck
- run: pnpm lint
- run: pnpm check:file-sizes
- name: Policy regression tests
run: pnpm modelgov test-policy --file modelgov.policy-tests.yaml
- name: Verify version surfaces
run: bash scripts/verify-versions.sh
- name: Production example deploy checks
run: pnpm exec tsx scripts/doctor-production-example.ts
- name: Validate production example config
run: OPENAI_API_KEY=x ANTHROPIC_API_KEY=x pnpm modelgov validate --config modelgov.production.example.yaml --production
- run: pnpm test:coverage 2>&1 | tee /tmp/test.log
- name: Scaffold smoke (create-modelgov)
run: pnpm exec tsx scripts/scaffold-smoke.ts
- name: Integration tests ran (not skipped)
run: |
# Every suite in this repo runs when DATABASE_URL is wired (the
# DB-gated ones are describe.skipIf(!DATABASE_URL)), so ANY skipped
# test file means the DB wasn't reachable and integration suites
# silently no-op'd. (vitest 4 dropped the per-file ↓ markers the old
# guard grepped for; the summary line is the stable signal.)
if grep -E "Test Files.*skipped" /tmp/test.log; then
echo "::error::Test files were skipped — DATABASE_URL must be set in CI"
exit 1
fi
- name: Upload coverage report
uses: actions/upload-artifact@v4
if: always()
with:
name: coverage
path: coverage/
retention-days: 14
if-no-files-found: ignore
- run: pnpm --filter @modelgov/api openapi:export
- name: OpenAPI spec is committed and current
run: |
git diff --exit-code packages/api/openapi.json \
|| (echo "::error::openapi.json is stale — run 'pnpm --filter @modelgov/api openapi:export' and commit the result" && exit 1)
- name: API boot smoke test
run: bash scripts/smoke-ci.sh
feature-flags:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:16-alpine
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: modelgov
ports:
- 55432:5432
options: >-
--health-cmd "pg_isready -U postgres"
--health-interval 5s
--health-timeout 3s
--health-retries 12
env:
DATABASE_URL: postgres://postgres:postgres@localhost:55432/modelgov
HIERARCHICAL_BUDGETS: "true"
MULTI_TENANT_POLICY: "true"
POLICY_STORE_ENABLED: "true"
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 10.19.0
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Wait for Postgres
run: npx wait-on tcp:localhost:55432 --timeout 60000
- run: pnpm build
- name: Feature-flag integration tests
run: |
pnpm exec vitest run \
--no-file-parallelism \
packages/api/test/chat-hierarchical.integration.test.ts \
packages/api/test/budget-nodes.integration.test.ts \
packages/api/test/policy-tenant.integration.test.ts \
packages/api/test/policy-store.integration.test.ts \
packages/api/test/rls-tenant.integration.test.ts 2>&1 | tee /tmp/ff-test.log
- name: Feature-flag integration tests ran (not skipped)
run: |
# Mirror the `test` job guard: these suites are all describe.skipIf(!DATABASE_URL),
# so a missing DATABASE_URL would make them silently no-op and pass.
if grep -E "Test Files.*skipped" /tmp/ff-test.log; then
echo "::error::Feature-flag integration tests were skipped — DATABASE_URL must be set in CI"
exit 1
fi
compose-e2e:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 10.19.0
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- name: Docker compose e2e (optional example stack)
run: bash scripts/example-e2e-ci.sh
terraform:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.9.8
- name: Validate AWS module
working-directory: deploy/terraform/aws
run: |
terraform fmt -check -recursive
terraform init -backend=false
terraform validate
helm:
# The chart is the recommended production path, so a broken profile is a
# shipped outage. `helm lint` is not enough — it renders with defaults, where
# the production guards are inert. This templates EVERY profile with realistic
# secrets, which is what catches a profile whose fail-closed validation the
# documented install command cannot satisfy.
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
# This job only renders templates; it never pushes. Not persisting the
# token keeps it out of the workspace git config for later steps.
persist-credentials: false
- uses: azure/setup-helm@v4
with:
version: v3.16.3
- name: Render every Helm values profile
run: bash scripts/helm-render-check.sh
python-sdk:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.9"
- name: Install Python SDK with dev extras
working-directory: packages/sdk-python
run: pip install -e ".[dev]"
- name: Run Python SDK tests
working-directory: packages/sdk-python
run: python -m pytest -q