Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support checksyncrc files #812

Merged
merged 20 commits into from
Dec 15, 2021
Merged

Support checksyncrc files #812

merged 20 commits into from
Dec 15, 2021

Conversation

somewhatabstract
Copy link
Owner

@somewhatabstract somewhatabstract commented Nov 22, 2021

Summary:

This adds support for configuration files so that we don't have to supply all options on the command line.
It also adds test coverage for our output sink class and some other light tweaks.

This is the last piece for CheckSync v3! (Though I may try addressing #666)

Note to reviewers:

Much of this diff is test and snapshots updates. I recommend filtering out .snap files and skipping over _test.js files to look at the JSON and JS file changes.

Fixes #664

Test plan:

yarn test
yarn flow

@codecov
Copy link

codecov bot commented Nov 22, 2021

Codecov Report

Merging #812 (037a0fc) into main (772deb8) will not change coverage.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##              main      #812    +/-   ##
==========================================
  Coverage   100.00%   100.00%            
==========================================
  Files           28        34     +6     
  Lines          455       682   +227     
  Branches        85       145    +60     
==========================================
+ Hits           455       682   +227     
Impacted Files Coverage Δ
src/exit-codes.js 100.00% <ø> (ø)
src/get-files.js 100.00% <ø> (ø)
src/marker-parser.js 100.00% <ø> (ø)
src/types.js 100.00% <ø> (ø)
src/ancesdir-or-currentdir.js 100.00% <100.00%> (ø)
src/cli.js 100.00% <100.00%> (ø)
src/default-options.js 100.00% <100.00%> (ø)
src/determine-options.js 100.00% <100.00%> (ø)
src/file-reference-logger.js 100.00% <100.00%> (ø)
src/find-configuration-file.js 100.00% <100.00%> (ø)
... and 15 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7805955...037a0fc. Read the comment docs.

@somewhatabstract somewhatabstract added this to the CheckSync 3.0.0 milestone Nov 22, 2021
Comment on lines +1 to +18
{
"$schema": "./src/checksync.schema.json",
"$comment": "This is the config file for our integration tests. By not specifying it directly, we also test configuration file discovery.",
"autoFix": false,
"comments": [
"//",
"#",
"{/*"
],
"dryRun": false,
"excludeGlobs": [
"**/excluded/**"
],
"ignoreFiles": [
"**/ignore-file.txt"
],
"json": false
}
Copy link
Owner Author

Choose a reason for hiding this comment

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

An example config file for checksync. Note that the schema can be specified at the top of the file as per JSON Schema specifications (the schema is shipped with the tool).

Note that folks don't need to include this - their configs will still be validated against this schema, regardless. However, for tools like VSCode, this tells it what schema to use and provides autocomplete/intellisense accordingly.

@@ -0,0 +1,55 @@
declare module "@hyperjump/json-schema" {
Copy link
Owner Author

Choose a reason for hiding this comment

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

Pieced this together from typescript and reading the code.

@@ -0,0 +1,79 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
Copy link
Owner Author

Choose a reason for hiding this comment

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

This is the JSON Schema definition file against which our config files will be compared.

Comment on lines +26 to +27
// NOTE: minimist treats `no` on the front of a known flag
// as a flag inversion of the none-`no` version.
Copy link
Owner Author

Choose a reason for hiding this comment

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

I learned this the hard way. Nice default feature, if you know it exists.

const schema = await JsonSchema.get("file://./checksync.schema.json");

log.verbose(() => `Validating configuration`);
const validation = await JsonSchema.validate(
Copy link
Owner Author

Choose a reason for hiding this comment

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

The validation does include details of the actual errors, but it requires some work to turn that into human readable info that can be acted upon, so I'm going to not do that for now.

Comment on lines +3 to +4
export {default as checkSync} from "./check-sync.js";
export {default as loadConfigurationFile} from "./load-configuration-file.js";
Copy link
Owner Author

Choose a reason for hiding this comment

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

Checksync can now be used as an API. Should help with eslint integration, @kevinbarabash

Copy link
Collaborator

Choose a reason for hiding this comment

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

This should improve performance of our eslint rule significantly.

*/
const regex =
const rootDirRegex = new RegExp(escapeRegExp(ROOT_DIR), "g");
Copy link
Owner Author

Choose a reason for hiding this comment

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

The verbose logging mode includes file paths - to make sure they pass, we strip the root dir off them.


const line = `${" ".repeat(this._groupIndent)}${args
.map(normalize)
.join("")}`.trimRight();
Copy link
Owner Author

Choose a reason for hiding this comment

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

Trailing whitespace isn't really relevant and it can be annoying in inline snapshots when saving as eslint/prettier autofixes away empty lines. So, we trim the trailing whitespace

Copy link
Collaborator

Choose a reason for hiding this comment

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

I've run into this elsewhere and agree, so annoying.

@kevinbarabash
Copy link
Collaborator

Thanks for adding support for config files. I'll have a look later this week.

Copy link
Collaborator

@kevinbarabash kevinbarabash left a comment

Choose a reason for hiding this comment

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

LGTM. Supporting rc files is a great addition to checksync. I left a few comments, but nothing blocking.

.vscode/settings.json Show resolved Hide resolved
@@ -38,6 +38,7 @@
"@babel/preset-env": "^7.16.4",
"@babel/preset-flow": "^7.16.0",
"@babel/register": "^7.16.0",
"@hyperjump/json-schema": "^0.17.2",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why did you pick @hyperjump/json-schema over ajv? Is it faster?

Copy link
Owner Author

Choose a reason for hiding this comment

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

It seemed to support more recent drafts of the spec and have a better rep over all.

Copy link
Owner Author

Choose a reason for hiding this comment

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

That and it was one of the first i landed on that did what I want (I found it via the jsonschema.org site). I could be persuaded to change it. It worked so I stopped looking.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I was curious about the speed because I tried to use ajv in the past and it was slow for the schema I had written. It could also been that my schema was overly complex. 🤷‍♂️

Comment on lines +12 to +14
// Where our coverage data does and does not come from.
collectCoverageFrom: ["src/**/*.js", "!src/__tests__/*.js"],

Copy link
Collaborator

Choose a reason for hiding this comment

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

It's too bad jest doesn't automatically filter out test files from coverage.

src/checksync.schema.json Outdated Show resolved Hide resolved
Comment on lines 24 to 38
"comments": {
"description": "An array of the strings that identify the starts of comments in the files being parsed",
"type": "array",
"items": {
"type": "string"
},
"uniqueItems": true,
"minLength": 0
},
Copy link
Collaborator

Choose a reason for hiding this comment

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

It looks like json-schema support defaults. If you end up generating docs from this schema file then including defaults might be useful. I'm not sure how schema parsing libraries deal with defaults. It would be nice if you could pass it an empty JSON object and it would return an object with all the defaults.

Copy link
Owner Author

Choose a reason for hiding this comment

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

I seem to recall including defaults in an earlier version, but I decided against it. I don't recall why. I'll check.

Comment on lines +8 to +9
export const optionsFromArgs = (args: minimistOutput): $Shape<Options> => {
const options: $Shape<Options> = {};
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: maybe use Partial instead of $Shape.

Copy link
Owner Author

Choose a reason for hiding this comment

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

It doesn't work for this situation.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I thought that Partial was just a better version of $Shape. Do they handle optionality differently?

Copy link
Owner Author

Choose a reason for hiding this comment

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

No, so Partial as I understand it, says "I am a type that is any combination of the values within this type" whereas $Shape says, "I look like this type, but all my values are optional" or something along those lines.

So T can be considered equal to $Shape<T> it seems, but T is not equal to Partial<T>.

At least, that's my basic understanding.

Comment on lines +14 to +17
const excludeGlobs = (args.ignore: any)?.split(";").filter((c) => !!c);
if (excludeGlobs != null) {
options.excludeGlobs = excludeGlobs;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can ignore be false like ignoreFiles?

Copy link
Owner Author

Choose a reason for hiding this comment

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

No, it doesn't work that way - it's either a string, or its not provided. The main reason for the ? is to work around the ambiguity of minimist typing and the fact that this argument may not be supplied.

Comment on lines +41 to +43
if (args.dryRun != null) {
options.dryRun = !!args.dryRun;
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does minimist not provide booleans or is this just to convince Flow that these values are actually booleans?

Copy link
Owner Author

Choose a reason for hiding this comment

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

minimist types args as boolean | string | void, I believe. So we need to coerce them to booleans for Flow to recognize we did the right thing.

src/output-sink.js Show resolved Hide resolved

const line = `${" ".repeat(this._groupIndent)}${args
.map(normalize)
.join("")}`.trimRight();
Copy link
Collaborator

Choose a reason for hiding this comment

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

I've run into this elsewhere and agree, so annoying.

Comment on lines +46 to +48
// Could be in the working directory too, so we add a fake child
// to the path that ancesdir will cut off to start the search
// in parent locations, which will then be the cwd.
Copy link
Owner Author

Choose a reason for hiding this comment

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

NIT: don't need to be so specific here since I added the helper method for this

Comment on lines +43 to +65
const closestRCPath = checkSyncRcNames
.map((rc) => {
try {
// Could be in the working directory too, so we add a fake child
// to the path that ancesdir will cut off to start the search
// in parent locations, which will then be the cwd.
return path.join(ancesdirOrCurrentDir(process.cwd(), rc), rc);
} catch (e) {
return "";
}
})
.filter((f) => f != "")
.map((rcPath) => ({
rcPath,
distance: path.relative(process.cwd(), rcPath).split(path.sep)
.length,
}))
.reduce((acc, cur) => {
if (acc == null || cur.distance < acc.distance) {
return cur;
}
return acc;
}, null);
Copy link
Owner Author

Choose a reason for hiding this comment

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

So, if we execute just checksync we want it to just work, and this caters to that. Means that even in webapp, we could just run it and it should work, even before it knows the root marker

src/get-files.js Show resolved Hide resolved
src/help.js Show resolved Hide resolved
Comment on lines +25 to +27
if (!rcForValidation.$schema) {
rcForValidation.$schema = "file://./checksync.schema.json";
}
Copy link
Owner Author

Choose a reason for hiding this comment

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

It should still validate against our schema, but their tooling will probably complain (if it supports schemas, like vscode for example).

And yes, I believe we do need to set the schema still. The idea is we're asking "validate against this set of schema" and the reference tells it which of those schema to start at. Something like that. I know I had to do a few incantations to get things working.

Comment on lines +8 to +9
export const optionsFromArgs = (args: minimistOutput): $Shape<Options> => {
const options: $Shape<Options> = {};
Copy link
Owner Author

Choose a reason for hiding this comment

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

No, so Partial as I understand it, says "I am a type that is any combination of the values within this type" whereas $Shape says, "I look like this type, but all my values are optional" or something along those lines.

So T can be considered equal to $Shape<T> it seems, but T is not equal to Partial<T>.

At least, that's my basic understanding.

@somewhatabstract somewhatabstract merged commit 1b7b343 into main Dec 15, 2021
@somewhatabstract somewhatabstract deleted the somewhatabstract/issue664 branch December 15, 2021 22:30
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.

.checksyncrc file
2 participants