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

How to use parser headerPattern #607

Open
blackswanny opened this issue Apr 2, 2019 · 20 comments
Open

How to use parser headerPattern #607

blackswanny opened this issue Apr 2, 2019 · 20 comments

Comments

@blackswanny
Copy link

blackswanny commented Apr 2, 2019

The task is to use commitlint to prevent commits from being commited. I use husky as well
when I test it and run
echo "bla bla bla" | npx commitlint
It doesn't catch anything and shows no errors found

⧗   input: bla bla bla 
✔   found 0 problems, 0 warnings 

Please, help, why it ignores parserOpts.headerPattern ?
Also some other notice:
I need at least one rule, otherwise commitlint doesn't want to run
Do I need to add headerCorrespondence to make it work or I can have headerPattern only?
Can I customize report message in case if I headerPattern is not matched?

commitlint.config.js

module.exports = {
  rules: {
    'header-min-length': [2, 'always', 20],
  },
  parserPreset: {
    parserOpts: {
      headerPattern: /^(feat|fix|perf|test|BREAKING CHANGE):.*\[REF-(\d{3,}|N\\A)\] \S+ \S+ \S+ \S+ \S+/,
      headerCorrespondence: ['type', 'scope', 'subject']
    }
  }
};

husky in package.json

  "husky": {
    "hooks": {
      "pre-push": "npm test",
      "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
    }
  }

I installed the next

    "@commitlint/cli": "^7.5.2",
    "@commitlint/parse": "^7.5.0",
@escapedcat
Copy link
Member

Hi @blackswanny,

you're right, this is a bit weird.

With your described config I get this output:

echo "bla bla bla" | npx commitlint

⧗   input: bla bla bla
✖   header must not be shorter than 20 characters, current length is 11 [header-min-length]
✖   found 1 problems, 0 warnings
    (Need help? -> https://github.com/conventional-changelog/commitlint#what-is-commitlint )

Using this reduced config...

module.exports = {
  parserPreset: {
    parserOpts: {
      headerPattern: /^(feat|fix|perf|test|BREAKING CHANGE):.*\[REF-(\d{3,}|N\\A)\] \S+ \S+ \S+ \S+ \S+/,
    }
  }
};

...output is:

echo "bla bla bla bla bla bla bla" | npx commitlint

⧗   input: bla bla bla bla bla bla bla
✖   Please add rules to your `commitlint.config.js`
    - Getting started guide: https://git.io/fhHij
    - Example config: https://git.io/fhHip [empty-rules]
✖   found 1 problems, 0 warnings
    (Need help? -> https://github.com/conventional-changelog/commitlint#what-is-commitlint )

When adding this:

  rules: {
    'header-min-length': [2, 'always', 20],
  },

I get:

echo "bla bla bla bla bla bla bla" | npx commitlint

⧗   input: bla bla bla bla bla bla bla
✔   found 0 problems, 0 warnings
    (Need help? -> https://github.com/conventional-changelog/commitlint#what-is-commitlint )

But if the regex is correct I would have expected an error.
I guess we need to look into this. What do you think @byCedric ?

@blackswanny
Copy link
Author

I simplified this to be very simple config. The regex below is obviously correct. However, it does not work still

module.exports = {
  rules: {
    'header-min-length': [2, 'always', 2]
  },
  parserPreset: {
    parserOpts: {
      headerPattern: /^feat/,
      headerCorrespondence: ['type']
    }
  }
};

@maeriens
Copy link

I have been playing with this for a few hours with no avail; wanted to implement a way to at least warn devs that they needed to add the ticket # in the commit message.
Upon finding this tool I was eager to try it, but the parserOpts I give are never used. After fiddling with everything and finding this issue, I installed @commitlint/parser besides @commitlint/cli but nothing changed.
I have a commitlint.config.js similar to the posted above and also tried with the commitlint example (that encourages you to add it to the package.json but it's missing all the double quotes for JSON format?) and still can commit with any random message.

I'm subscribing particularly to this issue to track and try in a future personal project; I love the idea behind this and am sure it will be great, but the general feel the overall package gives to me is a bit broken (rules being required, documentation and installing modules a bit fuzzy, parsers not being used, the constant 'need help?' message, etc.).

@escapedcat
Copy link
Member

Hey @maeriens , checking for # in the reference works here for example: https://github.com/sumcumo/node-modules-check/blob/master/commitlint.config.js

If you have questions regarding this you can find me in the commitlint room here: https://devtoolscommunity.herokuapp.com/

@blackswanny
Copy link
Author

ok, i debugged and I know why we think it doesn't work.

  1. The parser takes headerPattern and runs regex.match for commit message. Match results are put into output json under names provided in headerCorrespondence. So headerCorrespondence is a must have or nothing is saved. For instance ['type', 'reference']
    https://github.com/conventional-changelog/conventional-changelog/blob/master/packages/conventional-commits-parser/lib/parser.js

image

  1. Then tools is looping through only rules and try to ask each rule if it fails against that output. If you have no rule, nothing to be caught.

https://github.com/conventional-changelog/commitlint/blob/master/%40commitlint/lint/src/index.js
image

  1. However, the last thing is that we can check only against existing rules, which all expect exact fields in parser output. For instance rule type-empty expects that parsed.type should be present, which can only happen if we used headerCorrespondence: ['type']. So literally there is no custom check via this parserOpts and it totally sticks to rules of commitlint itself. So I have to use type-empty rule even if I don't have type as my first match in commit message, but something else.

@marionebl
Copy link
Contributor

@blackswanny Thanks for the summary! This is essentially a consequence of our decision to leak the commits-parser configuration as is to commitlint users.

I still think it is right to do so to enable some more complicated use cases but we could def. do a better job on explaining that parserOpts are considered "advanced" usage.

I expect most users to specify plugins they want to use (which might enable certain parserOpts) instead of touching the low level options like these directly. Could you outline what you tried to achieve with your parserOpts commitlint rule combination?

@blackswanny
Copy link
Author

@marionebl i just wanted every commit to match this regEx.

/^(feat|fix|perf|test|BREAKING CHANGE):.*\[REF-(\d{3,}|N\\A)\] \S+ \S+ \S+ \S+ \S+/

Plugins would solve the issue, but they are not yet released, waiting for it

@jasonhodges
Copy link

I have ben following and would like to implement this same functionality on some projects.
I have tested the following regex:
/^(\w*)(?:\(([JIRA]+-[a-zA-Z0-9_.-]+)\))?\: (.*)$/g

Screen Shot 2019-09-10 at 5 23 14 PM

You can see in the image, the groups are correct which also match the pattern I have in my config file.
Screen Shot 2019-09-10 at 5 24 49 PM

and the error I receive

Screen Shot 2019-09-10 at 5 26 56 PM

@nellyk
Copy link

nellyk commented Feb 25, 2020

@jasonhodges did you manage to resolve the issue, i've been looking at achieving something similar

@vbabenko
Copy link

ok, i debugged and I know why we think it doesn't work.

  1. The parser takes headerPattern and runs regex.match for commit message. Match results are put into output json under names provided in headerCorrespondence. So headerCorrespondence is a must have or nothing is saved. For instance ['type', 'reference']
    https://github.com/conventional-changelog/conventional-changelog/blob/master/packages/conventional-commits-parser/lib/parser.js
image
  1. Then tools is looping through only rules and try to ask each rule if it fails against that output. If you have no rule, nothing to be caught.

https://github.com/conventional-changelog/commitlint/blob/master/%40commitlint/lint/src/index.js
image

  1. However, the last thing is that we can check only against existing rules, which all expect exact fields in parser output. For instance rule type-empty expects that parsed.type should be present, which can only happen if we used headerCorrespondence: ['type']. So literally there is no custom check via this parserOpts and it totally sticks to rules of commitlint itself. So I have to use type-empty rule even if I don't have type as my first match in commit message, but something else.

@blackswanny Hey, Did you find a workaround for your case? I have the same issue...

@RobCC
Copy link

RobCC commented Feb 28, 2020

I also tried to use a similar regex as @jasonhodges did, with the same result.

If I extend @commitlint/config-conventional on the commitlint.config.js file, I'll get the same 2 errors:

✖   subject may not be empty [subject-empty]
✖   type may not be empty [type-empty]

However, if I remove that extend, the headerPattern is simply ignored, and lets any message go through.

This is the regex I tried: https://regex101.com/r/SF1P42/1

@vbabenko
Copy link

@marionebl Hi Mario,
Thank you for this awasome tool. Is any news/plans for this issue?

@ArmsZhou
Copy link

i tried to set none of any keys and values in the rules when i use local custom parser in the commitlint.config.js file,the headerPattern can be matched.

const types = [
  'build',    // 构建执行
  'ci',       // CI 相关
  'chore',    // 构建工具相关
  'docs',     // 文档更新
  'feat',     // 新功能
  'fix',      // bug 修复
  'pref',     // 性能优化
  'refactor', // 功能重构
  'revert',   // 回滚操作
  'style',    // 样式变动
  'test'      // 单元测试
];

typeEnum = {
  rules: {
    'type-enum': [2, 'always', types]
  },
  value: () => types
}

// Level,0-2:0表示禁用这条规则、1表示警告、2表示错误。
// Applicable,always|never:always表示使用规则,never表示不使用规则。
// Value:用于这条规则的值。
// https://commitlint.js.org/#/reference-rules
 
module.exports = {
    extends: [
      "@commitlint/config-conventional",
      "@commitlint/parse"
    ],
    rules: {
      // 'body-leading-blank': [1, 'always'],
      // 'footer-leading-blank': [1, 'always'],
      // 'header-max-length': [2, 'always', 72],
      // 'header-min-length': [2, 'always', 20],
      // 'scope-empty': [0, 'never'],
      // 'scope-case': [0],
      // 'subject-full-stop': [0, 'never'],
      // 'subject-case': [0, 'never'],
      // 'type-case': [0, 'always', 'lower-case'],
      // 'type-empty': [0, 'never'],
      // 'type-enum': typeEnum.rules['type-enum']
    },
    parserPreset: {
      parserOpts: {
        headerPattern: /^(build|ci|chore|docs|feat|fix|pref|refactor|revert|style|test)(\(\d+\.\d+\.\d+\)): (\S{20,})$/,
        headerCorrespondence: ['type', 'scope', 'subject']
      }
    }
  };
  • subject less than 20 letter, error, because i set the subject as (\S{20,})
echo "fix(1.12.1): dajkdajjkk" | npx commitlint
⧗   input: fix(1.12.1): dajkdajjkk
✖   subject may not be empty [subject-empty]
✖   type may not be empty [type-empty]

✖   found 2 problems, 0 warnings
ⓘ   Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint

then i changed the (\S{20,}) to (\S{5,}), there is no error any more.

so, don't use any rules when use local parser!!!

@PLQin
Copy link

PLQin commented Nov 17, 2020

Okay, I'm having this problem, and I want to ask, Who requires that 'commitlint.config.js' must exist?


Why is it necessary to add this rule, even though the intention is good,
It's like forcing me to drink water. It's disgusting .

@FelixSauer
Copy link

I have the same problem and wanted to ask if there is a solution in the meantime?

@xianshenglu
Copy link

Here is my demo commit to customize commit lint rules with help from here

@mistricky
Copy link

There is missing the document about parserPreset and parserOpts. :(

@samayer12
Copy link

This guide, by strdr4605 is a great starting point for how to write a custom parser. Cross-references in #3336 as something to reference while documenting parserOpts and headerPattern.

@baby-gnu
Copy link

I'm still looking for a solution to only configure headerPattern without breaking everything.

@pasik89
Copy link

pasik89 commented Dec 29, 2023

  "parserPreset": {
    "parserOpts": {
      "headerPattern": "^(.[[A-Z]{1,7}-\\d{1,7}.]) \\s*(build|ci|docs|feat|fix|perf|refactor|test)(?:\\(\\S*(animations|bazel|benchpress|common|compiler|compiler-cli|core|elements|forms|http|language-service|localize|platform-browser|platform-browser-dynamic|platform-server|router|service-worker|upgrade|zone.js|packaging|changelog|docs-infra|migrations|devtools)\\))?\\S* (.+)$",
      "headerCorrespondence": ["ticketReference", "type", "scope", "subject"]
    }
  }

Here is working Regex for angular commit pattern with optional scope group. The problem with yours regex is that you have non-grouping groups and headerCorrespondence can't recognize subject.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests