-
Notifications
You must be signed in to change notification settings - Fork 87
chore(copilot-instructions): add the copilot-instructions.md #7926
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,193 @@ | ||||||
| # Carbon (carbon-react) — Copilot Agent Instructions | ||||||
|
|
||||||
| Trust these instructions. Only fall back to repo-wide search if something here is incorrect or incomplete. | ||||||
|
|
||||||
| ## 1. What this repo is | ||||||
|
|
||||||
| - **`carbon-react`** — Sage's React component library, published to npm. | ||||||
| - **Language / stack**: TypeScript + React 18 (peer-supports 17 & 18), styled-components v5, Storybook 8 (8.6.x, Vite builder), Rollup build, Jest (jsdom + node projects), Playwright Component Testing (Chromium only). | ||||||
| - **Size**: Large monorepo-style single package. ~90 components under [src/components/](../src/components), large `package.json` (~9.6 KB), `package-lock.json` ~800 KB. `npm ci` is slow (several minutes); the `lib/`/`esm/` build is also slow. | ||||||
| - **Distribution**: Two outputs — `lib/` (CJS) and `esm/` (ESM), both produced by Rollup + `tsc` for `.d.ts`. | ||||||
|
|
||||||
| ## 2. Required environment | ||||||
|
|
||||||
| ALWAYS use these versions; CI pins them and mismatches break installs/tests: | ||||||
|
|
||||||
| - **Node**: pinned in [.nvmrc](../.nvmrc) as `lts/krypton` (Node **24.x**, `>=24.11.0`). CI also runs Jest on Node **22**. | ||||||
| - **npm**: `>=11.11.1` (CI runs `npm install -g npm@11.11.1` before every job — do the same if the local npm is older). | ||||||
| - **OS**: Linux/macOS. Windows requires WSL. | ||||||
| - **`.npmrc`** sets `ignore-scripts=true`. After `npm ci` you MUST run `npm run prepare` (husky install) — this is what `npm run setup` does. | ||||||
|
|
||||||
| ## 3. Bootstrap (always run first, in this order) | ||||||
|
|
||||||
| ```sh | ||||||
| nvm use # picks up .nvmrc -> Node 24 | ||||||
| npm install -g npm@11.11.1 | ||||||
| npm run setup # = npm ci && npm run prepare (husky) | ||||||
| ``` | ||||||
|
|
||||||
| `npm ci` is the only supported install — never use `npm install` (lockfile is authoritative and `package-lock.json` changes will fail CI). | ||||||
|
|
||||||
| ## 4. Generated assets — design tokens (gotcha) | ||||||
|
|
||||||
| Most scripts implicitly run `generate-tokens:dev` first (it writes into `src/components/tokens-wrapper/static-tokens/`). If you invoke `jest`, `eslint`, `tsc`, or `playwright` **directly** (not via `npm run …`), run this first or imports of static tokens will fail to resolve: | ||||||
|
|
||||||
| ```sh | ||||||
| npm run generate-tokens:dev | ||||||
| ``` | ||||||
|
|
||||||
| `npm run build` uses the production variant `npm run generate-tokens` (no dark theme) — do not mix them. | ||||||
|
|
||||||
| ## 5. Validation pipeline (mirror of CI in [.github/workflows/ci.yml](workflows/ci.yml)) | ||||||
|
|
||||||
| Run these locally before pushing — CI runs the exact same commands and a PR will fail if any of them fail: | ||||||
|
|
||||||
| | Step | Command | Notes | | ||||||
| |---|---|---| | ||||||
| | Format check | `npx prettier --check './src/**/*.{js,jsx,ts,tsx}'` | Auto-fix with `npm run format`. | | ||||||
| | Lint | `npm run lint` | ESLint flat config in [eslint.config.mjs](../eslint.config.mjs). Uses `--max-warnings=636` and `--report-unused-disable-directives`; do not introduce new warnings or unused `eslint-disable` lines. | | ||||||
| | Type check | `npm run type-check` | `tsc --noEmit` against [tsconfig.json](../tsconfig.json). | | ||||||
| | Skills sync | `npm run build:skills -- --check` | Fails if files in [skills/](../skills) are stale relative to component changes. Regenerate with `npm run build:skills` and commit the diff. | | ||||||
|
Comment on lines
+49
to
+50
|
||||||
| | Unit tests | `npm test` | Sharded 4 ways in CI; matrix runs on Node 22 and Node 24. Locally use Node 24 (`.nvmrc`). Two Jest projects: `Client` (jsdom) for `*.spec.*`/`*.test.*`, `Server` (node) for `*.server.spec.*`. | | ||||||
| | Coverage | (CI merges shards) | 100% coverage policy is expected for new code. Thresholds in [coverage-thresholds.json](../coverage-thresholds.json). Run a single test file with `npm test -- path/to/file.spec.tsx`. | | ||||||
| | Build | `npm run build` | Order is fixed: `clean-lib → generate-tokens → type-check → rollup → generate package.jsons → copy svg → build:types`. | | ||||||
| | Playwright CT | `npm run test:ct` | Separate workflow [.github/workflows/playwright.yml](workflows/playwright.yml). Runs against Chromium via `mcr.microsoft.com/playwright:v1.55.1-noble` in CI. Locally requires `npx playwright install --with-deps chromium` once. Tests live in `*.pw.tsx` next to components. | | ||||||
|
|
||||||
| Common failure patterns observed: | ||||||
|
|
||||||
| - "Cannot find module .../static-tokens/..." → forgot `generate-tokens:dev` (see §4). | ||||||
| - `nwsapi` `SyntaxError` from jsdom in a Jest test → caused by CSS `:has()` selectors in styled-components (especially in dialog/sidebar/popover styles). Avoid `:has()` in styles touched by jsdom tests, or assert via roles instead of querying the offending DOM. | ||||||
| - Husky pre-commit running `lint-staged` will run prettier + eslint on staged files; if it fails, fix and re-stage rather than bypassing with `--no-verify`. | ||||||
| - Commit messages MUST follow Conventional Commits (`feat:`, `fix:`, `docs:`, `chore:`, etc.) — enforced by `commitlint` in [.husky/commit-msg](../.husky/commit-msg). Breaking changes via `!` or `BREAKING CHANGE:` footer drive `semantic-release` versioning. | ||||||
|
|
||||||
| ## 6. Project layout & key conventions | ||||||
|
|
||||||
| ``` | ||||||
| src/ | ||||||
| components/<kebab-name>/ # one folder per public component (~90 components) | ||||||
| <name>.component.tsx # implementation + exported Props interface | ||||||
| <name>.style.ts # styled-components | ||||||
| <name>.spec.tsx # Jest + RTL tests (jsdom) | ||||||
| <name>.pw.tsx # Playwright CT tests | ||||||
| <name>.stories.tsx # Storybook stories | ||||||
| <name>.mdx # docs (carbon.sage.com) | ||||||
| index.ts # public re-exports | ||||||
| __internal__/ # NOT exported; internal subcomponents | ||||||
| __internal__/ # shared internal helpers | ||||||
| __spec_helper__/ # Jest setup, test utilities (excluded from coverage) | ||||||
| hooks/ locales/ style/ # shared | ||||||
| playwright/ | ||||||
| components/<name>/{index.ts,locators.ts} # custom locators by component | ||||||
| index.html, index.tsx # Playwright CT harness | ||||||
| global-teardown.js | ||||||
| skills/ # agent skills — MUST be regenerated when a component's public API changes (see §5 "Skills sync") | ||||||
| scripts/ # repo automation (token gen, svg copy, package.json gen, skills build, commit helper) | ||||||
| .storybook/ # Storybook 8 config (Vite) | ||||||
| .github/workflows/ # ci.yml, playwright.yml, chromatic.yml, semantic-release.yml, codeql-analysis.yml, semantic-commit-lint.yml, ... | ||||||
| contributing/ # codebase-overview.md, dev-environment-setup.md, testing-guide.md (READ FIRST for deeper context) | ||||||
| __mocks__/ # Jest manual mocks (fs, styles, carbon-react) | ||||||
| coverage-thresholds.json # global Jest thresholds enforced in CI | ||||||
| jest.config.ts # 2 projects: Client (jsdom) + Server (node) | ||||||
| playwright-ct.config.ts # CT config; testMatch = *.pw.tsx; testIdAttribute = data-role | ||||||
| rollup.config.mjs, tsconfig-build.json # library build | ||||||
| eslint.config.mjs # flat ESLint config | ||||||
| babel.config.js # used by babel-jest | ||||||
| ``` | ||||||
|
|
||||||
| Key conventions (follow them — CI/lint will enforce most): | ||||||
|
|
||||||
| - Use `data-role` (NOT `data-testid`) for test queries; `data-component` is reserved for component roots, `data-element` for sub-elements. Both Jest (RTL) and Playwright are configured to read `data-role` as the test-id attribute. | ||||||
|
||||||
| - Use `data-role` (NOT `data-testid`) for test queries; `data-component` is reserved for component roots, `data-element` for sub-elements. Both Jest (RTL) and Playwright are configured to read `data-role` as the test-id attribute. | |
| - Prefer `data-role` for test queries; `data-component` is reserved for component roots, `data-element` for sub-elements. Both Jest (RTL) and Playwright are configured to read `data-role` as the test-id attribute. `data-testid` may still appear in Storybook-specific selectors/pseudo states or legacy code, so treat `data-role` as the default for new tests rather than an absolute ban. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: The lint step note implies CI prevents new warnings, but
--max-warnings=636only caps the total warnings. Consider rephrasing to “CI allows up to 636 warnings; avoid increasing the count / fix warnings rather than raising the ceiling” for accuracy.