vivaxy / vscode-conventional-commits

💬Conventional Commits for VSCode.
https://marketplace.visualstudio.com/items?itemName=vivaxy.vscode-conventional-commits
MIT License
324 stars 35 forks source link

[FEAT] reload commitlint config on each invocation #235

Open codeyourfaceoff opened 2 years ago

codeyourfaceoff commented 2 years ago

Is your feature request related to a problem? Please describe

Currently the commtilint config only gets loaded the first time the extension gets run in a project. This means that if I make changes to my scopes in my commitlint.config.js for instance I must reload my entire project window to get a new execution of this plugin.

Describe the solution you'd like

It'd be nice to not have to reload the entire vscode window each time to refresh updates to my config files and instead have the extension reload these settings each time I run Conventional Commits from the command palette.

Describe alternatives you've considered

A clear and concise description of any alternative solutions or features you've considered.

Additional context

I've actually gone a head and dug into why this happens a bit. From my findings I think it appears to be a combination of the way extensions in vscode run and the way the commitlint loads config files using require. Since vscode extensions get loaded on first init and then hangs around means once a config file is loaded by require it's cached and instead of reloading that file for subsequent uses of this extension, require just reuses the previous one meaning no updates until the entire vscode window is reloaded and thus the extension too.

I've patched my local version of this extension to get this functionality working, it's a bit hacky so I'd prefer to discuss the solution in this issue before submitting a PR.

Basically the solution is to simply clear require's cache of the known config files listed here. I couldn't find a good way of reusing the ones used by commitlint so for now a copy/paste is the only solution. Another alternative would be to just clear all of require's cache, but I wasn't sure if that would impact performance in anyway, so the safe bet felt to just copy the ones needed over.

Then, just before loading the config rules here we can simply loop through the array of config files and delete them from require's cache.

All in all the solution could look like this:

// line 134 of src/lib/conventional-commits.ts

      // 4. get commitlint rules
const configPaths = [
    // list of files taken from [commitlint-load-config](https://github.com/conventional-changelog/commitlint/blob/master/%40commitlint/load/src/utils/load-config.ts#L16)
    'package.json',
    `.commitlintrc`,
    `.commitlintrc.json`,
    `.commitlintrc.yaml`,
    `.commitlintrc.yml`,
    `.commitlintrc.js`,
    `.commitlintrc.cjs`,
    `commitlint.config.js`,
    `commitlint.config.cjs`,

    // files supported by TypescriptLoader
    `.commitlintrc.ts`,
    `commitlint.config.ts`,
]
.map(configPath => path.resolve(repository.rootUri.fsPath, configPath)) // resolve to local vscode project's directory

function clearRequireCache() {
    configPaths.forEach(function(key) {
        delete require.cache[key];
    });  
}
clearRequireCache()

      const commitlintRuleConfigs = await commitlint.loadRuleConfigs(
        repository.rootUri.fsPath,
      );
      output.info(
        `commitlintRuleConfigs:\n${JSON.stringify(
          commitlintRuleConfigs,
          null,
          2,
        )}`,
      );

I'd be more than happy to work on this and implement it if it's something you think would be of value, would just need some pointers on where best to put this new logic.

Also thank you for this extension! I love it, use it everyday and it has drastically sped up my workflow so I super appreciate all the hard work you've put into this!