Skip to content

fix(lint): migrate to flat eslint config, and give stylelint a config at all - #304

Merged
rubenvdlinde merged 3 commits into
developmentfrom
fix/eslint-flat-config
Aug 31, 2026
Merged

fix(lint): migrate to flat eslint config, and give stylelint a config at all#304
rubenvdlinde merged 3 commits into
developmentfrom
fix/eslint-flat-config

Conversation

@rubenvdlinde

Copy link
Copy Markdown
Contributor

eslint could not run here once its version moved:

Oops! Something went wrong! :(
ESLint: 10.9.1
ESLint couldn't find an eslint.config.* file.

versioniq was the last app in the fleet still on .eslintrc.cjs; every other one already ships eslint.config.mjs. That was invisible while the lockfile held eslint 8.57.1, and surfaced the moment a Dependabot group bump pulled eslint 10 — which requires flat config.

development       eslint 8.57.1   .eslintrc.cjs works
dependabot #276   eslint 10.9.1   crashes before linting a file

This takes hermiq's eslint.config.mjs, which documents itself as the fleet's canonical shape ("copy it verbatim; only the last two blocks should differ"), keeping versioniq's own rules in those blocks with their original rationales. The old jsdoc rules are deliberately not carried over — the canonical config already scopes them and already declares the spec tag gate-16 requires, and re-declaring them unscoped aborts the entire run.

stylelint had no configuration whatsoever

ConfigurationError: No rules found within configuration.

The app declared @nextcloud/stylelint-config and never extended it — no config file of any kind. stylelint 16 tolerated that silently. A declared linter with no rules is not a lenient linter, it is an absent one: the package was installed on every CI run and judged nothing. The 16→17 move did not break stylelint here, it revealed that stylelint had never run.

Between them the two config fixes surfaced 247 eslint and 70 stylelint findings that had never been reportable. Most were auto-fixable; the rest were 24 missing import extensions (resolved against the file on disk, not appended blindly) and two refs declared 90 lines below their first use.

Verified: eslint exits 0 (113 warnings, 0 errors), stylelint exits 0, webpack build compiles, vitest 11 files / 58 tests pass.

Conduction Release Bot added 3 commits August 30, 2026 19:29
eslint could not run here at all once its version moved:

  Oops! Something went wrong! :(
  ESLint: 10.9.1
  ESLint couldn't find an eslint.config.* file.

versioniq was the LAST app in the fleet still on .eslintrc.cjs; every
other one already ships eslint.config.mjs. That was invisible while the
lockfile held eslint 8.57.1, and surfaced the moment a Dependabot group
bump pulled eslint 10 -- which requires flat config.

  development branch   eslint 8.57.1   .eslintrc.cjs works
  dependabot #276      eslint 10.9.1   crashes before linting a file

This takes hermiq's eslint.config.mjs, which documents itself as the
fleet's canonical shape ('copy it verbatim; only the last two blocks
should differ'), and keeps versioniq's own rules in those two blocks with
their original rationales.

The jsdoc rules from .eslintrc.cjs are NOT carried over: the canonical
config already scopes them and already declares the  tag that
gate-16 needs. Re-declaring them unscoped aborts the whole run -- which
it did, once, before this was corrected.

Fixing the config surfaced 247 findings it had been unable to report.
194 were auto-fixable. Of the rest:

  24x import-extensions/extensions   relative imports now carry .ts,
                                     checked against the file on disk
                                     rather than appended blindly
   4x no-use-before-define           two refs declared 90 lines below
                                     their first use, moved above it

Verified: eslint exits 0 (113 warnings, 0 errors), stylelint exits 0,
webpack build compiles, vitest 11 files / 58 tests pass.
Aligning the lockfile for the eslint migration moved stylelint 16 -> 17,
and 17 refused to start:

  ConfigurationError: No rules found within configuration.
  Have you provided a "rules" property?

The cause was not the upgrade. This app declared
`@nextcloud/stylelint-config` as a devDependency and then never extended
it -- no config file of any kind, and no `stylelint` key in package.json.
stylelint 16 tolerated that silently.

A declared linter with no rules is not a lenient linter, it is an absent
one: the package was installed on every CI run and judged nothing. The
16 -> 17 move did not break stylelint here, it revealed that stylelint
had never been running.

It now has a config pointing at the package it already depended on,
written as `export default` rather than `module.exports` because this
package is `"type": "module"` and a `.js` config file is therefore an ES
module -- CommonJS there throws `ReferenceError: module is not defined in
ES module scope`.

With stylelint finally running it reported 70 findings; 59 were
auto-fixable and the remainder were logical-property warnings
(padding-left -> padding-inline-start), which are warnings and do not
fail the run.

The v3 stylelint stack is now declared explicitly rather than inherited:
stylelint ^17.14.1, @nextcloud/stylelint-config ^3.2.2,
stylelint-config-recommended-scss ^17.0.1,
stylelint-config-recommended-vue ^1.6.1 and stylelint-config-html ^1.1.0
-- the same set shillinq and zaakafhandelapp run green.

Note on the previous commit: its message lost the word `spec` from one
sentence. Backticks in a double-quoted `-m` string were expanded by the
shell before git saw them. It should read "already declares the `spec`
tag that gate-16 requires". Left uncorrected because amending would need
a force-push onto a shared branch.

Verified: eslint exits 0 (113 warnings, 0 errors), stylelint exits 0,
webpack build compiles, vitest 11 files / 58 tests pass.
development moved 37 commits ahead while this branch was open, and the two
files that conflicted were package.json and package-lock.json — dependency
churn, no source conflict.

package.json: kept @nextcloud/stylelint-config ^3.2.2 over development's
^3.1.1. 3.2.2 is published and is what the rest of the fleet already carries.

package-lock.json: regenerated. Taking development's copy wholesale left it
describing a tree package.json no longer asks for, and npm install then failed
ERESOLVE against the very version it was being told to install.

Verified on a clean tree with node_modules removed first, because a check that
runs against a stale node_modules proves nothing: npm ci, lint, build,
check:l10n-js and stylelint all exit 0.
@github-actions

Copy link
Copy Markdown
Contributor

Quality Report — ConductionNL/versioniq @ c6cbe3a

Check PHP Vue Security License Tests
lint
phpcs
phpmd
psalm
phpstan
phpmetrics
eslint
stylelint
build
composer ✅ 29/29
npm ✅ 302/302
app:check-code ⏭️
info.xml
REUSE
PHPUnit
Newman ⏭️
Playwright 🚨 NO VERDICT — enabled but never ran
Hydra gates

Quality workflow — 2026-08-31 02:42 UTC

Download the full PDF report from the workflow artifacts.

@rubenvdlinde
rubenvdlinde merged commit b576ded into development Aug 31, 2026
46 of 48 checks passed
@rubenvdlinde
rubenvdlinde deleted the fix/eslint-flat-config branch August 31, 2026 02: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.

1 participant