chore: migrate from cli-style to the shared style configs - #1765
Merged
Merged
Conversation
Contributor
|
🚀 Deployed on https://pr-1765--dhis2-ui.netlify.app |
HendrikThePendric
force-pushed
the
chore/migrate-to-style-configs
branch
from
September 15, 2026 09:34
8ff8680 to
91437da
Compare
HendrikThePendric
force-pushed
the
chore/migrate-to-style-configs
branch
from
September 15, 2026 09:56
91437da to
b0743c5
Compare
HendrikThePendric
force-pushed
the
chore/migrate-to-style-configs
branch
from
September 15, 2026 10:02
b0743c5 to
a4355be
Compare
HendrikThePendric
force-pushed
the
chore/migrate-to-style-configs
branch
from
September 15, 2026 10:32
a4355be to
1a10641
Compare
HendrikThePendric
force-pushed
the
chore/migrate-to-style-configs
branch
from
September 15, 2026 11:27
1a10641 to
42d2fb6
Compare
Replaces the `@dhis2/cli-style` eslint and prettier configs with `@dhis2/config-eslint/react` and `@dhis2/config-prettier`, which means eslint 7 -> 9 and flat config, and prettier 2 -> 3. The shared eslint config is written for single-package apps, so this repo re-opens the paths it ignores (`./*.js`, and `src/`-scoped globs that never match `components/*/src`) and re-enables four rules it drops: `import/extensions`, `import/no-unresolved`, and the two React-in-scope rules, which matter here because cli-app-scripts still builds JSX with babel's classic runtime. The ignore lists grow because `d2-style` applied a hardcoded blacklist on top of them: build output, CHANGELOG.md and the generated icon sources were never passed to either tool, and now have to be named. `yarn lint` is red after this commit: prettier 3 reformats 66 files and the new eslint rules report 21 errors. The next two commits clear them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Prettier 2 padded a list marker out to the tab width (`- item`); prettier 3 always uses a single space (`- item`). There is no option for it: `tabWidth` still controls the indentation of nested items, but the space after the marker is fixed. Nothing but whitespace changes here, in its own commit so it can be skipped rather than read. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Template literals holding css break differently, `es5` trailing commas now reach typescript type parameter lists, and call arguments hug differently when a single argument is itself a call. No content changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Most of the 21 errors come from three rules the old config did not have. Two of them are about re-render churn, so they are switched off for stories, which are fixtures rather than shipped components. The rest are fixed where they are: - hoist the object, array and function defaults in SimpleSingleSelect and MultiSelectFieldFF, so they keep one identity across renders - build the debounced refetch in SharingAutocomplete with `useMemo` instead of wrapping an already-built one in `useCallback`, which created and discarded a debounce on every render - drop the unused catch bindings in the api doc generator, leaving the three that actually log the error alone - render `null` as the empty child of a Node story, rather than an expression that is constant - delete an `eslint-enable` with no matching `eslint-disable` One is suppressed with a reason: a named export that static analysis cannot see behind a CommonJS shim. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`@typescript-eslint/parser` was pinned to 7.18 because it was the last release supporting eslint 8, and `typescript` was pinned below 5.6 to stay inside that parser's supported range. `@dhis2/config-eslint` brings its own parser on the v8 line, so neither pin has anything left to hold: the direct dependency goes, and typescript moves to 5.9. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Both commit-linting jobs resolved their config by requiring `@dhis2/cli-style` at runtime, which is the last thing in CI that depends on the package. A root `commitlint.config.mjs` replaces it, and because it is the filename both actions already look for, the lookup step goes away rather than moving. The pull request title job drops `pull-request-name-linter-action`, which is pinned to the long-removed node12 runtime, in favour of piping the title into commitlint directly. The title is untrusted, so it goes through the environment instead of being interpolated into the shell. Verified against 150 commits of master: commitlint 20 and the 12 that cli-style bundles accept and reject exactly the same set. The hooks lose the husky shim they sourced, which never existed here -- nothing installs it, `core.hooksPath` is unset, and so neither hook has ever run on a fresh clone. They are left working for anyone who points git at them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nothing resolves through it any more. Its remaining pieces were either already standalone or dead: `.editorconfig` and the github templates are plain files it copied in once and never read again, and the ls-lint check it ran on every invocation was a no-op without a `.ls-lint.yml`. Removing it also takes eslint 7, husky 7, commitlint 12 and ls-lint out of the dependency tree. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Node 20 reached end of life on 2026-04-30, so `20.x` pinned every job to an unsupported runtime. Node 24 is the active lts until 2026-10-20 and in maintenance until 2028-04-30. This also settles an engine mismatch the eslint 9 upgrade introduced: `@eslint/core` and `eslint-visitor-keys` declare `^20.19.0 || ^22.13.0 || >=24`, which the last node 20 releases satisfy but earlier ones do not. Pinned to `24.x` rather than `lts/*` deliberately: node 26 becomes lts on 2026-10-28, and a runtime should move because someone decided it should, not because a date passed. Verified on node 24: lint, typecheck, the full test suite, build:lib, build:api, the storybook build and `yarn setup`. No package in the installed tree declares an engine range that excludes node 24. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
HendrikThePendric
force-pushed
the
chore/migrate-to-style-configs
branch
from
September 15, 2026 11:36
42d2fb6 to
ecd4df6
Compare
|
kabaros
approved these changes
Sep 15, 2026
kabaros
reviewed
Sep 15, 2026
| set -e | ||
|
|
||
| yarn d2-style check --staged | ||
| staged_files_without_deletions() { |
Collaborator
There was a problem hiding this comment.
I normally use lint-staged here .. maybe we could discuss what approach to take in general and standardise, but happy with this if it works
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.



Implements: N/A — follow-up to the
style-configsrollout (LIBS-614)Description
Replaces
@dhis2/cli-stylewith@dhis2/config-eslint/reactand@dhis2/config-prettierfromdhis2/style-configs. That carries eslint 7 → 9 and flat
config and prettier 2 → 3, and takes eslint 7, husky 7, commitlint 12 and ls-lint out of the
dependency tree.
cli-styleis being phased out by the extensibility team. Its commitlint, ls-lint and stylelintconfigs are still in progress upstream, so commitlint is inlined locally here — as in
event-visualizer-app#336.
Two commits are formatting only and can be skipped:
style: reflow markdown list markers(45 files) and
style: reformat code(18 files). The other six touch 26 files.Implementation choices
Four rules the shared config leaves off are enabled here, keeping what cli-style did:
import/extensions— the JS packages publish ESM, where Node does no extension guessing, sorelative imports need
.js. TS sources are the inverse (never), since TypeScript resolvesextensionless.
import/no-unresolved— off upstream over a resolver issue this repo does not hit.react/react-in-jsx-scope+react/jsx-uses-react— off upstream viajsx-runtime.@dhis2/cli-app-scriptsruns@babel/preset-reactin classic mode, so JSX compiles toReact.createElementand a missing import fails at runtime rather than at build time. The secondrule stops
no-unused-varsflagging the import the first one requires.The shared config's ignores are app-shaped as well (
./*.js, andsrc/-scoped globs that nevermatch
components/*/src), so this repo's list replaces them and re-includes the root config files.Other points to take note of:
.d.tsfiles stay unlinted, as before this PR. Linting them costs ~350errors, 277 of them
react/no-unused-prop-typesreading type declarations as components.react/no-object-type-as-default-propandreact-hooks/static-componentsare off for storiesonly — both concern re-render churn in shipped components.
(#3230,
#3979).
@commitlint/cliis on v20 rather than v21, which needs node ≥ 22.12.24.xrather thanlts/*, so node 26 becoming LTS on 2026-10-28 does not moveCI on its own.
45-file commit.
New mechanisms
commitlint.config.mjsat the root. Both commit jobs used to require@dhis2/cli-styleatruntime to locate their config.
.mjsis the filename both actions look for by default, so thatlookup step is gone rather than moved.
lint-pr-titlealso replacespull-request-name-linter-action, pinned to the removed node12 runtime, with commitlint readingthe title from
env:— it is untrusted input.core.hooksPathis unset, so neither has run on a fresh clone. They are dependency-free now.yarn lintiseslint . && prettier --check ., andformatthe equivalent, replacing thefour
d2-stylescripts.build-world.shformats build output directly.Behaviour changes
.css/.scss, whichd2-style's*.{md,json,yml,html}pattern didnot. One file was reformatted.
eslint.config.mjsis linted; the shared config ignoreseslint.config*by default.node-version: 20.xpinned every job to anunsupported runtime. Moving also satisfies
@eslint/coreandeslint-visitor-keys, which want^20.19.0 || ^22.13.0 || >=24.@typescript-eslint/parserpin and thetypescript ~5.5.4ceiling added in feat: support writing components in TypeScript, with a placeholder OuTree #1764 are gone.typescript-eslintv8 supersedes both, and disablesno-undef,no-redeclareandno-dupe-class-membersfor.ts/.tsx— the set that was being worked around there.Known issues
None.
Checklist
build:apiruns cleanVerification
All green:
yarn lint(0 errors; the 10 remaining warnings are pre-existingreact-hooks/exhaustive-deps),CI=true yarn lint, which addsimport/no-cycleandimport/no-self-import,yarn typecheckon TypeScript 5.9.3,yarn test(126 suites, 976passed), and
build:lib+build:api+ the storybook build. CI passes too, including all sevene2e shards.
Commitlint was checked differentially: across 150 commits of master, v20 and the v12
cli-stylebundles accept and reject the same set.
🤖 Generated with Claude Code