Repository navigation
feat(ui-react): capture the full [data-theme] × OS theme matrix in vi… #30
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: Test - CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| jobs: | |
| ci: | |
| runs-on: ubuntu-latest | |
| env: | |
| WORKSPACES: >- | |
| @constructor-lab/ui-kit-demo | |
| @constructor-lab/ui-kit-demos | |
| @constructor-lab/uikit-docs | |
| @constructor-lab/tokens | |
| @constructor-lab/icons-react | |
| @constructor-lab/icons-svg | |
| @constructor-lab/ui-react | |
| @constructor-lab/ui-spec | |
| @constructor-lab/figma-icons-fetcher | |
| @constructor-lab/figma-token-exporter | |
| @constructor-lab/style-dictionary | |
| @constructor-lab/token-emit | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v6 | |
| with: | |
| fetch-depth: 0 | |
| - name: Detect published-workspace changes | |
| if: "github.event_name == 'pull_request' && github.event.pull_request.title != 'chore(release): version packages'" | |
| id: changeset_filter | |
| uses: dorny/paths-filter@v4 | |
| with: | |
| list-files: shell | |
| filters: | | |
| published: | |
| - 'packages/ui-react/**' | |
| - 'packages/icons-react/**' | |
| - 'packages/tokens/**' | |
| changeset: | |
| - '.changeset/*.md' | |
| - name: Enforce changeset for published-surface PRs | |
| if: "github.event_name == 'pull_request' && github.event.pull_request.title != 'chore(release): version packages'" | |
| env: | |
| PUBLISHED_FILES: ${{ steps.changeset_filter.outputs.published_files }} | |
| HAS_CHANGESET: ${{ steps.changeset_filter.outputs.changeset }} | |
| run: | | |
| set -euo pipefail | |
| if [ -z "${PUBLISHED_FILES:-}" ]; then | |
| echo "No published-workspace changes detected." | |
| exit 0 | |
| fi | |
| requires_changeset=false | |
| while IFS= read -r file; do | |
| [ -z "$file" ] && continue | |
| case "$file" in | |
| # docs / metadata | |
| */README.md|*/CHANGELOG.md|*/CONTRIBUTING.md|*/AGENTS.md|*/context/*) | |
| ;; | |
| # test-only/story-only changes | |
| */__tests__/*|*.test.*|*.spec.*|*.stories.*) | |
| ;; | |
| *) | |
| requires_changeset=true | |
| echo "Published-surface change detected: $file" | |
| ;; | |
| esac | |
| done <<< "$PUBLISHED_FILES" | |
| if [ "$requires_changeset" = true ] && [ "${HAS_CHANGESET}" != "true" ]; then | |
| echo "A changeset is required for published-surface changes." | |
| echo "Run 'pnpm changeset' and commit the generated .changeset/*.md file." | |
| exit 1 | |
| fi | |
| if [ "$requires_changeset" = true ]; then | |
| echo "Changeset check passed." | |
| else | |
| echo "Only non-release-impacting published-workspace files changed." | |
| fi | |
| - name: Setup PNPM | |
| uses: pnpm/action-setup@v6 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: 22 | |
| cache: 'pnpm' | |
| - name: Get pnpm store directory | |
| shell: bash | |
| run: | | |
| echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV | |
| - name: Cache node modules | |
| id: cache-pnpm | |
| uses: actions/cache@v6 | |
| env: | |
| cache-name: cache-node-modules | |
| with: | |
| path: ${{ env.STORE_PATH }} | |
| key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('pnpm-lock.yaml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-${{ env.cache-name }}- | |
| ${{ runner.os }}- | |
| # --frozen-lockfile: refuse the install if pnpm-lock.yaml is out of | |
| # sync with package.json. This is what guarantees CI sees the exact | |
| # tree a contributor saw locally. | |
| - name: Install dependencies | |
| run: pnpm install --frozen-lockfile | |
| # Apps import the libraries by package name, so their dist (incl. types) | |
| # must exist before `pnpm -r typecheck`. Building ui-react's graph covers | |
| # @constructor-lab/tokens (generated CSS), icons-react, and the design-data packages. | |
| - name: Build library dependencies | |
| run: pnpm --filter "@constructor-lab/ui-react..." run build | |
| - name: Lint (per workspace) | |
| run: | | |
| set -euo pipefail | |
| for workspace in $WORKSPACES; do | |
| pnpm --filter "$workspace" lint | |
| done | |
| - name: Format check | |
| run: pnpm format:check | |
| # Generate the fumadocs .source files needed by apps/docs typecheck. | |
| - name: Generate fumadocs source | |
| run: pnpm --filter @constructor-lab/uikit-docs exec fumadocs-mdx | |
| - name: Typecheck (per workspace) | |
| run: | | |
| set -euo pipefail | |
| for workspace in $WORKSPACES; do | |
| pnpm --filter "$workspace" typecheck | |
| done | |
| # Build runs last so the topological build order (ui → demo / docs) | |
| # is exercised against the same lockfile we just installed from. | |
| - name: Build | |
| run: pnpm -r build | |
| # @constructor-lab/tokens ships generated, committed artifacts (css/scss/js/dtcg). | |
| # Fail the build if a token change wasn't re-generated + committed (the | |
| # build above is idempotent). | |
| - name: Verify generated tokens are committed | |
| run: git diff --exit-code -- packages/tokens/css packages/tokens/scss packages/tokens/js packages/tokens/dtcg | |
| - name: Test (per workspace) | |
| run: | | |
| set -euo pipefail | |
| for workspace in $WORKSPACES; do | |
| pnpm --filter "$workspace" test | |
| done | |
| # `test` no longer runs ui-react's vitest `typecheck` block — it made every | |
| # `vitest run` also run `tsc` per test file, at 5–10× the cost, and a check | |
| # too slow to run is a check that cannot fail. Moving it costs no coverage: | |
| # the type-test files are inside the tsconfig `include`, so the per-workspace | |
| # `typecheck` step above already reports every `expectTypeOf` failure as an | |
| # ordinary type error (measured — a false assertion surfaces as `TS2344`). | |
| # This step adds what `tsc` cannot: per-file and per-test-name attribution. | |
| # | |
| # ui-react only, because it is the only workspace with the block, and | |
| # `pnpm --filter` fails outright on a package with no such script. | |
| # `src/__tests__/typecheck-gate.test.ts` asserts the coupling that keeps the | |
| # redundancy true. | |
| - name: Type tests (ui-react) | |
| run: pnpm --filter @constructor-lab/ui-react test:types | |
| # `*.browser.test.tsx` — suites that assert real layout (resolved column | |
| # widths, truncation at a given container width, pinned-column geometry, | |
| # pointer drags with real capture). `vitest.config.ts` excludes them from | |
| # `pnpm test` on purpose, so without this step they run nowhere: the | |
| # ui-blocks DataGrid sync added 948 lines of them that no runner had ever | |
| # executed. See `packages/ui-react/vitest.browser.config.ts`. | |
| # | |
| # ui-react only, for the same reason as the type tests: it is the only | |
| # workspace with the script, and `pnpm --filter` fails outright on a package | |
| # that has none. | |
| - name: Install Chromium for browser tests | |
| run: pnpm --filter @constructor-lab/ui-react exec playwright install --with-deps chromium | |
| - name: Browser tests (ui-react) | |
| run: pnpm --filter @constructor-lab/ui-react test:browser |