Commitlint: How to handle long URLs in commit messages

Created on 9 Sep 2020  Â·  3Comments  Â·  Source: conventional-changelog/commitlint

Expected Behavior

I want to be able to add links with long URLs (over 100 characters) to the footer so that I'll be able to adjust the footer line length in my own rules, while still assuring that the commit message body will be formatted consistently.

Alternatively there should be another way to add long urls to commits without having to minify them, while still adhering to the commit message max-line-length rules.

Current Behavior

It is impossible to create a commit containing a long url (over 100 characters), with the default config without minifying it.
I would prefer not to minify the URL as depending on the minification service the minified URL might not be online as long and I could potentially lose context information from the actual URL, which I can only find out by following the minfied one.

Putting a long URL in the body on a single line only works by adjusting the body-max-line-length rule, reducing the usefulness of the configuration.

Example

docs(adl): commit message style convention

asserted by commitlint to [angular commit style] 
https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional#type-enum
according to the conventional commits convention.

Putting the URL as a markdown link in the footer does not work while adjusting footer-max-line-length to Infinity as it is recognized not as the footer, but as part of the body.

Example

docs(adl): commit message style convention

asserted by commitlint to [angular commit style] according to the
conventional commits convention.

[angular commit style]: https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional#type-enum

results in

husky > pre-commit (node v12.18.2)
✔ Preparing...
✔ Running tasks...
✔ Applying modifications...
✔ Cleaning up...
husky > commit-msg (node v12.18.2)
â§—   input: docs(adl): commit message style convention

asserted by commitlint to [angular commit style] according to the
conventional-commits convention

[angular-commit-style]: https://github.com/conventional-changelog/commitlint/tree/master/@commitlint/config-conventional
✖   body's lines must not be longer than 100 characters [body-max-line-length]

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

husky > commit-msg hook failed (add --no-verify to bypass)

This seems to be due to the conventional-commit-parser package only recognizing the footer by usage of either "BREAKING CHANGE:" or supplying some issue number link "#333".
I found this out by saving the above commit message to a test.txt file and running the parser over it resulting in:

[
  {
    "type":"docs",
    "scope":"adl",
    "subject":"commit message style convention",
    "merge":null,
    "header":"docs(adl): commit message style convention",
    "body":"asserted by commitlint to [angular commit style] according to the\n[conventional commits] convention.\n\n[angular commit style]: https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional#type-enum",
    "footer":null,
    "notes":[],
    "references":[],
    "mentions":[],
    "revert":null
  }
]

Affected packages

  • [x] parse
  • [x] config-angular

Possible Solution

A solution could be to supply the conventional-commits-parser with a regex for specific noteKeywords.
Another solution could be to introduce an option to somehow ignore single line urls in the body of commit messages from the testing of body-max-line-length rule.

But my question would also be how others normally add URLs to commit messges. Do you just always minify them?

question

Most helpful comment

Here is my 2c for what it's worth.

Forgive me because I am not sure if [angular commit style] is a static string or if that is contextual based on the current commit. If it's static and you are always going to use that then you could easily just pass in the former as a parser option.

module.exports = {
    extends: ['@commitlint/config-conventional'], // My repo is using config-conventional you could use anything...
    rules: {
        'footer-max-line-length': [0, 'always'] // Make sure there is never a max-line-length by disabling the rule
    },
    parserPreset: {
        parserOpts: {
            noteKeywords: ['[angular commit style]'] // Create a custom keyword to distinguish the footer
        }
    }
};

In which case the following parses correctly:

docs(adl): commit message style convention

asserted by commitlint to [angular commit style] according to the conventional commits convention.

[angular commit style]: https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional#type-enum

If [angular commit style] changes then you might need to create a keyword such that you can recognise the start of a footer. Such as link, or links:

module.exports = {
    extends: ['@commitlint/config-conventional'], // My repo is using config-conventional you could use anything...
    rules: {
        'footer-max-line-length': [0, 'always'] // Make sure there is never a max-line-length by disabling the rule
    },
    parserPreset: {
        parserOpts: {
            noteKeywords: ['link:'] // Create a custom keyword to distinguish the footer
        }
    }
};

Then you could just append the word link to your footer whenever you need to list a footer.

Then when you need a link you can simpy do the following:

docs(adl): commit message style convention

asserted by commitlint to [angular commit style] according to the conventional commits convention.

link: [angular commit style]: https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional#type-enum

I would note though in both scenarios I have had to disable the footer line length because that line (without the link keyword appended) is longer than 100 characters anyway. So if you're going to disable line length somewhere I think it's a trade off between how much you want to control the body length vs how much you force a particular commit style for footers.

All 3 comments

Hey @texhnolyze ,

hm, interesting usage. So far I never experienced this. Maybe because we rarely add URLs to commits. Or they haven't been over 100 chars. I agreed minifying URLs is kinda bad because as someone who reads the message I would like to see the real URL.

Personally I would just increase body-max-line-length I guess.
I don't see the need to solve this in the main codebase for now. You could try a plugin maybe. Or maybe other will see this issue and jump in. You could also ask in our slack chat how other might handle this or get some feedback.

Here is my 2c for what it's worth.

Forgive me because I am not sure if [angular commit style] is a static string or if that is contextual based on the current commit. If it's static and you are always going to use that then you could easily just pass in the former as a parser option.

module.exports = {
    extends: ['@commitlint/config-conventional'], // My repo is using config-conventional you could use anything...
    rules: {
        'footer-max-line-length': [0, 'always'] // Make sure there is never a max-line-length by disabling the rule
    },
    parserPreset: {
        parserOpts: {
            noteKeywords: ['[angular commit style]'] // Create a custom keyword to distinguish the footer
        }
    }
};

In which case the following parses correctly:

docs(adl): commit message style convention

asserted by commitlint to [angular commit style] according to the conventional commits convention.

[angular commit style]: https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional#type-enum

If [angular commit style] changes then you might need to create a keyword such that you can recognise the start of a footer. Such as link, or links:

module.exports = {
    extends: ['@commitlint/config-conventional'], // My repo is using config-conventional you could use anything...
    rules: {
        'footer-max-line-length': [0, 'always'] // Make sure there is never a max-line-length by disabling the rule
    },
    parserPreset: {
        parserOpts: {
            noteKeywords: ['link:'] // Create a custom keyword to distinguish the footer
        }
    }
};

Then you could just append the word link to your footer whenever you need to list a footer.

Then when you need a link you can simpy do the following:

docs(adl): commit message style convention

asserted by commitlint to [angular commit style] according to the conventional commits convention.

link: [angular commit style]: https://github.com/conventional-changelog/commitlint/tree/master/%40commitlint/config-conventional#type-enum

I would note though in both scenarios I have had to disable the footer line length because that line (without the link keyword appended) is longer than 100 characters anyway. So if you're going to disable line length somewhere I think it's a trade off between how much you want to control the body length vs how much you force a particular commit style for footers.

@iamscottcab Nice that actually helped a lot. I did not realize, that you are able to add parserOpts in your configuration.
Yeah [angular commit message] was just an example, which changes depending on the link text I want to use.

Thanks to your examples and looking at the actual implementation of the noteKeywords parser options I constructed this:

module.exports = {
  extends: ['@commitlint/config-conventional'],
  rules: { 'footer-max-line-length': [1, 'always', 100] },
  parserPreset: { parserOpts: { noteKeywords: ['\\[.+\\]:'] } },
}

This is somewhat a workaround due to me realizing, that the parser actually constructs a regex with the list of noteKeywords I pass it. It enables me however to add any link in the format [any text]: to the footer, which is a pattern I do not expect anywhere within the body of a normal commit message.
I also opted to still get a warning for longer than 100 character footers so people will have a second look, when it is not necessary.

I'll close this as my issue is solved. Thanks guys!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

juliuscc picture juliuscc  Â·  3Comments

kirillgroshkov picture kirillgroshkov  Â·  3Comments

MathiasKandelborg picture MathiasKandelborg  Â·  3Comments

QuentinRoy picture QuentinRoy  Â·  5Comments

gajus picture gajus  Â·  4Comments