Refactor commit_messages#lint_commit
This introduces additional method for linting, to reduce the complexity of `lint_commits`.
This commit is contained in:
parent
9d842c704a
commit
d8145aa693
|
|
@ -64,11 +64,12 @@ def too_many_changed_lines?(commit)
|
||||||
lines_changed_in_commit(commit) >= 30
|
lines_changed_in_commit(commit) >= 30
|
||||||
end
|
end
|
||||||
|
|
||||||
def lint_commits(commits)
|
def emoji_checker
|
||||||
failures = false
|
@emoji_checker ||= EmojiChecker.new
|
||||||
emoji_checker = EmojiChecker.new
|
end
|
||||||
|
|
||||||
unicode_emoji_regex = %r((
|
def unicode_emoji_regex
|
||||||
|
@unicode_emoji_regex ||= %r((
|
||||||
[\u{1F300}-\u{1F5FF}] |
|
[\u{1F300}-\u{1F5FF}] |
|
||||||
[\u{1F1E6}-\u{1F1FF}] |
|
[\u{1F1E6}-\u{1F1FF}] |
|
||||||
[\u{2700}-\u{27BF}] |
|
[\u{2700}-\u{27BF}] |
|
||||||
|
|
@ -77,123 +78,132 @@ def lint_commits(commits)
|
||||||
[\u{1F680}-\u{1F6FF}] |
|
[\u{1F680}-\u{1F6FF}] |
|
||||||
[\u{2600}-\u{26FF}]
|
[\u{2600}-\u{26FF}]
|
||||||
))x
|
))x
|
||||||
|
end
|
||||||
|
|
||||||
commits.each do |commit|
|
def lint_commit(commit)
|
||||||
# For now we'll ignore merge commits, as getting rid of those is a problem
|
# For now we'll ignore merge commits, as getting rid of those is a problem
|
||||||
# separate from enforcing good commit messages.
|
# separate from enforcing good commit messages.
|
||||||
next if commit.message.start_with?('Merge branch')
|
return false if commit.message.start_with?('Merge branch')
|
||||||
|
|
||||||
# We ignore revert commits as they are well structured by Git already
|
# We ignore revert commits as they are well structured by Git already
|
||||||
next if commit.message.start_with?('Revert "')
|
return false if commit.message.start_with?('Revert "')
|
||||||
|
|
||||||
subject, separator, details = commit.message.split("\n", 3)
|
failures = false
|
||||||
|
subject, separator, details = commit.message.split("\n", 3)
|
||||||
|
|
||||||
if subject.split.length < 3
|
if subject.split.length < 3
|
||||||
fail_commit(
|
fail_commit(
|
||||||
commit,
|
commit,
|
||||||
'The commit subject must contain at least three words'
|
'The commit subject must contain at least three words'
|
||||||
)
|
)
|
||||||
|
|
||||||
failures = true
|
failures = true
|
||||||
end
|
|
||||||
|
|
||||||
if subject.length > 72
|
|
||||||
fail_commit(
|
|
||||||
commit,
|
|
||||||
'The commit subject may not be longer than 72 characters'
|
|
||||||
)
|
|
||||||
|
|
||||||
failures = true
|
|
||||||
elsif subject.length > 50
|
|
||||||
warn_commit(
|
|
||||||
commit,
|
|
||||||
"This commit's subject line is acceptable, but please try to [reduce it to 50 characters](#{URL_LIMIT_SUBJECT})."
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
unless subject_starts_with_capital?(subject)
|
|
||||||
fail_commit(commit, 'The commit subject must start with a capital letter')
|
|
||||||
failures = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if subject.end_with?('.')
|
|
||||||
fail_commit(commit, 'The commit subject must not end with a period')
|
|
||||||
failures = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if separator && !separator.empty?
|
|
||||||
fail_commit(
|
|
||||||
commit,
|
|
||||||
'The commit subject and body must be separated by a blank line'
|
|
||||||
)
|
|
||||||
|
|
||||||
failures = true
|
|
||||||
end
|
|
||||||
|
|
||||||
details&.each_line do |line|
|
|
||||||
line = line.strip
|
|
||||||
|
|
||||||
next if line.length <= 72
|
|
||||||
|
|
||||||
url_size = line.scan(%r((https?://\S+))).sum { |(url)| url.length }
|
|
||||||
|
|
||||||
# If the line includes a URL, we'll allow it to exceed 72 characters, but
|
|
||||||
# only if the line _without_ the URL does not exceed this limit.
|
|
||||||
next if line.length - url_size <= 72
|
|
||||||
|
|
||||||
fail_commit(
|
|
||||||
commit,
|
|
||||||
'The commit body should not contain more than 72 characters per line'
|
|
||||||
)
|
|
||||||
|
|
||||||
failures = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if !details && too_many_changed_lines?(commit)
|
|
||||||
fail_commit(
|
|
||||||
commit,
|
|
||||||
'Commits that change 30 or more lines across at least three files ' \
|
|
||||||
'must describe these changes in the commit body'
|
|
||||||
)
|
|
||||||
|
|
||||||
failures = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if emoji_checker.includes_emoji?(commit.message)
|
|
||||||
fail_commit(
|
|
||||||
commit,
|
|
||||||
'Avoid the use of Markdown Emoji such as `:+1:`. ' \
|
|
||||||
'These add no value to the commit message, ' \
|
|
||||||
'and are displayed as plain text outside of GitLab'
|
|
||||||
)
|
|
||||||
|
|
||||||
failures = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if commit.message.match?(unicode_emoji_regex)
|
|
||||||
fail_commit(
|
|
||||||
commit,
|
|
||||||
'Avoid the use of Unicode Emoji. ' \
|
|
||||||
'These add no value to the commit message, ' \
|
|
||||||
'and may not be displayed properly everywhere'
|
|
||||||
)
|
|
||||||
|
|
||||||
failures = true
|
|
||||||
end
|
|
||||||
|
|
||||||
if commit.message.match?(%r(([\w\-\/]+)?(#|!|&|%)\d+\b))
|
|
||||||
fail_commit(
|
|
||||||
commit,
|
|
||||||
'Use full URLs instead of short references ' \
|
|
||||||
'(`gitlab-org/gitlab-ce#123` or `!123`), as short references are ' \
|
|
||||||
'displayed as plain text outside of GitLab'
|
|
||||||
)
|
|
||||||
|
|
||||||
failures = true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if failures
|
if subject.length > 72
|
||||||
|
fail_commit(
|
||||||
|
commit,
|
||||||
|
'The commit subject may not be longer than 72 characters'
|
||||||
|
)
|
||||||
|
|
||||||
|
failures = true
|
||||||
|
elsif subject.length > 50
|
||||||
|
warn_commit(
|
||||||
|
commit,
|
||||||
|
"This commit's subject line is acceptable, but please try to [reduce it to 50 characters](#{URL_LIMIT_SUBJECT})."
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
unless subject_starts_with_capital?(subject)
|
||||||
|
fail_commit(commit, 'The commit subject must start with a capital letter')
|
||||||
|
failures = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if subject.end_with?('.')
|
||||||
|
fail_commit(commit, 'The commit subject must not end with a period')
|
||||||
|
failures = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if separator && !separator.empty?
|
||||||
|
fail_commit(
|
||||||
|
commit,
|
||||||
|
'The commit subject and body must be separated by a blank line'
|
||||||
|
)
|
||||||
|
|
||||||
|
failures = true
|
||||||
|
end
|
||||||
|
|
||||||
|
details&.each_line do |line|
|
||||||
|
line = line.strip
|
||||||
|
|
||||||
|
next if line.length <= 72
|
||||||
|
|
||||||
|
url_size = line.scan(%r((https?://\S+))).sum { |(url)| url.length }
|
||||||
|
|
||||||
|
# If the line includes a URL, we'll allow it to exceed 72 characters, but
|
||||||
|
# only if the line _without_ the URL does not exceed this limit.
|
||||||
|
next if line.length - url_size <= 72
|
||||||
|
|
||||||
|
fail_commit(
|
||||||
|
commit,
|
||||||
|
'The commit body should not contain more than 72 characters per line'
|
||||||
|
)
|
||||||
|
|
||||||
|
failures = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if !details && too_many_changed_lines?(commit)
|
||||||
|
fail_commit(
|
||||||
|
commit,
|
||||||
|
'Commits that change 30 or more lines across at least three files ' \
|
||||||
|
'must describe these changes in the commit body'
|
||||||
|
)
|
||||||
|
|
||||||
|
failures = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if emoji_checker.includes_emoji?(commit.message)
|
||||||
|
fail_commit(
|
||||||
|
commit,
|
||||||
|
'Avoid the use of Markdown Emoji such as `:+1:`. ' \
|
||||||
|
'These add no value to the commit message, ' \
|
||||||
|
'and are displayed as plain text outside of GitLab'
|
||||||
|
)
|
||||||
|
|
||||||
|
failures = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if commit.message.match?(unicode_emoji_regex)
|
||||||
|
fail_commit(
|
||||||
|
commit,
|
||||||
|
'Avoid the use of Unicode Emoji. ' \
|
||||||
|
'These add no value to the commit message, ' \
|
||||||
|
'and may not be displayed properly everywhere'
|
||||||
|
)
|
||||||
|
|
||||||
|
failures = true
|
||||||
|
end
|
||||||
|
|
||||||
|
if commit.message.match?(%r(([\w\-\/]+)?(#|!|&|%)\d+\b))
|
||||||
|
fail_commit(
|
||||||
|
commit,
|
||||||
|
'Use full URLs instead of short references ' \
|
||||||
|
'(`gitlab-org/gitlab-ce#123` or `!123`), as short references are ' \
|
||||||
|
'displayed as plain text outside of GitLab'
|
||||||
|
)
|
||||||
|
|
||||||
|
failures = true
|
||||||
|
end
|
||||||
|
|
||||||
|
failures
|
||||||
|
end
|
||||||
|
|
||||||
|
def lint_commits(commits)
|
||||||
|
failed = commits.reject do |commit|
|
||||||
|
lint_commit(commit)
|
||||||
|
end
|
||||||
|
|
||||||
|
if failed.any?
|
||||||
markdown(<<~MARKDOWN)
|
markdown(<<~MARKDOWN)
|
||||||
## Commit message standards
|
## Commit message standards
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue