ADORSYS-GIS / ADORSYS-GIS/converse-frontends
[Story]: every workspace package is typechecked under its own tsconfig, not incidentally via apps/console
- 主要言語
- TypeScript
- スター
- 0
- フォーク
- 0
- 平均マージ
- 1時間 49分
- マージ済み PR(30日)
- 253
説明
## Story Statement
As a developer changing a shared workspace package (`authz-rpc`, `hooks`, `api-rest`, `i18n`, `api-native`),
I want CI to typecheck that package under its own `tsconfig.json`,
so that a type error in it fails the PR that introduced it, instead of surfacing later — or never.
## Real Intent
The Typecheck job in `.github/workflows/test.yml` discovers work by globbing `tsconfig.json` at `-maxdepth 2` under `apps/` and `packages/`. **Only 4 of 10 workspaces have one** (`apps/authz-ui`, `apps/console`, `packages/chart-core`, `packages/ui-web`), so five packages are never checked under their own compiler settings.
The job's author clearly cared about this gate not being hollow — it carries an explicit no-op guard:
```
if [ "${#tsconfigs[@]}" -eq 0 ]; then
echo "::error::No tsconfig.json found under apps/ or packages/ — the typecheck gate would be a no-op"
```
That guard fires only when the count is **zero**. It cannot notice that the count is 4 when it should be 9, which is the actual state today. This is the "green does not mean tested" failure mode: the job passes having never looked at most of the packages.
Found while upgrading cratestack 0.9.4 → 0.10.0 (#433). That PR regenerated `packages/authz-rpc`'s client and changed its emitted peer bounds — and `packages/authz-rpc` is one of the packages with no `tsconfig.json` of its own.
## Background and Context
The coverage is **partial, not absent** — worth stating precisely so this isn't over- or under-sold:
| Package | src files | Coverage today |
|---|---|---|
| `packages/hooks` | 34 | Incidental only — via `apps/console`'s import graph |
| `packages/api-rest` | 20 | Incidental only — via `apps/console` |
| `packages/authz-rpc` | 9 | Incidental only — via `apps/console` |
| `packages/i18n` | 3 | **None** — not a dependency of either app |
| `packages/api-native` | 1 | **None** — not a dependency of either app |
The three "incidental" packages set `"main"`/`"types"` to `src/index.ts`, so `apps/console`'s `tsc --noEmit` does follow into their real source. That is genuine coverage, and it is why this is a gap rather than an outage. What it does **not** cover:
- Code not reachable from `index.ts` — including every `*.test.ts` in those packages, and `authz-rpc`'s separate `./refine` export unless console happens to import it.
- The package's **own** compiler settings. They are checked under `apps/console`'s Next.js config (its `strict`, `lib`, `jsx`, `types`), not their own. A package intending stricter settings than console's silently doesn't get them.
- `apps/authz-ui` depends only on `@lightbridge/ui-web`, so it contributes no coverage here.
## Source of truth (links)
- Observed during #433 (cratestack 0.9.4 → 0.10.0), which regenerated `packages/authz-rpc`'s client — a package outside the gate.
- `.github/workflows/test.yml`, the `Typecheck all workspaces` step and its zero-count no-op guard.
- Estate rule that a gate which can pass without running is not a gate (the same reasoning behind lightbridge-authz's `just it-tests` `check_binary` guards, which assert a non-zero test count because "a skip is not a pass").
## Acceptance Criteria
### Functional
- [ ] Given a workspace package under `apps/` or `packages/` containing TS source, when CI runs Typecheck, then that package is checked under **its own** `tsconfig.json`.
- [ ] Given a type error introduced in `packages/hooks`, `packages/api-rest`, `packages/authz-rpc`, `packages/i18n` or `packages/api-native`, when CI runs, then the Typecheck job **fails**.
- [ ] Given a type error only in a package's `*.test.ts`, when CI runs, then it is still caught.
### Negative / Edge Cases
- [ ] Given a **new** workspace package added with no `tsconfig.json`, when CI runs, then the job **fails loudly** rather than silently skipping it. (This is the real defect — the guard must detect "fewer tsconfigs than packages with TS source", not just "zero".)
- [ ] Given `packages/authz-rpc/generated/` (gitignored, regenerated by `postinstall`), when CI runs, then it stays excluded — it has its own `tsconfig.json` and is not hand-maintained.
- [ ] Given a package intentionally without TS source, when CI runs, then it does not fail the new guard.
### Non-Functional
- [ ] Typecheck job wall-clock stays within roughly 2× today's ~1 min; if adding five projects costs more, consider TS project references / `--build` with incremental caching.
- [ ] Prove the gate works: introduce a deliberate type error in each newly-covered package, confirm CI goes red **for that reason**, then revert. A gate added without watching it fail has not been verified.
## Out of Scope
- Fixing whatever type errors the new coverage surfaces — if the backlog is non-trivial, split into a follow-up per package.
- The 2 pre-existing `pnpm lint` errors on `main` (`react-hooks/rules-of-hooks` in `apps/console/src/client/use-shared-mutation.test.tsx`; setState-in-effect in `apps/console/src/containers/use-rename-account-dialog.ts`). Related smell, separate story.
- Changing any package's public entrypoints or build outputs.
## Dependencies and Blockers
None. Self-contained CI + tsconfig work.
## Assumptions
- Each of the five packages *should* be typechecked. If `api-native` is dead code from the Expo retirement (#279), deleting it is a legitimate alternative to adding a tsconfig — decide before implementing.
- A shared `tsconfig.base.json` that packages extend is preferable to five hand-rolled configs. Confirm against how `packages/ui-web` and `packages/chart-core` configure themselves today.
## Implementation Notes
Guidance, not gospel:
1. Add a `tsconfig.json` per package, extending a shared base, with `noEmit` for check-only packages.
2. Replace the zero-count guard with a real completeness check: enumerate packages containing `src/**/*.ts(x)`, assert each has a discoverable `tsconfig.json`, and fail listing the missing ones. That is the part which keeps this from regressing the next time a package is added.
3. Consider `tsc --build` with project references so the five new projects reuse each other's output instead of recompiling per invocation.
## Test Expectations
- CI: the Typecheck job covers 9 projects (or whatever the true count is), not 4.
- Regression: the completeness guard fails when a package with TS source lacks a tsconfig — verified by temporarily removing one.
- Mutation-style: a deliberate type error in each newly-covered package turns CI red, then is reverted.
## Verification evidence
Evidence the gap is real, gathered on 2026-08-31 against `main`:
```bash
$ for d in apps/*/ packages/*/; do [ -f "$d/tsconfig.json" ] || echo "NO tsconfig: $d"; done
NO tsconfig: packages/api-native/
NO tsconfig: packages/api-rest/
NO tsconfig: packages/authz-rpc/
NO tsconfig: packages/hooks/
NO tsconfig: packages/i18n/
$ find packages/authz-rpc -name tsconfig.json -not -path "*/node_modules/*"
packages/authz-rpc/generated/tsconfig.json # excluded by the CI loop's -not -path '*/generated/*'
```
Running CI's exact discovery loop locally yields **4** tsconfigs and `TYPECHECK_STATUS=0` — green, having never checked five packages under their own settings.
Not yet verified (for the implementer): how many type errors the new coverage actually surfaces.
## Human accountable owner
@stephane-segning
## AI Usage Declaration
Drafting this story, Refining acceptance criteria, Suggesting implementation.
Drafted by Claude Opus 5 (Claude Code) after observing the gap while upgrading cratestack in #433. All command output quoted above is from real runs against `main`.
## Human verification completed
- [ ] I checked the story against the source of truth
- [ ] I confirmed the acceptance criteria
- [ ] I reviewed the implementation approach
- [ ] I am the accountable owner and accept responsibility for this story.
**Left unticked deliberately** — these are the accountable owner's assertions to make, not the drafting agent's.
コントリビューションガイド
評価
この issue はまだ評価されていません。