@mridang/commitlint-plugin-conditionals v1.1.1
Commitlint - Conditional Rules Plugin
A commitlint plugin to enable conditional application of linting rules based on various commit attributes, such as author patterns or message content.
This plugin helps ensure that commit message conventions can be flexibly enforced. For instance, it allows for different linting standards for human-authored commits versus automated commits (e.g., from bots), or for varying rules based on the type of changes being committed. It is designed to be extended with more conditional capabilities over time.
Why?
Maintaining consistent and meaningful commit messages is crucial for project health, enabling better collaboration, clearer history, and automated changelog generation. Commitlint is an excellent tool for enforcing these conventions.
However, a one-size-fits-all linting approach isn't always optimal. Different types of commits or contributions might warrant different levels of scrutiny or slightly varied rules:
- Automated Commits: Commits generated by bots (e.g., Dependabot, Renovate, CI scripts) often have a standardized, machine-generated format. Applying the same strict linting rules designed for human contributors can be overly restrictive or lead to unnecessary failures for these automated processes. It's often desirable to either bypass linting for these bots or apply a more lenient set of rules.
- Work-in-Progress or Specific Branch Types: Teams might want to enforce
strict rules on main development lines (
main,develop) but allow more flexibility on feature branches or for commits marked as "WIP" (Work In Progress). - Evolving Standards: As a project evolves, you might want to introduce new linting rules but apply them conditionally at first, or only to certain types of commits, before making them universal.
This plugin, @mridang/commitlint-plugin-conditionals, aims to provide the
flexibility to handle such scenarios. It allows you to define conditions
(initially based on author patterns) under which commit linting rules are
applied differently, or even skipped entirely. This helps maintain high
standards for human contributions where needed, while accommodating the
practicalities of automated systems and diverse development workflows,
ultimately leading to a more effective and less burdensome commit linting
process.
Installation
Install using NPM by using the following command:
npm install --save @mridang/commitlint-plugin-conditionalsUsage
To use this plugin, add @mridang/commitlint-plugin-conditionals to your commitlint
configuration file (e.g., commitlint.config.js or .commitlintrc.js).
You'll need to list it in the plugins array. The rules provided by this
plugin will then be available to be configured in the rules object, prefixed
with the plugin's name.
First, add the plugin to the plugins array in your commitlint configuration:
/**
* @type {import('@commitlint/types').UserConfig}
*/
const config = {
extends: [
'@commitlint/config-conventional', // Or your preferred base configuration
],
plugins: [
'@mridang/conditionals', // Add the plugin by its package name
],
rules: {
// Rule configuration will go here
},
};
module.exports = config;Configuring the ignoreForAuthors Rule
This rule is the core of the plugin.
Rule Name: @mridang/commitlint-plugin-conditionals/ignore-for-authors
Options (IgnoreForAuthorsRuleOptions):
The rule accepts an object with the following properties:
ignoreAuthorPatterns?: string[]:- An array of string patterns (e.g.,
['dependabot[bot]', 'renovate-bot']). - If a pattern matches content in the raw commit message, the rules
defined in
rulesToEnforceare bypassed for that commit.
- An array of string patterns (e.g.,
rulesToEnforce?: ExternalRuleToEnforce[]:- An array of rule configurations to apply if the commit is not from an ignored author.
- Each entry is an object:
packageName: string: NPM package name (e.g.,'@commitlint/rules').ruleName: string: Rule name within that package (e.g.,'type-enum').value: unknown: Configuration value for that rule.
Behavior:
- If
ignoreAuthorPatternsmatch, this rule passes, and its configuredrulesToEnforceare skipped. - If no
ignoreAuthorPatternsmatch, each rule inrulesToEnforceis dynamically loaded and executed. If any fail, this rule fails. - This rule is asynchronous.
Important: This rule only controls the execution of rules listed in its
rulesToEnforce option. Other rules from extends or elsewhere in your
main rules object will still apply to all commits unless explicitly
disabled or managed by a global dynamic configuration.
Example: Conditional Rules for Specific Authors
This example shows how to use ignoreForAuthors to apply different body-max-line-length
and type-enum settings for dependabot[bot] versus other users, while
still inheriting other rules from @commitlint/config-conventional.
import { RuleConfigSeverity } from '@commitlint/types';
import mridangConditionalsPlugin from '@mridang/commitlint-plugin-conditionals'; // eslint-disable-line
/**
* @type {import('@commitlint/types').UserConfig}
*/
export default {
extends: ['@commitlint/config-conventional'],
plugins: [mridangConditionalsPlugin],
rules: {
/**
* Disable the 'body-max-line-length' rule from '@commitlint/config-conventional'
* because we want our plugin to control it conditionally.
* Using RuleConfigSeverity.Disabled (which is 0).
*/
'body-max-line-length': [RuleConfigSeverity.Disabled, 'always'],
/**
* Configure the rule from your plugin.
* The rule name is prefixed with your actual package name.
* Options type (for JSDoc reference if needed):
* import('@mridang/commitlint-conditionals').IgnoreForAuthorsRuleOptions
*/
'@mridang/commitlint-conditionals/ignoreForAuthors': [
RuleConfigSeverity.Error, // Severity: Error (2) for this conditional rule itself
'always', // Condition
{
/**
* Use 'signOffPatternsToIgnore' to specify patterns within
* 'Signed-off-by:' lines.
*/
signOffPatternsToIgnore: [
'dependabot[bot]',
// Add other patterns like 'bot@example.com'
],
rulesToEnforce: [
// For commits not matching signOffPatternsToIgnore, enforce this:
{
packageName: '@commitlint/rules',
ruleName: 'body-max-line-length',
value: 100, // Standard limit for humans
},
// Example: Enforcing type-enum for non-bots
// {
// packageName: '@commitlint/rules',
// ruleName: 'type-enum',
// value: [
// 'build', 'chore', 'ci', 'docs', 'feat', 'fix', 'perf',
// 'refactor', 'revert', 'style', 'test',
// ],
// },
],
},
],
/**
* Note:
* - Other rules from '@commitlint/config-conventional' (e.g., 'type-enum'
* if not handled by the plugin above and its original disabled)
* that were NOT disabled will now apply to ALL commits.
* - This example makes 'body-max-line-length' conditional.
*/
},
};Known Issues
- External Rule Dependencies (
rulesToEnforce): When configuringrulesToEnforce, ensure each specifiedpackageNameis installed in your project and exports its rule functions in a standardcommitlintplugin format. The plugin will dynamically load these external rules. - Author Identification (
signOffPatternsToIgnore): This feature identifies authors by searching for your specified patterns withinSigned-off-by:lines in the raw commit message text. It does not directly use Git's discrete author fields (e.g.,GIT_AUTHOR_NAME). - Plugin's Scope of Control: This plugin conditionally applies only those rules explicitly listed in its
rulesToEnforceoption. It does not automatically bypass other rules inherited viaextendsor defined elsewhere in your maincommitlintconfiguration. For a global bypass of all rules for certain authors, a dynamic JavaScript/TypeScript configuration file (commitlint.config.jsor.ts) is necessary, as detailed in the "Usage" section.
Useful links
- Commitlint: The linting tool for commit
messages that
@mridang/commitlint-plugin-conditionalsintegrates with. - Conventional Commits: The commit
convention that
commitlintoften enforces.
Contributing
If you have suggestions for how this app could be improved, or want to report a bug, open an issue - we'd love all and any contributions.
License
Apache License 2.0 © 2024 Mridang Agarwalla