debian-mirror-gitlab/danger/commit_messages/Dangerfile

163 lines
5 KiB
Ruby
Raw Normal View History

2018-12-05 23:21:45 +05:30
# frozen_string_literal: true
2020-03-13 15:44:24 +05:30
require_relative File.expand_path('../../lib/gitlab/danger/commit_linter', __dir__)
2018-12-05 23:21:45 +05:30
2019-03-02 22:35:43 +05:30
URL_GIT_COMMIT = "https://chris.beams.io/posts/git-commit/"
2020-03-13 15:44:24 +05:30
MAX_COMMITS_COUNT = 10
2018-12-05 23:21:45 +05:30
2019-12-04 20:38:33 +05:30
def gitlab_danger
@gitlab_danger ||= GitlabDanger.new(helper.gitlab_helper)
end
2018-12-05 23:21:45 +05:30
def fail_commit(commit, message)
2020-03-13 15:44:24 +05:30
self.fail("#{commit.sha}: #{message}")
2018-12-05 23:21:45 +05:30
end
def warn_commit(commit, message)
2020-03-13 15:44:24 +05:30
self.warn("#{commit.sha}: #{message}")
2018-12-05 23:21:45 +05:30
end
2020-03-13 15:44:24 +05:30
def squash_mr?
gitlab_danger.ci? ? gitlab.mr_json['squash'] : false
2018-12-05 23:21:45 +05:30
end
2020-03-13 15:44:24 +05:30
def wip_mr?
gitlab_danger.ci? ? gitlab.mr_json['work_in_progress'] : false
2018-12-05 23:21:45 +05:30
end
2020-03-13 15:44:24 +05:30
# Perform various checks against commits. We're not using
# https://github.com/jonallured/danger-commit_lint because its output is not
# very helpful, and it doesn't offer the means of ignoring merge commits.
def lint_commit(commit)
linter = Gitlab::Danger::CommitLinter.new(commit)
2019-12-26 22:10:19 +05:30
2019-07-07 11:18:12 +05:30
# For now we'll ignore merge commits, as getting rid of those is a problem
# separate from enforcing good commit messages.
2020-03-13 15:44:24 +05:30
return linter if linter.merge?
2019-07-07 11:18:12 +05:30
# We ignore revert commits as they are well structured by Git already
2020-03-13 15:44:24 +05:30
return linter if linter.revert?
2019-07-07 11:18:12 +05:30
2020-03-13 15:44:24 +05:30
# If MR is set to squash, we ignore fixup commits
return linter if linter.fixup? && squash_mr?
2019-12-04 20:38:33 +05:30
2020-03-13 15:44:24 +05:30
if linter.fixup?
msg = 'Squash or fixup commits must be squashed before merge, or enable squash merge option'
if wip_mr? || squash_mr?
warn_commit(commit, msg)
2019-12-04 20:38:33 +05:30
else
2020-03-13 15:44:24 +05:30
fail_commit(commit, msg)
2019-12-04 20:38:33 +05:30
end
# Makes no sense to process other rules for fixup commits, they trigger just more noise
2020-03-13 15:44:24 +05:30
return linter
2019-12-04 20:38:33 +05:30
end
2019-09-30 21:07:59 +05:30
# Fail if a suggestion commit is used and squash is not enabled
2020-03-13 15:44:24 +05:30
if linter.suggestion?
unless squash_mr?
fail_commit(commit, "If you are applying suggestions, enable squash in the merge request and re-run the `danger-review` job")
2019-09-30 21:07:59 +05:30
end
2020-03-13 15:44:24 +05:30
return linter
2019-07-07 11:18:12 +05:30
end
2020-03-13 15:44:24 +05:30
linter.lint
end
2019-07-07 11:18:12 +05:30
2020-03-13 15:44:24 +05:30
def lint_mr_title(mr_title)
commit = Struct.new(:message, :sha).new(mr_title)
2019-07-07 11:18:12 +05:30
2020-03-13 15:44:24 +05:30
Gitlab::Danger::CommitLinter.new(commit).lint_subject("merge request title")
end
2019-07-07 11:18:12 +05:30
2020-03-13 15:44:24 +05:30
def count_non_fixup_commits(commit_linters)
commit_linters.count { |commit_linter| !commit_linter.fixup? }
end
2019-07-07 11:18:12 +05:30
2020-03-13 15:44:24 +05:30
def lint_commits(commits)
commit_linters = commits.map { |commit| lint_commit(commit) }
failed_commit_linters = commit_linters.select { |commit_linter| commit_linter.failed? }
warn_or_fail_commits(failed_commit_linters, default_to_fail: !squash_mr?)
2019-07-07 11:18:12 +05:30
2020-03-13 15:44:24 +05:30
if count_non_fixup_commits(commit_linters) > MAX_COMMITS_COUNT
level = squash_mr? ? :warn : :fail
self.__send__(level, # rubocop:disable GitlabSecurity/PublicSend
"This merge request includes more than #{MAX_COMMITS_COUNT} commits. " \
'Please rebase these commits into a smaller number of commits or split ' \
'this merge request into multiple smaller merge requests.')
2019-07-07 11:18:12 +05:30
end
2020-03-13 15:44:24 +05:30
if squash_mr?
multi_line_commit_linter = commit_linters.detect { |commit_linter| !commit_linter.merge? && commit_linter.multi_line? }
2019-07-07 11:18:12 +05:30
2020-03-13 15:44:24 +05:30
if multi_line_commit_linter && multi_line_commit_linter.failed?
warn_or_fail_commits(multi_line_commit_linter)
fail_message('The commit message that will be used in the squash commit does not meet our Git commit message standards.')
else
title_linter = lint_mr_title(gitlab.mr_json['title'])
if title_linter.failed?
warn_or_fail_commits(title_linter)
fail_message('The merge request title that will be used in the squash commit does not meet our Git commit message standards.')
end
end
else
if failed_commit_linters.any?
fail_message('One or more commit messages do not meet our Git commit message standards.')
end
2019-07-07 11:18:12 +05:30
end
2020-03-13 15:44:24 +05:30
end
2019-07-07 11:18:12 +05:30
2020-03-13 15:44:24 +05:30
def warn_or_fail_commits(failed_linters, default_to_fail: true)
level = default_to_fail ? :fail : :warn
Array(failed_linters).each do |linter|
linter.problems.each do |problem_key, problem_desc|
case problem_key
when :subject_above_warning
warn_commit(linter.commit, problem_desc)
else
self.__send__("#{level}_commit", linter.commit, problem_desc) # rubocop:disable GitlabSecurity/PublicSend
end
end
2019-07-07 11:18:12 +05:30
end
end
2020-03-13 15:44:24 +05:30
def fail_message(intro)
markdown(<<~MARKDOWN)
## Commit message standards
2018-12-05 23:21:45 +05:30
2020-03-13 15:44:24 +05:30
#{intro}
2018-12-05 23:21:45 +05:30
2020-03-13 15:44:24 +05:30
For more information on how to write a good commit message, take a look at
[How to Write a Git Commit Message](#{URL_GIT_COMMIT}).
2018-12-05 23:21:45 +05:30
2020-03-13 15:44:24 +05:30
Here is an example of a good commit message:
2018-12-05 23:21:45 +05:30
2020-03-13 15:44:24 +05:30
Reject ruby interpolation in externalized strings
2018-12-05 23:21:45 +05:30
2020-03-13 15:44:24 +05:30
When using ruby interpolation in externalized strings, they can't be
detected. Which means they will never be presented to be translated.
2018-12-05 23:21:45 +05:30
2020-03-13 15:44:24 +05:30
To mix variables into translations we need to use `sprintf`
instead.
2018-12-05 23:21:45 +05:30
2020-03-13 15:44:24 +05:30
Instead of:
2018-12-05 23:21:45 +05:30
2020-03-13 15:44:24 +05:30
_("Hello \#{subject}")
2018-12-05 23:21:45 +05:30
2020-03-13 15:44:24 +05:30
Use:
2018-12-05 23:21:45 +05:30
2020-03-13 15:44:24 +05:30
_("Hello %{subject}") % { subject: 'world' }
2018-12-05 23:21:45 +05:30
2020-03-13 15:44:24 +05:30
This is an example of a bad commit message:
2018-12-05 23:21:45 +05:30
2020-03-13 15:44:24 +05:30
updated README.md
2018-12-05 23:21:45 +05:30
2020-03-13 15:44:24 +05:30
This commit message is bad because although it tells us that README.md is
updated, it doesn't tell us why or how it was updated.
MARKDOWN
2018-12-05 23:21:45 +05:30
end
2020-03-13 15:44:24 +05:30
lint_commits(git.commits)