fix(chat): structured output vs grounding and output masking (#52) #230
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |