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 support for a dedicated configuration file #520

Closed
kkemple opened this issue Feb 7, 2016 · 36 comments
Closed

Adding support for a dedicated configuration file #520

kkemple opened this issue Feb 7, 2016 · 36 comments

Comments

@kkemple
Copy link

kkemple commented Feb 7, 2016

I'm not sure how viable this is currently due to the way pkg-conf is walking up until it finds a package.json file, but it would be nice to be able to set ava config in an .avarc file in the root of the project.

I'm not a huge fan of keeping config in my package.json or of overly verbose cli commands in scripts config. This is also pretty common practice with other tooling frameworks so I don't think it's too crazy of an idea.

I think an initial approach could be to check the current working directory for a .avarc file and if not found fall back to pkgConf.sync.

I would be more than willing to put together a PR if this seems like something you find appealing.

@sindresorhus
Copy link
Member

We're intentionally only using package.json for simplicity and consistency.

I'm not a huge fan of keeping config in my package.json

Why? We are not big fans of having an endless amount of meta files in our repos. It's IMHO nice to have one place for all config. This is becoming more and more common, with both AVA, ESLint, XO, nyc, standard, etc, tools doing it.

This is also pretty common practice with other tooling frameworks

Common practice doesn't necessarily mean it's a good one.

@kkemple
Copy link
Author

kkemple commented Feb 7, 2016

okay, thanks for the response

@kkemple kkemple closed this as completed Feb 7, 2016
@mattecapu
Copy link

Why? We are not big fans of having an endless amount of meta files in our repos

I am. I prefer separation over concentration, and it's handy to just ctrl-c ctrl-v a dotfile. That said, I think no one is really wrong or right and is just a matter of taste.

From what I can see, to add support for a dotfile there are just a handful of lines to edit in cli.js, profile.js and test/cli.js.

My naive implementation would just grab the config object from .avarc instead of package.json. A one-liner. I'd be really happy to make a PR for this (also because I love this project and I'd like to contribute). The only thing to decide is precedence, and I'll leave package.json first for legacy reasons.

Are there any complications I'm overlooking?

@sindresorhus
Copy link
Member

@mattecapu Sorry, we're not interested in having multiple ways to define config.

@calebmer
Copy link

calebmer commented May 7, 2016

Bump. For all my projects, my babel configuration is in a dot file, my eslint config is in a dot file, my editor config is in a dotfile, but my ava config has to be in my package.json.

This doesn't seem like a hard feature to implement and pretty much every other major tool in the JS ecosystem allows this style.

@jamestalmage
Copy link
Contributor

This is not going to get implemented until someone can demonstrate an actual need.

There are plenty of tools that just use package.json (browserify, nyc, xo, etc.). Adding multiple ways to do something "just because" is a quick road to project bloat. Users then have to ponder which method is "the better fit for their project", instead of just getting on with making things.

You could conceivably use global installs of eslint and babel on projects that don't have a package.json because they aren't Node based (that is less true of babel@6 than it was of babel@5, but whatever). You could make the argument that a package.json requirement for those was restrictive / confusing (it's a weak argument, but it's an argument). Some people have hundreds of rules in their eslint config - another decent argument. Putting an editorconfig in package.json would be nonsensical - it's a separate standard that has nothing to do with Node / npm.

My point here, is demonstrate some actual need. "Because I want" is not sufficient. Neither is "because project X does it that way". If not having the option is legitimately preventing you from getting things done, and you demonstrate why, we will happily change our minds.

@diegohaz
Copy link

diegohaz commented Oct 9, 2016

There're some annoying things on putting the configuration in package.json instead of dot files. Besides which was already said here, every time I npm install --save something my babel config will become from this:

{
  "presets": ["es2015", "react", "stage-0"],
  "plugins": [
    ["resolver", {"resolveDirs": ["app"]}]
  ],
  "env": {
    "development": {
      "plugins": ["react-hot-loader/babel"]
    }
  }
}

to something like this due to package.json auto re-indent:

{
  "presets": [
    "es2015", 
    "react", 
    "stage-0"
  ],
  "plugins": [
    [
      "resolver", {
        "resolveDirs": [
          "app"
        ]
      }
    ]
  ],
  "env": {
    "development": {
      "plugins": [
        "react-hot-loader/babel"
      ]
    }
  }
}

Also, eslintConfig rules are terribly indented in package.json.

Because of this I do prefer to keep it on dotfiles, but I can't do this with ava. 😭

@bdentino
Copy link

Here's a concrete use-case. I run a bunch of my integration tests using ava inside a docker container orchestrated via docker-compose. My docker image takes significantly longer (~100x) to rebuild when i modify package.json (since it has to re-run npm install). because i have to define ava defaults in this file, any change to those forces a pretty long and usually unnecessary rebuild. this is a relatively minor inconvenience but i definitely feel the pain when i'm setting up a new project, debugging test timeouts, trying to find an optimal concurrency limit, etc. i can of course specify other defaults on the command line or in custom scripts, but at that point i'm being forced to break from the concept of consolidating these defaults in one place anyways so it seems like having a file like .avarc would just be a better alternative.

i'm not gonna be all torn up inside if this never happens, but given that this project places a high value on developer workflow, productivity, and speed it seemed like a reasonable use-case to share.

@jeffijoe
Copy link

jeffijoe commented Nov 1, 2016

Neither is "because project X does it that way".

There are a bunch of "project X" out there that does have a dotfile for config. It was mentioned that nyc did not, and that was true until not so long ago.. I'd say that "because project X does it that way" is a valid argument if there are more than just a few cases.

I don't see how adding support for dotfiles will ruin the experience for those who prefer package.json.

@ORESoftware
Copy link

@sindresorhus you are opening the door for every meta tool to now store info in package.json, just think about what that might mean :) It probably won't mean much, except small chance of namespace conflicts, and very large package.json files :)

@jtag05
Copy link

jtag05 commented Dec 26, 2017

I was a large proponent of package.json based configs for the exact reasons you've offered here. Once I built a large project with that mentality and had numerous tools and environments to account for it became completely unruly and I quickly changed my tune. Also this is just imposing your thoughts on what is the right way to configure a project rather than allowing a developer to make that choice.

@danawoodman
Copy link

If this is implemented I’d recommend looking at cosmiconfig.

@jtag05
Copy link

jtag05 commented Jan 4, 2018

I submitted PR #1627 resolving this issue. It's seriously trivial to implement. Hopefully the maintainers will consider adopting it. I have no interest in maintaining a separate fork for 7 lines of code difference, but find it strange that there has been such a strong pushback against something that has no effect on the library's performance.

@pho3nixf1re
Copy link

I am cross-posting this from #1627 so it stays with the mainline of discussion.

@novemberborn there is a perfectly valid argument from @jtag05. The package.json file has become a dumping ground for configuration. In large projects it makes it huge and unwieldy. Digging through a giant JSON file is not a pleasant experience and is reminiscent of the Java world's XML configs. My team prefers the dotfiles as it neatly separates each tool's configuration that is easily explorable. It is not just because "we are used to it". Every other tool we use manages to support this trivial feature that we value but AVA. It seems absurd that even in the face of community outcry and the presence of a perfectly fine PR the maintainers here ignore the need.

@novemberborn
Copy link
Member

It's been nearly two years since this issue was first raised, and yes alternative configuration files have seen more adoption since then, as have monorepo projects. I'm not ignoring the need. We're trying hard not to overcomplicate what AVA does and this has also applied to how it's configured. There's some effort involved in revisiting this decision that goes beyond the number of lines of code an implementation takes. To that end:

We'd need to consider where AVA would find these alternative files. Currently it finds the closest package.json file from where AVA is invoked. This also determines the working directory for the test processes. Presumably these configuration files can only live next to package.json files? Or do folks here have use cases where alternative configuration files should determine the working directory?

The current trend seems to be for JS-based configuration files. Would folks be upset if AVA supported ava.config.js files but not .avarc files?

Do monorepo folks expect .avarc files to support inheritance?

@jtag05
Copy link

jtag05 commented Jan 4, 2018

I can only speak for myself, but I tend to expect my .rc files to live in the project root and would expect the applications to respond based on current working directory.

In regards to the current trend of config.js files I tend to associate that with projects like webpack where the config itself can perform operations. Seeing as AVA currently doesn't operate that way it's hard for me to think of a use case where that would be particularly beneficial, but I also can't say for certain it wouldn't be.

I think that if you were to take the ava.config.js route, being able to define where that lives becomes more of a conversation. It's easy to parse .rc files as configuration whereas a .js file could have implications for regex based tooling. Perhaps adding a --config option to the cli would be in order to allow developers to define whatever .js file they like as well as where it is stored relative to the working directory.

As far as .avarc inheritance, I again can only speak for myself, but I would think that testing configurations are unique enough to not make this a pressing concern.

@pho3nixf1re
Copy link

pho3nixf1re commented Jan 4, 2018

My use cases follow the same logic that @jtag05 has presented. There isn't much of a use case for a js config file and if there is ever a need for it AVA can implement that at a later date. The current conversation here is to just provide an alternative location with the same implications as the current package.json setup. The MVP implementation requested here is for there to be an option for a co-located rc file that lives next to the package configs. It doesn't need to be more complicated than that as far as inheritance goes. It is a starting point that future changes can build upon if more complicated use cases present themselves. I also like the idea of supporting a --config flag that would allow further customization but it isn't necessary to implement up front.

@danawoodman
Copy link

Why not just use a standard tool like cosmiconfig which handles all these decisions and behavior for you?

@novemberborn
Copy link
Member

@jtag05 @pho3nixf1re, @danawoodman, thanks, I'm just trying to get a fuller picture.

A --config flag might be interesting in monorepo projects. Any thoughts on that?

I'm hesitant in supporting it just so folks can pick different names for the configuration files. And ironically you may want to configure that flag in say the package.json so you don't need to add it into the build tooling 😉

What would be the expected priority order between these various files? E.g. Babel 6 loads .babelrc before checking package.json. Babel 7 also checks .babelrc.js (and soon babel.config.js I believe), but throws an exception when it finds multiple configurations. How would you expect AVA to behave?

@danawoodman
Copy link

danawoodman commented Jan 5, 2018

—config has highest priority. Then it would be whatever config file is present. I don’t know where package.json fits but Cosmiconfig probably documents which is highest priority. The project Prettier just adopted cosmiconfig after a long discussion and it worked out great. I’m using it too on my own projects and it’s very easy to integrate.

@danawoodman
Copy link

Using a prexisting tool that many projects use is much preferable than a “roll your own” approach in my opinion. Convention is good!

@danawoodman
Copy link

@sindresorhus are you sure you’re not willing to reconsider your stance on this? As outlined, there are a lot of good reasons to make this change and the only reason not to is “we don’t want multiple ways to configure things”. If you use a tool like cosmiconfig you don’t have to make any decisions as the tool does it for you. This means AVA stays simple because it just says “use cosmiconfig to handle config”. Nearly every major project has a dot file/config file (Babel, Prettier, Mocha, Lerna, nvm, etc.) and I believe it is because there are legitimate reasons to do this. Please reconsider so that users of AVA have options that work for them. Thanks!

@novemberborn
Copy link
Member

@danawoodman I'm also on the core team. We'll be taking all of this into account and go from there.

Meanwhile, please keep the feedback coming!

@danawoodman
Copy link

@novemberborn, good to know! Would be very excited to see this change. Being able to copy a config file from one project to another sure beats manually editing package.json 🕺 Also, I really do think having the config file would improve AVAs marketing because I know, at least for myself, that I’ve discovered lots of great tools by looking at a projects config files! Thanks!

@kkemple
Copy link
Author

kkemple commented Jan 5, 2018

After 2 yrs if you still need this that bad I recommend move to a framework that supports your needs. I opened this issue and have long since left Ava for Jest.

@novemberborn
Copy link
Member

novemberborn commented Jan 16, 2018

I've been thinking about this a bit. I can definitely see some interesting use cases for an ava.config.js configuration file. For instance certain behaviors can be changed dynamically during CI, or when Babel 7 support lands you could inline a Babel plugin.

I see less need for an .avarc file. If you want to write JSON you can do that in package.json. If you want to use a separate file there's ava.config.js. @danawoodman, looking at cosmicconfig it also ships with support for YAML files and config discovery, neither of which are needed with AVA.

I propose the following behavior:

  • When invoked, AVA walks the file hierarchy looking for a package.json file
  • AVA checks whether a sibling ava.config.js file exists
  • If the package.json file contains an "ava" configuration, and ava.config.js exists, AVA will exit with a warning about ambiguous configuration
  • Otherwise the package.json configuration takes precedence over ava.config.js
  • ava.config.js is loaded through esm so can be either a CJS or ESM file. The loader should support ESM transpilation by looking for a thruthy __esModule property: if set then the value of the default property is used
  • An actual configuration object may be exported, or a factory function
  • If a factory function is exported it'll be called with the project directory (for future compatibility). It must return a configuration object
  • The configuration object must not have a then property
  • (These are the same rules as for .babelrc.js files in Babel 7)

Down the line I'd be interested in exploring a --config argument. It would take precedence over both package.json and ava.config.js files, without ambiguity warnings. Multiple projects in a monorepo could use the same configuration through this argument (this is where passing the project directory to the factory function comes in). Perhaps we'd also support a string value for the "ava" key in package.json to point at a separate configuration file.

Eventually it'd also be good to support ESM for the configuration files, and allow asynchronous values. It'd also be good to have logic that can validate the configuration objects. In the meantime we could ship TS and Flow definitions (though we won't support ava.config.ts configuration files yet).

Thank you @jtag05, @pho3nixf1re and @danawoodman for pushing us on this issue. Please let me know if you're interested in implementing this before I get round to it.

@pho3nixf1re
Copy link

@novemberborn Although I disagree about the JSON format in an 'rc' file I am fine with the proposal. It solves the need and allows for a lot of future flexibility. Thank you for discussing this with us and coming up with a good compromise on the solution.

@novemberborn novemberborn changed the title Adding support for an .avarc configuration file Adding support for a dedicated configuration file Jan 18, 2018
@trusktr
Copy link

trusktr commented Feb 13, 2018

I know this issue is re-opened, but I'd like to add some points

demonstrate an actual need.

I decided to try Ava today for the first time, because it looks awesome. However, without so much as a --config option I can't use it. My use case: I store my build procedures and dependencies in a single package that is shared with all my projects, so I need to tell each tool where to read configuration from.

Despite how awesome Ava looks, I simply can't use it unless I can tell it where to look for configuration (in the shared package), and I want to avoid unwieldy command line arguments.

Furthermore, when configurations are stored in separate files (particularly in JSON form, or they export a JS object), it makes it easier for projects that use the shared config to be able to extend certain configs for their own needs.

Freedom of choice is the key here, it allows developer flexibility.

In my case, I'm making a setup that allows me to build many JS packages without having to configure each one ever again. Al I have to write in my packages is source with latest language features, and test files. The rest is all abstracted away and shared among all my JS packages. It is only possible (in a clean way) with tools that have configurable config location.


@novemberborn thanks for re-opening!

@trusktr
Copy link

trusktr commented Feb 13, 2018

By the way, hoping this makes it into v1.0.0 so I can come back to try it out later! Mostly everything about Ava seems really awesome, just that the config option is holding me back for now.

@novemberborn
Copy link
Member

@trusktr while less convenient than a --config flag, an initial implementation without it would still let you write an ava.config.js file which re-exports the config from your shared package.

@trusktr
Copy link

trusktr commented Feb 15, 2018

That's true, but means the project has to know about Ava. In my case, projects don't know about the tools, and no configs (even re-export types) need to exist in the project. It's completely decoupled. There's only, at maximum, a few package.json scripts that call generic prod, dev, and test commands on my Builder archetype.

@trusktr
Copy link

trusktr commented Feb 15, 2018

But, true, that could be "good enough" for the time being!

@good-idea
Copy link
Contributor

I'm not sure if this bloated thread needs another +1 comment, but my use cases are:

  1. Running ava on my src/__tests__ and dist/__tests__ with different configurations. I'd like to test the dist directory without using babel.
  2. Copying an ava.config.js from one project to another would be ideal.

@novemberborn
Copy link
Member

@good-idea well the feature is approved as of #520 (comment) — it's ready for somebody to pick up 😉

@good-idea
Copy link
Contributor

@novemberborn I'm looking into it right now. I'm a little confused by this line in your comment:

  • When invoked, AVA walks the file hierarchy looking for a package.json file
  • AVA checks whether a sibling ava.config.js file exists
  • ---> If this file contains an "ava" configuration, and ava.config.js exists, AVA will exit with a warning about ambiguous configuration
  • Otherwise the package.json configuration takes precedence over ava.config.js

When you say "this file" are you referring to package.json or ava.config.js? Or, to clarify:

  • If package.json contains an "ava" config property and ava.config.js exports a configuration, warn about ambiguous configuration.
  • If ava.config.js exists and does not export a configuration, use package.json.

Is that what you're thinking?

@novemberborn
Copy link
Member

@good-idea good catch. I meant to give the ambiguity warning if package.json contains an "ava" config property. I've updated my above comment.

I've also updated the comment to reflect that we should use esm to load the ava.config.js file. That way we can support export default syntax.

@avajs avajs locked as resolved and limited conversation to collaborators Jun 11, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests