Files
twenty/.github/workflows/ci-client-sdk.yaml
Paul Rastoin b88e49126d Port genql 3.0.5 test suite and run twenty-client-sdk tests in CI (#25092)
Follow-up to twentyhq/core-team-issues#2819 (genql vendor challenge):
give the vendored genql fork a real safety net — upstream's own test
suite, ported and enforced — and make CI actually run this package's
tests.

## Context

`packages/twenty-client-sdk/src/generate/genql` is a vendored copy of
`@genql/cli@3.0.5` (upstream commit
`4a547db46a9a614cc2b5958e28674af351898464`, now pinned in its README).
Diffing it against upstream showed the engine (`render/`, `runtime/`) is
near-verbatim while the orchestration was deliberately rewritten to drop
the vulnerable dependency graph. What was missing: behavioral test
coverage for the engine (the existing snapshot test pins bytes, not
behavior), and any CI running the package's tests at all.

## Ported upstream 3.0.5 test suite

`src/generate/__tests__/upstream-3.0.5/` ports the test suite of
remorses/genql at the vendored version (mapping table in its README):

- **Integration**: upstream's fixture schema (byte-verbatim),
`simple.ts` (query-generation snapshots) and `execution.ts` (end-to-end:
unions, interfaces, union-implements-interface, `__scalar`, batching,
`GenqlError`, sync/async header functions).
- **Unit**: `typeSelection` (the type-level `FieldsSelection` contract),
`typeMap`, `renderTyping`, `comment`, `RenderContext`, `renderSchema`.

This mirrors upstream's own CI model (its `genall` step regenerated the
client from the fixture schema on every run, typechecked it with the
tests, and ran the suite against it) and adds byte-level pinning
upstream did not have.

Adaptations (documented in the dir's README):
- apollo-server v3 (deprecated) is replaced by graphql-js `graphql()`
behind an injected `fetch`/`fetcher` — the identical client code path,
no network, zero new dependencies.
- mocha/sucrase/snap-shot-it/tsd become vitest.
- A generated fixture client is checked in (pinned by a drift test with
an `UPDATE_GENQL_UPSTREAM_FIXTURE=1` refresh mode) so the type-level
assertions compile and are verified by the package typecheck.
- tsd's `expectType` assertions are strengthened to exact: upstream
typechecked its tests with plain tsc, never the tsd CLI, and under plain
tsc `expectType<T>(value)` is only an assignability check — several
assertions were looser than the real types. The exact assertions here
pin what the 3.0.5 engine actually generates (`undefined` for absent
fields, never `null`; literal `__typename` types).
- Upstream's `typeMap` assertions ran in output-logging mode with stale
expected values; they are enabled and corrected to the engine's actual
output.

Not ported: `parse`/`printer` tests (cover code Twenty did not vendor)
and the subscription suite (already skipped upstream).

Also: `runtime-templates.ts` (Twenty's `?raw` bundling mechanism, not
upstream code) moved out of the vendored tree to `src/generate/`, so
`src/generate/genql/` contains only the fork plus its README and LICENSE
— and the file gains oxlint/oxfmt coverage it was previously excluded
from.

## Dedicated CI workflow

The package's tests never ran in CI: `ci-sdk.yaml`'s changed-files gate
does not include `packages/twenty-client-sdk/**`, and its matrix runs
`test:unit` while the package only defines `test`. This adds
`ci-client-sdk.yaml` (modeled on `ci-shared.yaml`): lint / typecheck /
test matrix via `nx affected` on a new `scope:client-sdk` tag, gated on
`twenty-client-sdk` and `twenty-shared` changes. The `test` target now
declares `dependsOn: ["^build"]` so `twenty-shared/dist` is fresh
wherever the suite runs (CI and locally).

## Validation

- `twenty-client-sdk` vitest: 15 files, 111 tests passing.
- `tsgo -p tsconfig.json --noEmit`: clean (this is what arms the
`@ts-expect-error`/`expectTypeOf` assertions).
- `nx lint twenty-client-sdk` (oxlint + oxfmt): clean.
- The `client-sdk-test` (lint / typecheck / test) jobs from the new
workflow run green on this PR.
2026-09-01 07:57:33 +00:00

56 lines
1.5 KiB
YAML

name: CI Client SDK
on:
pull_request:
merge_group:
permissions:
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
jobs:
changed-files-check:
if: github.event_name != 'merge_group'
uses: ./.github/workflows/changed-files.yaml
with:
files: |
packages/twenty-client-sdk/**
packages/twenty-shared/**
yarn.lock
.github/workflows/ci-client-sdk.yaml
!packages/twenty-client-sdk/package.json
client-sdk-test:
needs: changed-files-check
if: needs.changed-files-check.outputs.any_changed == 'true'
timeout-minutes: 30
runs-on: ubuntu-latest
env:
NODE_OPTIONS: '--max-old-space-size=4096'
strategy:
matrix:
task: [lint, typecheck, test]
steps:
- name: Fetch custom Github Actions and base branch history
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
fetch-depth: 10
- name: Install dependencies
uses: ./.github/actions/yarn-install
- name: Run ${{ matrix.task }} task
uses: ./.github/actions/nx-affected
with:
tag: scope:client-sdk
tasks: ${{ matrix.task }}
ci-client-sdk-status-check:
if: always() && !cancelled()
timeout-minutes: 5
runs-on: ubuntu-latest
needs: [changed-files-check, client-sdk-test]
steps:
- name: Fail job if any needs failed
if: contains(needs.*.result, 'failure')
run: exit 1