build(lint): migrate to eslint 10 + @nextcloud/eslint-config 9 - #201
Merged
Conversation
Same migration as the pilot (ConductionNL/larpingapp#325) and the template (ConductionNL/nextcloud-app-template#146). eslint.config.mjs is the canonical copy; only the app-specific blocks at the end differ. Requires Node 22 — @nextcloud/eslint-config@9 declares engines.node ^22.14 || ^24 || >=26 and imports findPackageJSON from node:module, first available in 22.14. The shared workflows already default to 22 (ConductionNL/.github#450). Stale eslint-8-era direct deps and overrides are removed, and the two peers the config needs are declared at the right major (vue-eslint-parser ^10.3.0, @typescript-eslint/parser ^8.67.0). An overrides entry resolves nc-vue's OPTIONAL eslint peer against eslint 10 — optional means npm will not install it, not that a mismatched version is accepted. Coverage: all 135 .vue files parse, 0 fatal errors. 157 PRE-EXISTING VIOLATIONS ARE RECORDED, NOT FIXED ------------------------------------------------------ v9 enables rules this app has never run. --fix and prettier resolved the mechanical ones; 157 findings across 63 files remain and are recorded in eslint-suppressions.json using eslint's own bulk suppressions (--suppress-all), NOT by loosening any rule. Every rule keeps the severity @nextcloud/eslint-config gives it, the debt is counted per file, and --prune-suppressions shrinks it as it is paid down. A NEW violation still fails the run — verified on openconnector by appending a console.log after suppressing. 72 @typescript-eslint/no-unused-vars 22 vue/custom-event-name-casing 20 eqeqeq 10 no-console 8 @nextcloud/l10n-enforce-ellipsis 7 no-useless-assignment 6 no-unused-vars 4 jsdoc/require-param-type 4 @nextcloud/no-deprecated-library-props 1 vue/prefer-prop-type-boolean-first 1 jsdoc/check-tag-names 1 no-undef TWO AUTOFIXES ARE DELIBERATELY WITHHELD (recorded as debt instead) ----------------------------------------------------------------- - @nextcloud/l10n-enforce-ellipsis rewrites '...' to the typographic '…' INSIDE translatable strings. That changes the translation KEY and orphans every l10n/*.json entry for it; on openconnector it turned the l10n parity check red while it was green on development. The migration must not silently drop translations, so the source strings are left alone. - vue/prefer-define-options rewrites 'export default {…}' in a plain <script> into 'defineOptions({…})' inside <script setup>, carrying props/data/computed across the block boundary. @vue/compiler-sfc then rejects the result outright (defineOptions() cannot declare props), which broke the build in softwarecatalog and docudesk. It is a semantic refactor, not a lint fix. TEST GLOBALS ARE DECLARED, NOT SUPPRESSED ----------------------------------------- Spec files that live under src/ have no framework globals, so no-undef reported every describe/it/expect as undefined — 1203 findings in openregister from just 7 identifiers. Declaring the environment removed ~1900 phantom findings fleet-wide. Suppressing them instead would have buried any REAL no-undef, which is the rule that catches a typo'd identifier. VERIFIED -------- npm run lint PASS npm run stylelint PASS npm run format PASS npm run build PASS
Contributor
Quality Report — ConductionNL/openbuild @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| test-l10n | ✅ | ||||
| check-gitignore | ✅ | ||||
| check-nc-floor | ✅ | ||||
| format | ✅ | ||||
| composer | ✅ | ✅ 106/106 | |||
| npm | ✅ | ✅ 638/638 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-14 13:19 UTC
Download the full PDF report from the workflow artifacts.
`@nextcloud/no-deprecated-library-props` autofixed NcButton's deprecated
`type="primary"` to `variant="primary"`. The rule is right — @nextcloud/vue v9
did repurpose `type` as the native button type and moved the visual style to
`variant` — but the rename changes the RENDERED DOM, and tests assert on it:
openbuild 10 tests failed on `button[data-nc-button-type="primary"]`
returning undefined; 1375/1375 pass on `development`.
So this is a runtime change, not a formatting one, and it belongs in its own
PR together with the test updates it requires. It joins the two autofixes
already withheld for the same reason:
@nextcloud/l10n-enforce-ellipsis edits the CONTENT of translatable strings,
changing the translation key
vue/prefer-define-options moves options across SFC block boundaries
and breaks the build
All three keep their @nextcloud/eslint-config severity and are recorded in
eslint-suppressions.json, so the debt is counted and any NEW occurrence still
fails the run.
Verified after the change: openbuild is back to 1375/1375, and lint / format /
stylelint / build pass on every app touched here.
Contributor
Quality Report — ConductionNL/openbuild @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| test-l10n | ✅ | ||||
| check-gitignore | ✅ | ||||
| check-nc-floor | ✅ | ||||
| format | ✅ | ||||
| composer | ✅ | ✅ 106/106 | |||
| npm | ✅ | ✅ 638/638 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-14 14:10 UTC
Download the full PDF report from the workflow artifacts.
The version-rollback E2E assertion timed out on `.version-history__row` being visible; the element WAS present (`version-history__row--current`) but in state "hidden", and the sibling test that lists the same chain passed in the same run. That reads as a visibility race rather than a structural break, so this empty commit re-runs the suite to separate flake from regression before the PR is judged.
Contributor
Quality Report — ConductionNL/openbuild @
|
| Check | PHP | Vue | Security | License | Tests |
|---|---|---|---|---|---|
| lint | ✅ | ||||
| phpcs | ✅ | ||||
| phpmd | ✅ | ||||
| psalm | ✅ | ||||
| phpstan | ✅ | ||||
| phpmetrics | ✅ | ||||
| eslint | ✅ | ||||
| stylelint | ✅ | ||||
| build | ✅ | ||||
| check-manifest | ✅ | ||||
| test-l10n | ✅ | ||||
| check-gitignore | ✅ | ||||
| check-nc-floor | ✅ | ||||
| format | ✅ | ||||
| composer | ✅ | ✅ 106/106 | |||
| npm | ✅ | ✅ 638/638 | |||
| app:check-code | ⏭️ | ||||
| info.xml | ✅ | ||||
| REUSE | ❌ | ||||
| PHPUnit | ✅ | ||||
| Newman | ⏭️ | ||||
| Playwright | ❌ | ||||
| Hydra gates | ❌ |
Quality workflow — 2026-08-14 14:53 UTC
Download the full PDF report from the workflow artifacts.
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Migrates the JS/Vue lint layer to eslint 10 +
@nextcloud/eslint-config@9, matching the pilot (ConductionNL/larpingapp#325) and the template (ConductionNL/nextcloud-app-template#146).eslint.config.mjsis the fleet's canonical copy.Needs Node 22 — the NC config declares
engines.node: ^22.14 || ^24 || >=26and importsfindPackageJSONfromnode:module. The shared workflows already default to 22 (ConductionNL/.github#450).Stale eslint-8-era direct deps and overrides are removed; the two load-bearing peers are declared at the right major (
vue-eslint-parser@^10.3.0,@typescript-eslint/parser@^8.67.0), and anoverridesentry resolves nc-vue's optional eslint peer against eslint 10 — optional means npm won't install it, not that a mismatch is accepted.Coverage
All 135
.vuefiles parse, 0 fatal. Get the peers wrong andtypescript-eslint/baseparses every SFC as TypeScript; eslint then reports one parse error per file and lints nothing else in it, so the whole Vue layer goes unchecked while the problem count looks small.157 pre-existing violations are recorded, not fixed
v9 enables rules this app has never run.
--fixand prettier resolved the mechanical majority; 157 findings across 63 files remain:@typescript-eslint/no-unused-varsvue/custom-event-name-casingeqeqeqno-console@nextcloud/l10n-enforce-ellipsisno-useless-assignmentno-unused-varsjsdoc/require-param-type@nextcloud/no-deprecated-library-propsvue/prefer-prop-type-boolean-firstjsdoc/check-tag-namesno-undefThese live in
eslint-suppressions.jsonvia eslint's own bulk suppressions — not by loosening any rule. Every rule keeps its@nextcloud/eslint-configseverity, the debt is counted per file, and--prune-suppressionsshrinks it as it's paid down. A new violation still fails the run (verified on openconnector by appending aconsole.logafter suppressing).Two autofixes deliberately withheld
@nextcloud/l10n-enforce-ellipsisrewrites...to…inside translatable strings, changing the translation key and orphaning everyl10n/*.jsonentry for it. On openconnector that turned the l10n parity check red while it was green ondevelopment.vue/prefer-define-optionsrewritesexport default {…}in a plain<script>intodefineOptions({…})inside<script setup>, draggingprops/data/computedacross the block boundary.@vue/compiler-sfcthen rejects it outright and the build fails — it hit 20 components in softwarecatalog and 15 in docudesk. That's a semantic refactor, not a lint fix.Both are recorded as debt instead.
Test globals are declared, not suppressed
Spec files under
src/had no framework globals, sono-undefreported everydescribe/it/expectas undefined — 1,203 findings in openregister from 7 identifiers. Declaring the environment removed ~1,900 phantom findings fleet-wide. Suppressing them would have buried any realno-undef.Verified
npm run lintnpm run formatnpm run stylelintnpm run build