Skip to content

Sync /_lint with host's lint plugins and settings#4965

Draft
richardhjtan wants to merge 1 commit into
mainfrom
cs-11261-_lint-should-sync-our-lint-plugins-and-settings
Draft

Sync /_lint with host's lint plugins and settings#4965
richardhjtan wants to merge 1 commit into
mainfrom
cs-11261-_lint-should-sync-our-lint-plugins-and-settings

Conversation

@richardhjtan
Copy link
Copy Markdown
Contributor

Summary

  • The realm-server's /_lint endpoint ran a hand-maintained ESLint config that drifted from what pnpm run lint runs in CI, and didn't run ember-template-lint at all. This blocked catalog submission pre-PR lint (CS-10863) from matching CI's verdict.
  • tasks/lint.ts now loads packages/host/.eslintrc.js dynamically (full plugin set, all 8 extends:) and runs ember-template-lint against packages/host/.template-lintrc.js per file. Each message carries an optional source: 'eslint' | 'template-lint' tag.
  • Endpoint wire shape is unchanged — still POST /_lint with text body + X-Filename header, still returns { output, fixed, messages }.

Key implementation notes

  • Engine cachingESLint and TemplateLinter instances are constructed once per worker process. Cold start is ~1.2s (plugin tree resolution); warm calls are ~25-40ms.
  • NODE_PATH shim — pnpm doesn't hoist transitive deps. ESLint's parser-by-name resolution (e.g. parser: 'ember-eslint-parser' in host's config) needs .pnpm/node_modules on NODE_PATH, mirroring what pnpm's own eslint bin wrapper does.
  • filePath anchoringfilePath is set to ${HOST_PKG}/<filename>, not ${HOST_PKG}/app/<filename>. Host's app/**-specific overrides (e.g. import/order) shouldn't apply to realm content; the broader **/*.gts and **/*.{js,ts} overrides still match and bring in the full shared config.
  • Timeout bumped from 10s → 30s to cover cold ESLint startup.
  • 5MB source-size cap lifted from the existing submission-lint.ts.

New test coverage

Three new tests in realm-endpoints/lint-test.ts verify rules that fire only if host's config is loaded:

  • ember/no-empty-glimmer-component-classes (from plugin:ember/recommended-gts)
  • @cardstack/boxel/no-raf-for-state (host rule, missing from the legacy inline config)
  • no-invalid-interactive (from ember-template-lint, which /_lint did not previously invoke at all)

Scope

This PR is the first of several under CS-10863:

  • In: /_lint config sync + ember-template-lint engine.
  • Out: a separate /_type_check endpoint, re-enabling the bot-runner submission lint step, deleting runtime-common/lint/submission-lint.ts. Those land in follow-up tickets.

Test plan

  • Existing realm-endpoints/lint-test.ts cases (18 tests) still pass against the new shape — they all use messages/output which is preserved.
  • Three new tests pass (proves host plugins, host custom rules, and template-lint engine are all live).
  • Local parity sweep confirmed 5/5 representative files from host/app/ (currently passing pnpm run lint) return zero errors from the new /_lint.
  • Factory + boxel-cli type-check clean — no consumer changes needed since the optional source field on messages is additive.
  • Manual: boxel lint <some-file.gts> against a local realm-server runs and reports findings.

Linear: CS-11261

🤖 Generated with Claude Code

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Aligns the realm-server /_lint endpoint behavior with the host package’s actual lint configuration so server-side linting matches what CI (pnpm run lint) enforces, and adds template-lint coverage for .hbs/.gts/.gjs.

Changes:

  • Replaced the hand-maintained in-task ESLint setup with dynamic loading of packages/host/.eslintrc.js and added ember-template-lint execution (with per-message source tagging).
  • Added engine caching and a pnpm NODE_PATH shim to support plugin/parser resolution in a pnpm workspace layout.
  • Increased /_lint job timeout and added endpoint tests that prove host ESLint + template-lint rules are actually being applied.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
packages/runtime-common/tasks/lint.ts Switches linting to use host ESLint + template-lint engines, adds caching/NODE_PATH shim, and normalizes result message shape.
packages/runtime-common/realm.ts Increases the queued lint job timeout to accommodate heavier cold-start lint initialization.
packages/realm-server/tests/realm-endpoints/lint-test.ts Adds regression tests that fail unless host ESLint config and ember-template-lint are both active.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/runtime-common/tasks/lint.ts
Comment thread packages/runtime-common/tasks/lint.ts Outdated
Comment thread packages/runtime-common/tasks/lint.ts Outdated
Comment thread packages/runtime-common/tasks/lint.ts Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 26, 2026

Host Test Results

    1 files  ± 0      1 suites  ±0   1h 20m 16s ⏱️ - 14m 57s
2 621 tests  - 39  2 607 ✅  - 38  14 💤  - 1  0 ❌ ±0 
2 638 runs   - 40  2 624 ✅  - 39  14 💤  - 1  0 ❌ ±0 

Results for commit 4f205c9. ± Comparison against earlier commit 914c211.

Realm Server Test Results

    1 files  ±0      1 suites  ±0   9m 48s ⏱️ -4s
1 550 tests ±0  1 549 ✅ +8  1 💤 ±0  0 ❌  - 8 
1 641 runs  ±0  1 640 ✅ +8  1 💤 ±0  0 ❌  - 8 

Results for commit 4f205c9. ± Comparison against earlier commit 914c211.

@richardhjtan richardhjtan force-pushed the cs-11261-_lint-should-sync-our-lint-plugins-and-settings branch 2 times, most recently from 9379f4b to 914c211 Compare June 3, 2026 05:17
@richardhjtan richardhjtan requested a review from Copilot June 3, 2026 05:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

Comment on lines +245 to +251
const passed = !messages.some((m) => m.severity === 2);
return {
passed,
output: working,
fixed: modified,
messages,
};
// Input bounds
// ---------------------------------------------------------------------------

const MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024;
Comment thread packages/runtime-common/tasks/lint.ts Outdated
Comment on lines +193 to +200
const validatedFilename = validateFilename(filename);
const ext = extname(validatedFilename).toLowerCase();
const messages: LintMessage[] = [];
let working = source;
let modified = false;

if (ESLINT_EXTENSIONS.has(ext)) {
const { output, messages: eslintMessages } = await runESLint(
The realm-server's /_lint endpoint ran a hand-maintained ESLint config that
had drifted from what `pnpm run lint` runs in CI, and it didn't run
ember-template-lint at all. This matters for catalog submission lint (CS-10863):
pre-PR validation must agree with CI or submitters hit false greens/reds.

- Dynamically load host/.eslintrc.js (full plugin set, all 8 extends) instead
  of the inline rule subset.
- Run ember-template-lint alongside ESLint, loading host/.template-lintrc.js.
- Tag each message with `source: 'eslint' | 'template-lint'`.
- Cache ESLint + TemplateLinter per worker process; cold ~1.2s, warm ~25-40ms.
- Anchor filePath at host package root (not under app/) so host's app-only
  overrides like import/order don't apply to realm content.
- NODE_PATH shim so transitive parsers/plugins resolve under pnpm.

New tests prove three rules now fire that didn't before:
  - ember/no-empty-glimmer-component-classes (host plugin:ember/recommended-gts)
  - @cardstack/boxel/no-raf-for-state (host rule, missing from inline config)
  - no-invalid-interactive (ember-template-lint, not previously run)

Endpoint shape unchanged: still POST /_lint with text body + X-Filename header,
still returns { output, fixed, messages }. The messages array can now contain
template-lint entries (tagged via the optional `source` field).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@richardhjtan richardhjtan force-pushed the cs-11261-_lint-should-sync-our-lint-plugins-and-settings branch from 914c211 to 4f205c9 Compare June 3, 2026 07:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants