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

Adding additional configuration file options #436

Closed
wants to merge 264 commits into from

Conversation

mcknasty
Copy link
Contributor

@mcknasty mcknasty commented Dec 4, 2022

Pull Request 436

Commit Message

commit 22a9c08
Author: The Nasty tmckeown@gmail.com
Date: Sat Jan 20 13:51:03 2024 -0500

Additional Configuration File Support (#436)

feat: Adding additional configuration file options
test: unit test for config file detection
test: unit test for config files pass via the cli
test: unit test case for early exit of hideInstrumenteeArgs
test: unit test for Node.js argument handling
fix: bug in spawning of c8 process that dropped coverage significantly

Following the Contributions Recommendations here.

  1. Make sure you have installed the latest version of Node.js
  2. Fork this project on GitHub and clone your fork locally
  3. Create local branches to work within. These should also be created directly from the main branch. Local Fork here.
  4. Make your changes.
  5. Run tests to make sure all is okay (everything should pass except the snapshot).
    1. A complete log of initial test results.
    2. As instructed, ignore snapshot failures. 17 pending
    3. 120 passing in 53 seconds
  6. Now update the snapshot.
    1. A complete log of snapshot test results.
    2. 120 passing in 52 seconds
  7. If all is passing, commit your changes. The log of the commit can be found here.
  8. As a best practice, once you have committed your changes, it is a good idea to use git rebase (not git merge) to synchronize your work with the main repository.
  9. Run tests again to make sure all is okay.
    1. A complete log of the final test results.
    2. 120 passing in 54 seconds
  10. Push
  11. Open the pull request, see details in the template.
  12. Make any necessary changes after review.

Unit Tests Results

Test Type PASS Tests Passed Tests Pending Time
Initial Test ✔️ 120 passing 17 pending 53 seconds
Snapshot Test ✔️ 120 passing 17 pending 52 seconds
Final Test ✔️ 120 passing 17 pending 54 seconds
  • Test completed in Node version v18.19.0

Node Version Testing Matrix

Node Version PASS Tests Passed Tests Pending Time
14.21.3 ✔️ 120 passing 17 pending 1 minutes
16.20.2 ✔️ 120 passing 17 pending 57 seconds
18.19.0 ✔️ 120 passing 17 pending 1 minutes
20.11.0 ✔️ 120 passing 17 pending 1 minutes

Duplicate of #447
References #448

  • edited 2022-12-05 4:58 AM EST. I noticed an error in my last patch, so I updated it.
  • edited 2023-02-20 12:41 PM EST. Updated pull request readme to the new format and linked existing issues.
  • edited 2023-07-28 11:50 AM EST. Adding additional unit tests for each of the config file options.
  • edited 2023-07-29 1:14 PM EST. Adding test case for loading invalid config files and updating readme to clarify ESM support.
  • edited 2024-01-08 3:17 PM EST. Fixing error that was causing code coverage drops. Changing Commit Message to include omitted items.
  • edited 2024-01-20 3:09 PM EST. Added test name for chia-snapshots. Skipped tests that require (feat: show derived configuration #517) to be merged. Updated an error handling test.

bcoe and others added 30 commits December 17, 2017 12:07
BREAKING CHANGE: switches to using NODE_V8_COVERAGE rather than inspector directly
Clarify project goals: I'd like this project to demonstrate a powerful code coverage solution relying primarily on native V8 functionality, and minimal user-land modules -- @bcoe
- issue template
- PR template
- contributing guide
- maintainers guide

closes bcoe#35
This commit fixes the conversion from `file://` urls to system-dependent paths. It ensures that it works on Windows and with special characters.
@mcknasty
Copy link
Contributor Author

mcknasty commented Jan 15, 2024

Overview

👏 The Good - This Pull Request is getting close. This PR is ready to go!
👌 The Bad - Need to get Another Pull Request merged before this one is ready to go. would get the rest of the unit tests ready. (#517)
👊 The Ugly - One of the Workflows is causing errors on multiple a pull request. (#453)

Update; There seems to be a dependency that has been updated that is solving some of these CD/CD concerns. Keeping the package-lock.json version number to 2 also seems to help for Node 14.

Workflow Errors

commit id checkout: 27d619c1b6005d0563098ab2d9909117586aa852
npm ci --engine-strict command failing

Run npm ci --engine-strict
  npm ci --engine-strict
  shell: /usr/bin/bash -e {0}
npm ERR! Cannot read property '@bcoe/v8-coverage' of undefined

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/runner/.npm/_logs/2024-01-15T05_55_22_507Z-debug.log
Error: Process completed with exit code 1.

Attempt to Reproduce Locally

$ git remote -v
origin  git@github.com:mcknasty/c8.git (fetch)
origin  git@github.com:mcknasty/c8.git (push)
upstream        https://github.com/bcoe/c8.git (fetch)
upstream        https://github.com/bcoe/c8.git (push)
$ git branch | grep '*'
* additional-config-files
$ git log | head -n 1
commit 27d619c1b6005d0563098ab2d9909117586aa852
$ node -v
v14.21.3
$ npm -v
9.8.1
$ npm ci --engine-strict

added 383 packages, and audited 384 packages in 5s

98 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
$ uname --all
Linux XXXXXXXXX 5.15.133.1-microsoft-standard-WSL2 #1 SMP Thu Oct 5 21:02:42 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

Is there a way to run the github actions locally? I initially tried a package called act. I didn't spend a ton of time with it, but it seemed to have some challenges. Are there any other packages I can try to reproduce this error or some additional information on act that could reproduce the errors in the workflow?

  • Updated 2024-01-20 at 12:49 PM EST. Added Reference to pull request for print config

test: absolute directories for tmpDir and reportsDir
test/parse-args-helper.js Outdated Show resolved Hide resolved
mcknasty added a commit to mcknasty/c8 that referenced this pull request Jan 20, 2024
feat: Adding additional configuration file options
test: unit test for config file detection
test: unit test for config files pass via the cli
test: unit test case for early exit of hideInstrumenteeArgs
test: unit test for Node.js argument handling
mcknasty added a commit to mcknasty/c8 that referenced this pull request Jan 20, 2024
feat: Adding additional configuration file options
test: unit test for config file detection
test: unit test for config files pass via the cli
test: unit test case for early exit of hideInstrumenteeArgs
test: unit test for Node.js argument handling
@mcknasty mcknasty force-pushed the additional-config-files branch 2 times, most recently from 0897804 to a534f68 Compare January 20, 2024 08:47
mcknasty added a commit to mcknasty/c8 that referenced this pull request Jan 20, 2024
feat: Adding additional configuration file options
test: unit test for config file detection
test: unit test for config files pass via the cli
test: unit test case for early exit of hideInstrumenteeArgs
test: unit test for Node.js argument handling
fix: bug in spawning of c8 process that dropped coverage significantly
@mcknasty
Copy link
Contributor Author

mcknasty commented Jan 20, 2024

Skipped the config detection tests for the moment. Ready to go from my perspective.


// Should the process die if none of these filename extensions are found?
if (Object.keys(config).length === 0) {
throw new Error(`Unsupported file type ${ext} while reading file ${path}`)
Copy link

Choose a reason for hiding this comment

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

I read why this was added, but it's going to result in bad UX when a config file return an empty object - in that situation it loaded fine, and is not an invalid file type, it's just not got any config entries.

Copy link
Contributor Author

@mcknasty mcknasty Jan 21, 2024

Choose a reason for hiding this comment

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

I want to be sure I am clear on what you stated above. To rewrite what you expressed in two use cases.


Scenario:

A user executes the c8 command with the --config parameter set to an existing file on the file system

Given:

The file has a valid file name as documented in the c8 readme
The file has no contents.

Result:
c8 will run with a default configuration


Scenario:

A user executes the c8 command without additional configuration arguments and c8 discovers a configuration file.

Given:
The file has a valid file name as documented in the c8 readme
The file has no contents.

Result:
c8 will run with a default configuration


Can you please confirm?

The block does cover the following use case.


Scenario:
A user executes the c8 command with the --config parameter set to an existing file on the file system.

Given:
The file does not have a valid file name as documented in the c8 readme

Result:
c8 will produce the error `Unsupported file type ...'


This test case can be found on Line 70 - Line 85 of the file test/parse-args.js

Copy link

Choose a reason for hiding this comment

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

Some notes before I hit the scenarios:

  1. Only YAML would have an empty file return an empty object.
  2. An empty JSON file is a syntax error.
  3. A JSON file of {} is valid.
  4. A CJS script that doesn't export anything IMO SHOULD result in an error as this is a common mistake.
  5. A CJS script that exports an empty object, e.g. {} is valid.

So, scenarios:


Scenario:
A user executes the c8 command with the --config parameter set to an existing file on the file system
OR
A user executes the c8 command without the --config parameter set AND c8 discovers a configuration file.

Given any of:

  • The file is JSON with the .json extension, case insensitive.
    The file has the contents {} or equivalent.
  • The file is YAML with the .yaml or .yml extension, case insensitive.
    The file has no contents
  • The file is CommonJS with the .js or .cjs extension, case insensitive.
    The file's contents result in an empty object {} being exported.

Result:
c8 will run with a default configuration.


Scenario:
A user executes the c8 command with the --config parameter set to an existing file on the file system
OR
A user executes the c8 command without the --config parameter set AND c8 discovers a configuration file.

Given any of:

  • The file has the .json extension, case insensitive.
    The file is invalid JSON.
  • The file has the .yaml or .yml extension, case insensitive.
    The file is invalid YAML.
  • The file has the .js or .cjs extension, case insensitive.
    The file's contents are invalid CommonJS or have a runtime error.
  • The file has the .js or .cjs extension, case insensitive.
    The file doesn't export anything.
  • The file has the .js or .cjs extension, case insensitive.
    The file exports something that's not an object.

Result:
c8 will fail with an appropriate error based on the actual underlying problem that will be helpful to the user.

Some errors are really very obtuse or otherwise mask the real problem. I think over time of people testing this those errors will be discovered and made nicer, so making the errors nicer probably shouldn't be part of this PR.


Scenario:
A user executes the c8 command with the --config parameter set to an existing file on the file system.

Given:
The file name is NOT one of the ones documented in the c8 readme.
The file extension is one of the valid types, e.g. .js, .cjs, .json, .yaml, .yml etc.
The file returns a valid c8 configuration.

Result:
c8 will run with the configuration coming from the file given.

This is because there are several reasons for using the --config parameter, here's just a few:

  1. I've got multiple config files to choose from. This you've covered.
  2. My config file's at an unusual path that auto detection won't find, e.g. .configs/c8rc.yaml This I'm pretty sure you've covered, though maybe not directly with a test.
  3. I don't like any of the default file names and have my own naming scheme I use, e.g. .config.c8.yaml - the current code looks like it handles this case already, there just doesn't seem to be a test covering this idea.

Copy link

Choose a reason for hiding this comment

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

I've created a PR for the branch of this PR that adds tests and changes to support the above.

Comment on lines +204 to +210
if (jsExts.includes(ext)) {
config = require(path)
} else if (ymlExts.includes(ext)) {
config = require('js-yaml').load(readFileSync(path, 'utf8'))
} else if (ext === '.json' || fileName.slice(-2) === 'rc') {
config = JSON.parse(readFileSync(path, 'utf8'))
}
Copy link
Contributor Author

@mcknasty mcknasty Jan 21, 2024

Choose a reason for hiding this comment

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

I am going to put this into a try/catch block for the following reasons ...

  1. If a not properly formated json or yaml object is returned, it will produce an error.
  2. If the path doesn't exist, it will produce an error.
  3. If an unsupported configuration value is present in the configuration file, the value will get ignored.

It could be helpful to have a config schema validator. Going to add unit tests for two of the potential issues above.

Copy link

Choose a reason for hiding this comment

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

I agree on a schema validator. It would help people a lot.

However masking erroneous configuration files by just ignoring them, or even just logging the problem and proceeding with defaults, is an antipattern to me. It results in unexpected behavior since c8 proceeds with different settings than intended.

Copy link

@kf6kjg kf6kjg Jan 25, 2024

Choose a reason for hiding this comment

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

In my PR to this PR I did wrap some of these in try-catch, but I only caught specific errors, re-thowing the others. The idea was to enhance the message in those cases as the underlying error was obtuse. However I think that other errors, such as file not found, are generally acceptable to leave alone.

JSON.parse is very well known for producing REALLY opaque errors. Unexpected end of JSON input always got me.

test/parse-args-helper.js Outdated Show resolved Hide resolved
mcknasty added a commit to mcknasty/c8 that referenced this pull request Feb 1, 2024
feat: Adding additional configuration file options
test: unit test for config file detection
test: unit test for config files pass via the cli
test: unit test case for early exit of hideInstrumenteeArgs
test: unit test for Node.js argument handling
fix: bug in spawning of c8 process that dropped coverage significantly
feat: Adding additional configuration file options
test: unit test for config file detection
test: unit test for config files pass via the cli
test: unit test case for early exit of hideInstrumenteeArgs
test: unit test for Node.js argument handling
fix: bug in spawning of c8 process that dropped coverage significantly
@kf6kjg
Copy link

kf6kjg commented Feb 2, 2024

Wait what, why closed?😳

@mcknasty
Copy link
Contributor Author

mcknasty commented Feb 2, 2024

sorry was editing my name in the commit history and it closed the branch. I'll fix it.

mcknasty added a commit to mcknasty/c8 that referenced this pull request Feb 2, 2024
feat: Adding additional configuration file options
test: unit test for config file detection
test: unit test for config files pass via the cli
test: unit test case for early exit of hideInstrumenteeArgs
test: unit test for Node.js argument handling
fix: bug in spawning of c8 process that dropped coverage significantly
mcknasty added a commit to mcknasty/c8 that referenced this pull request Feb 2, 2024
feat: Adding additional configuration file options
test: unit test for config file detection
test: unit test for config files pass via the cli
test: unit test case for early exit of hideInstrumenteeArgs
test: unit test for Node.js argument handling
fix: bug in spawning of c8 process that dropped coverage significantly
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.

None yet