Conversation
|
Hi @cs6cs6!, thanks for the Pull Request The pull request title isn't properly formatted. We ask that you update the pull request title to match this format, as we use it to generate changelogs and automate releases.
To Fix: You can fix this problem by clicking 'Edit' next to the pull request title at the top of this page. Read more about contributing to ESLint here |
|
Hello. How do I draw attention to this PR? I believe I am only awaiting feedback. |
nzakas
left a comment
There was a problem hiding this comment.
Thanks for putting this together and sorry for the delay -- we are a small team and have a lot to do.
Overall I think this looks good. I left some feedback throughout.
14475ae to
1bcafba
Compare
…oss developers or into ci machines. (#16493)
…che and the new cache would look like.
…based on feedback.
a05d10b to
0b7542c
Compare
nzakas
left a comment
There was a problem hiding this comment.
This is looking good. Left comments throughout on areas we can clarify and clean up.
|
|
||
| I originally planned the shareable-cache flag so that users of eslint could not be surprised by changed cache behavior, and would also not have to regenerate their cache | ||
| for a patch version change. But I discovered by testing that there is no way to NOT force people to regenerate their eslint cache with this change. That's because by adding | ||
| the 'shareable-cache' flag, it adds a property to the ConfigArray object. Even if it's set to false (the old behavior), the object's structure changes with a new property |
There was a problem hiding this comment.
How is this changing the ConfigArray? This setting is at the CLI level, not at the config level, so there shouldn't be any changes to the ConfigArray.
There was a problem hiding this comment.
The object itself, along with all of its properties (set or not) is rolled into the computed hash code that goes into the file. So, simply by adding a new property, the hash computed of the object changes, even if that property is deliberately set to create no change in behavior.
Accepting code review suggestion where backticks are added for readability. Co-authored-by: Nicholas C. Zakas <nicholas@humanwhocodes.com>
Per code review, adding backticks for readability. Co-authored-by: Nicholas C. Zakas <nicholas@humanwhocodes.com>
| - `lib/cli.js`: Add the `shareableCache` option, defaulted to false, in the `translateOptions `function. | ||
|
|
||
| ### Changing cache file serialization | ||
| - `lib/cli-engine/lint-result-cache.js`: Add the properties `cwd` and `shareableCache` to the `LintResultCache` class. `cwd` is a string, the current working directory. `shareableCache` is a boolean, the result of the user's passed in command line parameter. Use these values in two main places: |
There was a problem hiding this comment.
I think we should clarify what we mean by the current working directory that will be passed to the LintResultCache class. Is it process.cwd(), or cwd that was passed to ESLint/FlatESLint constructor? In the latter case, is there a way to pass cwd to file-entry-cache or we could end up calculating paths differently?
There was a problem hiding this comment.
Another question is does file-entry-cache support relative paths? All tests seem to be with absolute paths:
https://github.com/jaredwray/file-entry-cache/blob/master/test/specs/cache.js
There was a problem hiding this comment.
It will. I am just going to push up the code review sometime today. I have a complete and working branch on this task, and most of your questions wuold be resolved by the code review/better answered looking at the code changes.
There was a problem hiding this comment.
Don't forget to answer the question regarding what cwd is from the previous comment.
There was a problem hiding this comment.
Is it
process.cwd(), orcwdthat was passed to ESLint/FlatESLint constructor?
When created in cli-engine.js, it's options.cwd. It is also referred to as 'cwd' in the code.
When created in flat-eslint.js, it's processedOptions.cwd.
There was a problem hiding this comment.
Do you think that
cwdwould be a better base location to store relative paths?Do you mean in all cases? If so, the answer is no. I think it makes the most sense to have it relative to the cache file when
--cache-locationis not used.
I'm asking because when --cache-location is not set, the cache file location should be already cwd. I think the advantage of keeping the paths relative to the cache file directory is that they don't change if the current directory changes, for example in a monorepo. Do you have a particular scenario in mind where storing paths relative to cwd would be advantageous?
There was a problem hiding this comment.
Yeah, as @fasttime noticed, when --cache-location is not used, the cache file defaults to .eslintcache in cwd. So if the logic would be to use the location of the cache file when --cache-location is not used, and cwd when --cache-location is used, then it's basically the same as - always use cwd.
There was a problem hiding this comment.
For a use case where a monorepo has a single eslint cache file that's checked-in and shared between developers, and developers work and run eslint in project subdirectories (using --cache-location with a path to the single cache file somewhere in the root), I believe the only solution would be that the paths are relative to the cache file directory.
For other use cases, e.g., when the cache file is generated in CI and shared between CI runs (I believe that was the original use case in eslint/eslint#16493?), I'm not sure, it depends on where and how the cache file will be stored and used. It might be good to get more input from people requesting this feature.
There was a problem hiding this comment.
I think we should just make a decision and see what happens when people test with it. This PR has been open since October of last year, and it seems like this is the last thing to decide on, so I don't think there's value in drawing this out further when we have a binary decision to make.
So I'd like to propose that we say the paths are always relative to location of the .eslintcache file.
There was a problem hiding this comment.
So I'd like to propose that we say the paths are always relative to location of the
.eslintcachefile.
I agree.
|
@cs6cs6 there were still some outstanding requests for you to consider here. Are you still working on this? |
|
@cs6cs6 just checking back to see if you intend on finishing this up? |
|
Hello, I apologize for the delay. I am working on this today. |
|
@nzakas and @mdjermanovic - I released v9.1.0 of const path = require('node:path');
const fileEntryCache = require('file-entry-cache');
const cacheFileLocation = path.resolve(__dirname, '.eslintcache');
const useChecksum = true;
const currentWorkingDirectory = __dirname;
const cache = fileEntryCache.create(
cacheFileLocation,
undefined,
useChecksum,
currentWorkingDirectory
);Thanks for the patience on this and I believe this should un-block you with this where you want to rename the working folder and still use the cache. |
|
@jaredwray thanks for the new versions! Question: how to store file locations relative to the cache file? I tried the following: const fileEntryCache = require("file-entry-cache");
const path = require("node:path");
const cacheFileDir = path.resolve(__dirname, "cache");
const cacheFileLocation = path.resolve(cacheFileDir, ".eslintcache");
const useChecksum = true;
const currentWorkingDirectory = cacheFileDir;
const cache = fileEntryCache.create(
cacheFileLocation,
undefined,
useChecksum,
currentWorkingDirectory
);
const filePath = path.resolve(__dirname, "src", "my-file.js"); // exists
const fileDescriptor = cache.getFileDescriptor(filePath);
fileDescriptor.meta.results = { foo: "bar" };
cache.reconcile();
[{}] |
Do you have a project that I can see with this? I believe the paths are causing issues on this and one thing to look at is that with using the |
In the unit test, all paths are absolute, as they're produced by |
|
Here a stackblitz repro: https://stackblitz.com/edit/stackblitz-starters-eh4ubs?file=test.js |
The fix for this is to point at the current working directory of where the file is instead of the cache directory: https://stackblitz.com/edit/stackblitz-starters-ikrcmu?file=test.js,cache%2F.eslintcache The |
|
@mdjermanovic, @nzakas - I wanted to update you that we have released a new major version of Read the new docs here: https://www.npmjs.com/package/file-entry-cache I would recommend that you continue to do absolute paths like you have done before. We do support When a folder changes you can now call const fileEntryCache = require('file-entry-cache');
const cache = fileEntryCache.create('.eslintcache', undefined, true);
const fileEntry = cache.getFileDescriptor(path.resolve(__dirname, './src/test-file.js');
console.log(fileEntry.changed); // true, first time run
cache.reconcile(); // save to the file cache
// rename the `src` folder as an example
const oldPath = path.resolve(__dirname, './src');
const newPath = path.resolve(__dirname, './src2');
fs.renameSync(oldPath, newPath);
// update all the keys
cache.renameAbsolutePathKeys(oldPath, newPath);
// they are now updated in memory, update the disk cache
cache.reconcile();There are more updates around this with a faster caching layer and more robust features that you can read about at the README: https://github.com/jaredwray/cacheable/blob/main/packages/file-entry-cache/README.md Please let me know how I can help to make this happen. If you want to do a video conference just let me know. https://fantastical.app/jaredwray/30-minute-sync |
A problem with this is that we don't know |
|
To clarify, the example with renaming the directory was made to simplify the repro. The use case this RFC targets is when the cache file is created/updated on one machine, and then should be used on another machine where the project is possibly cloned into a different path so the absolute paths of files are different. We think the only way to achieve this is by storing relative instead of absolute paths in the cache file. |
In this example, the cache key for the file is |
|
@mdjermanovic @jaredwray at this point it seems better to open an issue to contain this back-and-forth instead of continuing on in this RFC. What do you think? |
Who can I work with on this to get it completed? More than happy to schedule a time as with the new file-entry-cache this should be really easy and less work. |
|
I think @mdjermanovic is the best person to work with. |
|
Here's an issue on the file-entry-cache repo for further discussion: jaredwray/cacheable#914 |
|
@cs6cs6 @nzakas - Just FYI that we will have this released in September. jaredwray/cacheable#914 |
|
@jaredwray thanks! @mdjermanovic can you take a look and make sure it's doing what you expect? |
Yes, I left a comment in the related issue: jaredwray/cacheable#914 |
|
@nzakas and @mdjermanovic - we are really close on this. jaredwray/cacheable#914 (comment) |
|
A couple of differences I noticed while testing
None of these differences seem problematic, but we'll need to make a few small changes in the code. |
| ] | ||
| ``` | ||
|
|
||
| ### Adding the command line parameter |
There was a problem hiding this comment.
I'm assuming this will also be a new ESLint constructor option, so we should mention that as well.
|
@mdjermanovic - I can make this work in v11. |
|
@mdjermanovic - on |
I think it isn't necessary. We can update ESLint to store custom data in the property that the file-entry-cache API provides for it ( None of differences described in #114 (comment) seem problematic, I just wanted to mention them as a reminder for when we update the file-entry-cache dependency to v11. |
I got |
|
file-entry-cache v11.0.0 has been released. Here's an example of how to achieve portable cache files with paths relative to the cache file location. // write.js
const path = require('node:path');
const fileEntryCache = require('file-entry-cache'); // v11.0.0
// cache file is cache/.eslintcache
const cacheDirectory = path.resolve(__dirname, 'cache');
const cacheFilename = '.eslintcache';
const cache = fileEntryCache.create(
cacheFilename,
cacheDirectory,
{
useCheckSum: true, // --cache-strategy content
cwd: cacheDirectory, // this means relative file paths should be treated as relative to the cache file location
}
);
const fullFilePath = path.resolve(__dirname, "src/a.js");
// path relative to the cache file location, normalized to posix
const filePath = path.relative(cacheDirectory, fullFilePath).replace(/\\/gu, "/");
const fileDescriptor = cache.getFileDescriptor(filePath);
// store custom data in the cache entry
fileDescriptor.meta.data = { foo: "bar" };
// save cache
cache.reconcile();// read.js
const path = require('node:path');
const fileEntryCache = require('file-entry-cache'); // v11.0.0
// cache file is cache/.eslintcache
const cacheDirectory = path.resolve(__dirname, 'cache');
const cacheFilename = '.eslintcache';
const cache = fileEntryCache.create(
cacheFilename,
cacheDirectory,
{
useCheckSum: true, // --cache-strategy content
cwd: cacheDirectory, // this means relative file paths should be treated as relative to the cache file location
}
);
const fullFilePath = path.resolve(__dirname, "src/a.js");
// path relative to the cache file location, normalized to posix
const filePath = path.relative(cacheDirectory, fullFilePath).replace(/\\/gu, "/");
const fileDescriptor = cache.getFileDescriptor(filePath);
console.log(fileDescriptor);
/*
{
key: '../src/a.js',
changed: false, // <-- cache hit 👍
meta: {
size: 3,
mtime: 1760181555466,
hash: 'acbd18db4cc2f85cedef654fccc4a4d8',
data: { foo: 'bar' }
}
}
*/ |
|
@cs6cs6 now that this is unblocked, would you like to continue working on this RFC? |
|
Closing due to inactivity. Thanks for your work on this RFC, I'll continue in a new PR. |
…velopers or into ci machines.
Summary
Related Issues