Skip to content

Eslint flat config v10 - #18157

Merged
marcelofukumoto merged 7 commits into
rancher:masterfrom
marcelofukumoto:eslint-flat-config-v10
Jul 30, 2026
Merged

Eslint flat config v10#18157
marcelofukumoto merged 7 commits into
rancher:masterfrom
marcelofukumoto:eslint-flat-config-v10

Conversation

@marcelofukumoto

@marcelofukumoto marcelofukumoto commented Jun 24, 2026

Copy link
Copy Markdown
Member

IMPORTANT this can only be merged on v2.16.0 Change is too big to merge it now for v2.15.0
This is a big change as well, so we will need more than one review on it

Summary

Fixes #15498
Fixes #16514
Fixes #17965

Migrates ESLint from v7 (legacy .eslintrc) to v10 flat config, unblocking the eslint-related Dependabot bumps that could not land on the deprecated config format.

Occurred changes and/or fixed issues

  • Removed .eslintrc.js, .eslintrc.default.js, .eslintignore; replaced with eslint.config.mjs (+ shared eslint.config.base.mjs) for root, pkg/rancher-components, and the extension scaffolding template.
  • Bumped toolchain: eslint 7→10, typescript-eslint 5→8, eslint-plugin-vue 9→10, eslint-plugin-jest 27→29, eslint-plugin-cypress 2→4.
  • Replaced standard/@vue/standard (capped at eslint 8) with their flat successor neostandard; re-added the import rules it drops.
  • Updated lint scripts (dropped removed --ext flag) and the jest/no-ifjest/no-conditional-in-test rule rename.

Technical notes summary

  • Behaviour-preserving migration: the effective ruleset matches the previous setup. Rules newly added to "recommended" by the major bumps are explicitly disabled to keep the codebase green with no source changes — a follow-up should re-enable them incrementally.
  • Lint scope replicates the old --ext .js,.ts,.vue + dotfile ignores via flat-config ignores.

Areas or cases that should be tested

  • CI lint (root) and lint:lib (pkg/rancher-components) pass with --max-warnings 0.
  • Extension scaffolding: yarn create @rancher/extension then yarn lint resolves the toolchain transitively from @rancher/shell.
  • No formatting drift: eslint --fix-dry-run . produces no changes.

Areas which could experience regressions

  • Any tooling that runs eslint directly with the removed --ext flag.
  • The @rancher/shell standalone install/publish — shell/yarn.lock must be regenerated for the new toolchain (still pins eslint@7.32.0).

Screenshot/Video

N/A — tooling-only change, no UI impact.

Checklist

  • The PR is linked to an issue and the linked issue has a Milestone, or no issue is needed
  • The PR has a Milestone
  • The PR template has been filled out
  • The PR has been self reviewed
  • The PR has a reviewer assigned
  • The PR has automated tests or clear instructions for manual tests and the linked issue has appropriate QA labels, or tests are not needed
  • The PR has reviewed with UX and tested in light and dark mode, or there are no UX changes
  • The PR has been reviewed in terms of Accessibility
  • The PR has considered, and if applicable tested with, the three Global Roles Admin, Standard User and User Base

@marcelofukumoto marcelofukumoto changed the title [DRAFT] Eslint flat config v10 Eslint flat config v10 Jun 25, 2026
@marcelofukumoto
marcelofukumoto marked this pull request as ready for review June 25, 2026 17:16
@marcelofukumoto
marcelofukumoto marked this pull request as draft June 25, 2026 17:16

@codyrancher codyrancher left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

  • We'll want to validate extensions still work (kubewarden can still be loaded and built using a yarn link on shell.
  • I think we'll want Alex to take a look because of extensions
  • And either Neil or Phil because of dependabot

Comment thread shell/package.json
"entities": "4.5.0",
"eslint": "7.32.0",
"eslint-config-standard": "16.0.3",
"eslint": "10.5.0",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

shell/yarn.lock still resolves eslint@7.32.0.

We'll need to make sure each of the lock files are updated.
image

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

That is good catch, updated the lock.

Comment thread eslint.config.base.mjs
files: ['**/*.{js,ts,vue}'],
rules: {
'@typescript-eslint/no-empty-function': 'off',
// `@typescript-eslint/ban-types` was split in ts-eslint v8; disable successors.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comment thread eslint.config.base.mjs
'import/no-named-as-default': 'off',

// --- ESLint v9 / typescript-eslint v8 upgrade compatibility ---
// Disabled (config-only, no source changes) to preserve the pre-upgrade green state.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I don't understand this comment. Are we saying that this only affected config files? If so, can we just disable rules for those files instead of for the entire project?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I tried to make the entire changes without touching the code base. That is what means config-only.
There are too many violations on this one. We can handle them on a different PR, remove maybe one by one and start making file changes.

The goal for this PR is update the version of the eslint without having to change the code base.

For example, if I remove
@typescript-eslint/no-require-imports
It will trigger 229 error in 93 files.

So we can do that later on to avoid complexity on this first PR.

Comment on lines +13 to +15
if (!parserServices?.defineTemplateBodyVisitor) {
return {};
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this would cause us to fail silently. If it's not available I think we'd just like to throw and then fix it if it's broken.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Ok! That is a good point, I will remove this.

Comment thread eslint.config.base.mjs

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It is a little difficult to evaluate equivalency by hand so I used AI to help find the differences.

Added:

Image

Behavior changed:

  • object-shorthand
    • old: ['warn', 'properties']
    • new: ['warn', 'always']

Were implicit but now explicit:

  • comma-spacing, array-bracket-spacing, keyword-spacing, object-curly-spacing, rest-spread-spacing, quote-props, spaced-comment, object-property-newline

Replicated:

  • --ext .js,.ts,.vue -> ignores: ['**/*.tsx', '**/*.jsx', '**/*.mjs', '**/*.cjs', '**/.*', '**/.*/**']
  • reportUnusedDisableDirectives: 'off' -> Had to be added since the default is warn
  • eslint:recommended -> js.configs.recommended
  • standard + @vue/standard -> neostandard({ ts: true, noStyle: true, noJsx: true })
  • plugin:@typescript-eslint/recommended -> tseslint.configs.recommended
  • plugin:vue/vue3-recommended -> pluginVue.configs['flat/recommended']
  • plugin:cypress/recommended -> pluginCypress.configs.recommended
  • plugin:local-rules/all -> { rules: { 'local-rules/v-clean-tooltip': 'error' } }

@richard-cox
richard-cox self-requested a review July 9, 2026 16:52
@richard-cox

Copy link
Copy Markdown
Member

i had a stab of this today, hadn't realised there was a PR up. would like to review as well, at least to work out where i was going wrong

@richard-cox richard-cox mentioned this pull request Jul 10, 2026
@marcelofukumoto marcelofukumoto added this to the v2.16.0 milestone Jul 17, 2026
@marcelofukumoto
marcelofukumoto marked this pull request as ready for review July 20, 2026 08:22
@marcelofukumoto
marcelofukumoto force-pushed the eslint-flat-config-v10 branch 2 times, most recently from b4bba5c to 666b496 Compare July 22, 2026 08:25

@rak-phillip rak-phillip left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this looks great. I only have a single comment with regards to some potential follow-up work that we might want to consider after merging this change.

Comment thread eslint.config.base.mjs
@github-actions

Copy link
Copy Markdown
Contributor

🔄 Auto-Retry Failed Run

The Tests workflow run 30264497383 failed and has been automatically retried.

Follow up on the retried run here if needed: https://github.com/rancher/dashboard/actions/runs/30264497383

rak-phillip
rak-phillip previously approved these changes Jul 27, 2026

@rak-phillip rak-phillip left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think this change looks great. Based on the scope of this change, I suggest getting at least one more approval before merging.

richard-cox
richard-cox previously approved these changes Jul 28, 2026

@richard-cox richard-cox left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

  • @aalves08 once a new extension creator package is created can you give linting a quick test?
  • i think it would be good for @codyrancher to review again to confirm his comments are good

@aalves08 aalves08 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

🔴 Extensions developer env is failing. Repro steps:

  • Clone https://github.com/aalves08/elemental-ui
  • Checkout compatibility-tests-version
  • Do yarn install
  • With this PR+branch, go to the shell folder and do yarn link
  • On the folder where you've cloned https://github.com/aalves08/elemental-ui, do yarn link "@rancher/shell"
  • Run the dev env with: API=.... yarn dev

Extension dev env throws multiple errors.

🟢 Elemental extension does build fine (you'll need to run on the current PR the ./scripts/typegen.sh to generate the missing type definitions and on the extension side you do yarn build-pkg elemental

🔴 scaffolding + build (creators package) and yarn dev, using:

Prerequisites

Make sure you're on the PR branch and deps are installed:

cd /Users/aalves/Desktop/PROJECTS/marcelo-dashboard

# Confirm you're on the right branch
git branch --show-current
# Expected: eslint-flat-config-v10

# Install root deps if not already done
yarn install --frozen-lockfile

# Install shell's own deps (needed so the build scripts are available via file: link)
cd shell && yarn install --frozen-lockfile && cd ..

Step 1 — Scaffold the extension skeleton

# Create a fresh temp directory
mkdir /tmp/test-ext-build && cd /tmp/test-ext-build

# Run app/init directly — scaffolds the skeleton and copies eslint.config.mjs
node /Users/aalves/Desktop/PROJECTS/marcelo-dashboard/creators/extension/app/init my-ext "0.0.0-local"

cd my-ext

At this point you have the skeleton with the new eslint.config.mjs template.


Step 2 — Scaffold the extension package

# Run pkg/init directly — creates pkg/my-ext/ with index.ts, vue.config.js, tsconfig.json
# and adds build-pkg / serve-pkgs / publish-pkgs scripts to the root package.json
node /Users/aalves/Desktop/PROJECTS/marcelo-dashboard/creators/extension/pkg/init my-ext

Step 3 — Wire @rancher/shell to the local PR branch

The scaffold set @rancher/shell: "^0.0.0-local" which won't resolve from npm.
Replace it with a file: reference pointing to the local checkout:

node -e "
  const fs = require('fs');
  const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
  pkg.dependencies['@rancher/shell'] = 'file:/Users/aalves/Desktop/PROJECTS/marcelo-dashboard/shell';
  fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2));
  console.log('Done. @rancher/shell now points to local checkout.');
"

With Yarn 1.x classic (which the extension scaffold uses via .yarnrc --frozen-lockfile true),
a file: reference installs the package AND hoists all its dependencies into the extension's
own node_modules. This is why neostandard, typescript-eslint, eslint-plugin-vue, etc.
(all in shell/package.json dependencies) will be importable by eslint.config.mjs.


Step 4 — Install dependencies

# --frozen-lockfile=false because we have no lockfile yet for this extension
yarn install --frozen-lockfile=false

After this, confirm the ESLint packages are present:

ls node_modules | grep -E "neostandard|typescript-eslint|eslint-plugin-vue|vue-eslint-parser|@eslint"

Expected output (all packages should be there):

@eslint
eslint-plugin-vue
neostandard
typescript-eslint
vue-eslint-parser

Step 5 — Lint

./node_modules/.bin/eslint --max-warnings 0 .

What to check:

  • No Cannot find module '...' errors — means ESLint package resolution works
  • No config parse errors — means the flat config syntax is valid
  • Zero warnings/errors on the scaffolded source files — means the rules are correct

Step 6 — Build the extension

yarn build-pkg my-ext

This runs node_modules/@rancher/shell/scripts/build-pkg.sh my-ext, which:

  1. Detects that shell is in node_modules/@rancher/shell/ (no shell/ folder at root)
  2. Creates a .shell symlink inside pkg/my-ext/ pointing to the shell location
  3. Runs vue-cli-service build --target lib pkg/my-ext/index.ts

Expected output:

Building UI Package my-ext
  Package name:    my-ext-0.1.0
  Package version: 0.1.0
  Output formats:  umd-min
  Output directory: /tmp/test-ext-build/my-ext/dist-pkg/my-ext-0.1.0
...
Build complete.

The built artifacts land in dist-pkg/my-ext-0.1.0/.


Troubleshooting

Cannot find module 'neostandard' (or similar) during lint

The ESLint packages did not hoist from shell. Check:

# Is the file: reference resolved?
ls -la node_modules/@rancher/shell

# Is neostandard missing entirely?
ls node_modules | grep neostandard

If missing, try:

yarn add neostandard@0.13.0 typescript-eslint@8.62.0 vue-eslint-parser@10.4.1 \
  "@eslint/js@10.0.1" globals@17.7.0 eslint-plugin-vue@10.9.2 \
  "eslint-plugin-cypress@4.3.0" eslint-plugin-import@2.32.0 --dev

.shell symlink exists but does not point to expected location during build

The build script creates .shell inside pkg/my-ext/ on each run.
If you ran the build before and the symlink is stale, remove it:

rm -f pkg/my-ext/.shell
yarn build-pkg my-ext

vue-cli-service: command not found or @vue/cli-service not found

@vue/cli-service should hoist from shell's deps. If it doesn't:

ls node_modules/@vue/cli-service
# If missing:
yarn add @vue/cli-service@5.0.8 --dev

frozen-lockfile error on install

The .yarnrc in the template sets --frozen-lockfile true by default.
Since there's no lockfile yet, override it:

yarn install --frozen-lockfile=false

Cleanup

rm -rf /tmp/test-ext-build

@marcelofukumoto
marcelofukumoto force-pushed the eslint-flat-config-v10 branch from 7472be7 to 906c7e5 Compare July 28, 2026 15:48
@marcelofukumoto

marcelofukumoto commented Jul 29, 2026

Copy link
Copy Markdown
Member Author

@aalves08

I did the required tests.
image

Seems to be ok.


For the yarn link + yarn dev
Currently it doesn't work properly because of the version difference on the webpack, there is a mismatch between the version on the elemental ui and master/my branch.
That is same for master.


But for the rest of the test it works well.

The lint as well doesn't work properly on elemental-ui. But that is same for master.

I created a way to make sure can support eslint v7 as well.
I tried with rancher-ai-ui, but most of our extensions already has their own lint anyway.

I did some test and seems to be working.
It adds a script on shell to help linting for both versions.
For the ones that already has their own, it worked well as well since it mostly ignores it.

@aalves08 aalves08 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Given the tests I've done using AI (needed a lot of resolving to do because of webpack version mismatch and all) it looks like this is safe to merge on the extensions side. I think it got proven that this should not affect "yarn dev" nor builds.

given that there was already an approval on the PR, I am approving as well.

Massive work @marcelofukumoto . Kudos

@marcelofukumoto

Copy link
Copy Markdown
Member Author

@aalves08 thank you!
For the yarn dev, only the yarn link fails because of the webpack version mismatch, but worked well with rancher-ai-ui and harvester-ui.

I will merge considering previous approval from @richard-cox and @rak-phillip and fixed comments from @codyrancher.

Since it is a big change it could affect later on, but I will be fixing as we find them.

@marcelofukumoto
marcelofukumoto merged commit 4ca5e5d into rancher:master Jul 30, 2026
63 of 64 checks passed
mantis-toboggan-md pushed a commit that referenced this pull request Jul 30, 2026
* Update to v9 with deprecated .eslint for minor changes

* Update to v9 with updated config

* Added eslint-v10 changes

* Fixed semver to 7.7.1, the one previously on the yarn.lock

* Applied same semver type to lock the expected version

* Updated based on review

* Compat to es7
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants