Class: Danger::Changelog
- Inherits:
-
Plugin
- Object
- Plugin
- Danger::Changelog
show all
- Defined in:
- lib/danger/plugins/changelog.rb
Overview
Contains method to check the presense and validity of changelogs.
Defined Under Namespace
Classes: ChangelogCheckResult, CommitWrapper
Constant Summary
collapse
- NO_CHANGELOG_LABELS =
[
"maintenance::refactor",
"maintenance::pipelines",
"maintenance::workflow",
"ci-build",
"meta",
].freeze
- NO_CHANGELOG_CATEGORIES =
i[docs none].freeze
- CHANGELOG_TRAILER_REGEX =
/^(?<name>Changelog):\s*(?<category>.+)$/i.freeze
- CHANGELOG_EE_TRAILER_REGEX =
/^EE: true$/.freeze
- CHANGELOG_MODIFIED_URL_TEXT =
"**CHANGELOG.md was edited.** Please remove the additions and follow the [changelog guidelines](https://docs.gitlab.com/ee/development/changelog.html).\n\n"
- CHANGELOG_MISSING_URL_TEXT =
"**[CHANGELOG missing](https://docs.gitlab.com/ee/development/changelog.html)**:\n\n"
- IF_REVERT_MR_TEXT =
"In a revert merge request? Use the revert merge request template to add labels [that skip changelog checks](https://docs.gitlab.com/ee/development/pipelines#revert-mrs).\n\nReverting something in the current milestone? A changelog isn't required. Skip changelog checks by adding `~\"regression:*\"` label, then re-run the danger job (there is a link at the bottom of this comment).\n"
- OPTIONAL_CHANGELOG_MESSAGE =
{
local: "If this merge request [doesn't need a CHANGELOG entry](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry), feel free to ignore this message.",
ci: " If this merge request needs a changelog entry, add the `Changelog` trailer to the commit message you want to add to the changelog.\n\n If this merge request [doesn't need a CHANGELOG entry](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry), feel free to ignore this message.\n MSG\n}.freeze\n"
- SEE_DOC =
"See the [changelog documentation](https://docs.gitlab.com/ee/development/changelog.html)."
- REQUIRED_CHANGELOG_REASONS =
{
db_changes: "introduces a database migration",
feature_flag_removed: "removes a feature flag"
}.freeze
- REQUIRED_CHANGELOG_MESSAGE =
{
local: "This merge request requires a changelog entry because it [%<reason>s](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry).",
ci: " To create a changelog entry, add the `Changelog` trailer to one of your Git commit messages.\n\n This merge request requires a changelog entry because it [%<reason>s](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry).\n MSG\n}.freeze\n"
- DEFAULT_CHANGELOG_CATEGORIES =
%w[
added
fixed
changed
deprecated
removed
security
performance
other
].freeze
Instance Method Summary
collapse
Instance Method Details
#add_danger_messages(check_result) ⇒ Object
rubocop:disable Style/SignalException
162
163
164
165
166
167
|
# File 'lib/danger/plugins/changelog.rb', line 162
def add_danger_messages(check_result)
check_result.errors.each { |error| fail(error) }
check_result.warnings.each { |warning| warn(warning) }
check_result.markdowns.each { |markdown_hash| markdown(**markdown_hash) }
check_result.messages.each { |text| message(text) }
end
|
#categories ⇒ Object
112
113
114
|
# File 'lib/danger/plugins/changelog.rb', line 112
def categories
valid_changelog_commits.map(&:category)
end
|
#changelog_categories_checks ⇒ Object
157
158
159
|
# File 'lib/danger/plugins/changelog.rb', line 157
def changelog_categories_checks
check_changelog_commit_categories
end
|
#changelog_commits ⇒ Object
227
228
229
230
231
232
233
|
# File 'lib/danger/plugins/changelog.rb', line 227
def changelog_commits
git.commits.each_with_object([]) do |commit, memo|
trailer = commit.message.match(CHANGELOG_TRAILER_REGEX)
memo << CommitWrapper.new(commit, trailer[:name], trailer[:category]) if trailer
end
end
|
#check! ⇒ Object
116
117
118
119
120
121
122
|
# File 'lib/danger/plugins/changelog.rb', line 116
def check!
return if revert_in_current_milestone?
critical_checks
regular_checks
changelog_categories_checks
end
|
#check_changelog_commit_categories ⇒ Object
rubocop:enable Style/SignalException
171
172
173
174
175
|
# File 'lib/danger/plugins/changelog.rb', line 171
def check_changelog_commit_categories
changelog_commits.each do |commit|
add_danger_messages(check_changelog_trailer(commit))
end
end
|
#check_changelog_path ⇒ Object
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
|
# File 'lib/danger/plugins/changelog.rb', line 187
def check_changelog_path
check_result = ChangelogCheckResult.empty
return check_result unless exist?
ee_changes = helper.changed_files(%r{\Aee/})
if ee_changes.any? && !ee_changelog? && !required?
check_result.warning("This MR changes code in `ee/`, but its Changelog commit is missing the [`EE: true` trailer](https://docs.gitlab.com/ee/development/changelog.html#gitlab-enterprise-changes). Consider adding it to your Changelog commits.")
end
if ee_changes.empty? && ee_changelog?
check_result.warning("This MR has a Changelog commit for EE, but no code changes in `ee/`. Consider removing the `EE: true` trailer from your commits.")
end
if ee_changes.any? && ee_changelog? && required_reasons.include?(:db_changes)
check_result.warning("This MR has a Changelog commit with the `EE: true` trailer, but there are database changes which [requires](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry) the Changelog commit to not have the `EE: true` trailer. Consider removing the `EE: true` trailer from your commits.")
end
check_result
end
|
#check_changelog_trailer(commit) ⇒ Object
177
178
179
180
181
182
183
184
185
|
# File 'lib/danger/plugins/changelog.rb', line 177
def check_changelog_trailer(commit)
unless commit.trailer_key == "Changelog"
return ChangelogCheckResult.error("The changelog trailer for commit #{commit.sha} must be `Changelog` (starting with a capital C), not `#{commit.trailer_key}`")
end
return ChangelogCheckResult.empty if valid_categories.include?(commit.category)
ChangelogCheckResult.error("Commit #{commit.sha} uses an invalid changelog category: #{commit.category}")
end
|
#critical_checks ⇒ Object
136
137
138
139
140
141
142
143
144
145
|
# File 'lib/danger/plugins/changelog.rb', line 136
def critical_checks
check_result = ChangelogCheckResult.empty
check_result.warning(modified_text) if git.modified_files.include?("CHANGELOG.md")
check_result.warning(IF_REVERT_MR_TEXT) if helper.revert_mr? && !helper.stable_branch?
add_danger_messages(check_result)
end
|
#ee_changelog? ⇒ Boolean
241
242
243
244
245
|
# File 'lib/danger/plugins/changelog.rb', line 241
def ee_changelog?
changelog_commits.any? do |commit|
commit.message.match?(CHANGELOG_EE_TRAILER_REGEX)
end
end
|
#exist? ⇒ Boolean
223
224
225
|
# File 'lib/danger/plugins/changelog.rb', line 223
def exist?
valid_changelog_commits.any?
end
|
#modified_text ⇒ Object
247
248
249
250
|
# File 'lib/danger/plugins/changelog.rb', line 247
def modified_text
CHANGELOG_MODIFIED_URL_TEXT +
(helper.ci? ? format(OPTIONAL_CHANGELOG_MESSAGE[:ci]) : OPTIONAL_CHANGELOG_MESSAGE[:local])
end
|
#optional? ⇒ Boolean
219
220
221
|
# File 'lib/danger/plugins/changelog.rb', line 219
def optional?
categories_need_changelog? && mr_without_no_changelog_label?
end
|
#optional_text ⇒ Object
260
261
262
263
|
# File 'lib/danger/plugins/changelog.rb', line 260
def optional_text
CHANGELOG_MISSING_URL_TEXT +
(helper.ci? ? format(OPTIONAL_CHANGELOG_MESSAGE[:ci]) : OPTIONAL_CHANGELOG_MESSAGE[:local])
end
|
#regular_checks ⇒ Object
147
148
149
150
151
152
153
154
155
|
# File 'lib/danger/plugins/changelog.rb', line 147
def regular_checks
if exist?
add_danger_messages(check_changelog_path)
elsif required?
required_texts.each { |_, text| fail(text) }
elsif optional?
message optional_text
end
end
|
#required? ⇒ Boolean
215
216
217
|
# File 'lib/danger/plugins/changelog.rb', line 215
def required?
required_reasons.any?
end
|
#required_reasons ⇒ Object
208
209
210
211
212
213
|
# File 'lib/danger/plugins/changelog.rb', line 208
def required_reasons
[].tap do |reasons|
reasons << :db_changes if helper.changes.added.has_category?(:migration)
reasons << :feature_flag_removed if helper.changes.deleted.has_category?(:feature_flag)
end
end
|
#required_texts ⇒ Object
252
253
254
255
256
257
258
|
# File 'lib/danger/plugins/changelog.rb', line 252
def required_texts
required_reasons.each_with_object({}) do |required_reason, memo|
memo[required_reason] =
CHANGELOG_MISSING_URL_TEXT +
format(REQUIRED_CHANGELOG_MESSAGE[helper.ci? ? :ci : :local], reason: REQUIRED_CHANGELOG_REASONS.fetch(required_reason))
end
end
|
#revert_in_current_milestone? ⇒ Boolean
124
125
126
127
128
129
130
131
132
133
134
|
# File 'lib/danger/plugins/changelog.rb', line 124
def revert_in_current_milestone?
return false unless helper.revert_mr?
return true unless helper.ci?
return false unless helper.current_milestone
current_regression_label = "regression:#{helper.current_milestone.title}"
helper.mr_labels.any?(current_regression_label)
end
|
#valid_changelog_commits ⇒ Object
235
236
237
238
239
|
# File 'lib/danger/plugins/changelog.rb', line 235
def valid_changelog_commits
changelog_commits.select do |commit|
valid_categories.include?(commit.message.match(CHANGELOG_TRAILER_REGEX)[:category])
end
end
|