Skip to content
Snippets Groups Projects
Commit 03f7e89e authored by Rémy Coutable's avatar Rémy Coutable Committed by Albert Salim
Browse files

Introduce Change and Changes classes to encapsulate changes for Danger


This encapsulate logic about the changes into a dedicated class.

Signed-off-by: default avatarRémy Coutable <remy@rymai.me>
parent 20083ff6
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -54,7 +54,7 @@ def check_changelog_path(path)
warn "This MR has a Changelog file in `ee/`, but no code changes in `ee/`. Consider moving the Changelog file outside `ee/`."
end
 
if ee_changes.any? && changelog.ee_changelog? && changelog.required_reasons(feature_flag_helper: feature_flag).include?(:db_changes)
if ee_changes.any? && changelog.ee_changelog? && changelog.required_reasons.include?(:db_changes)
warn "This MR has a Changelog file inside `ee/`, but there are database changes which [requires](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry) the Changelog placement to be outside of `ee/`. Consider moving the Changelog file outside `ee/`."
end
end
Loading
Loading
@@ -68,8 +68,8 @@ changelog_found = changelog.found
if changelog_found
check_changelog_yaml(changelog_found)
check_changelog_path(changelog_found)
elsif changelog.required?(feature_flag_helper: feature_flag)
changelog.required_texts(feature_flag_helper: feature_flag).each { |_, text| fail(text) }
elsif changelog.required?
changelog.required_texts.each { |_, text| fail(text) } # rubocop:disable Lint/UnreachableLoop
elsif changelog.optional?
message changelog.optional_text
end
Loading
Loading
@@ -2,75 +2,48 @@
 
require_relative 'danger_spec_helper'
 
require_relative '../../../tooling/danger/helper'
require_relative '../../../tooling/danger/changelog'
 
RSpec.describe Tooling::Danger::Changelog do
include DangerSpecHelper
 
let(:added_files) { [] }
let(:removed_feature_flag_files) { [] }
let(:fake_git) { double('fake-git', added_files: added_files) }
let(:change_class) { Tooling::Danger::Helper::Change }
let(:changes_class) { Tooling::Danger::Helper::Changes }
let(:changes) { changes_class.new([]) }
 
let(:mr_labels) { nil }
let(:mr_json) { nil }
let(:fake_gitlab) { double('fake-gitlab', mr_labels: mr_labels, mr_json: mr_json) }
let(:mr_labels) { [] }
let(:sanitize_mr_title) { 'Fake Title' }
 
let(:changes_by_category) { nil }
let(:sanitize_mr_title) { nil }
let(:ee?) { false }
let(:fake_helper) { double('fake-helper', changes_by_category: changes_by_category, sanitize_mr_title: sanitize_mr_title, ee?: ee?) }
let(:fake_helper) { double('fake-helper', changes: changes, mr_iid: 1234, mr_title: sanitize_mr_title, mr_labels: mr_labels) }
 
let(:fake_feature_flag) { double('feature-flag', feature_flag_files: removed_feature_flag_files) }
let(:fake_danger) { new_fake_danger.include(described_class) }
 
subject(:changelog) { fake_danger.new(git: fake_git, gitlab: fake_gitlab, helper: fake_helper) }
subject(:changelog) { fake_danger.new(helper: fake_helper) }
 
describe '#required_reasons' do
subject { changelog.required_reasons }
 
[
'db/migrate/20200000000000_new_migration.rb',
'db/post_migrate/20200000000000_new_migration.rb'
].each do |file_path|
context "added files contain a migration (#{file_path})" do
let(:added_files) { [file_path] }
context "added files contain a migration" do
let(:changes) { changes_class.new([change_class.new('foo', :added, :migration)]) }
 
it { is_expected.to include(:db_changes) }
end
it { is_expected.to include(:db_changes) }
end
 
[
'config/feature_flags/foo.yml',
'ee/config/feature_flags/foo.yml'
].each do |file_path|
context "removed files contains a feature flag (#{file_path})" do
let(:removed_feature_flag_files) { [file_path] }
context 'when no feature_flag_helper is given' do
it { is_expected.to be_empty }
end
context "removed files contains a feature flag" do
let(:changes) { changes_class.new([change_class.new('foo', :deleted, :feature_flag)]) }
 
context 'when a feature_flag_helper is given' do
subject { changelog.required_reasons(feature_flag_helper: fake_feature_flag) }
it { is_expected.to include(:feature_flag_removed) }
end
end
it { is_expected.to include(:feature_flag_removed) }
end
 
[
'app/models/model.rb',
'app/assets/javascripts/file.js'
].each do |file_path|
context "added files do not contain a migration (#{file_path})" do
let(:added_files) { [file_path] }
context "added files do not contain a migration" do
let(:changes) { changes_class.new([change_class.new('foo', :added, :frontend)]) }
 
it { is_expected.to be_empty }
end
it { is_expected.to be_empty }
end
 
context "removed files do not contain a feature flag" do
let(:removed_feature_flag_files) { [] }
let(:changes) { changes_class.new([change_class.new('foo', :deleted, :backend)]) }
 
it { is_expected.to be_empty }
end
Loading
Loading
@@ -80,44 +53,27 @@
subject { changelog.required? }
 
context 'added files contain a migration' do
[
'db/migrate/20200000000000_new_migration.rb',
'db/post_migrate/20200000000000_new_migration.rb'
].each do |file_path|
let(:added_files) { [file_path] }
let(:changes) { changes_class.new([change_class.new('foo', :added, :migration)]) }
 
it { is_expected.to be_truthy }
end
it { is_expected.to be_truthy }
end
 
[
'config/feature_flags/foo.yml',
'ee/config/feature_flags/foo.yml'
].each do |file_path|
context "removed files contains a feature flag (#{file_path})" do
let(:removed_feature_flag_files) { [file_path] }
context "removed files contains a feature flag" do
let(:changes) { changes_class.new([change_class.new('foo', :deleted, :feature_flag)]) }
 
context 'when no feature_flag_helper is given' do
it { is_expected.to be_falsey }
end
it { is_expected.to be_truthy }
end
 
context 'when a feature_flag_helper is given' do
subject { changelog.required?(feature_flag_helper: fake_feature_flag) }
context 'added files do not contain a migration' do
let(:changes) { changes_class.new([change_class.new('foo', :added, :frontend)]) }
 
it { is_expected.to be_truthy }
end
end
it { is_expected.to be_falsey }
end
 
context 'added files do not contain a migration' do
[
'app/models/model.rb',
'app/assets/javascripts/file.js'
].each do |file_path|
let(:added_files) { [file_path] }
context "removed files do not contain a feature flag" do
let(:changes) { changes_class.new([change_class.new('foo', :deleted, :backend)]) }
 
it { is_expected.to be_falsey }
end
it { is_expected.to be_falsey }
end
end
 
Loading
Loading
@@ -130,8 +86,7 @@
subject { changelog.optional? }
 
context 'when MR contains only categories requiring no changelog' do
let(:changes_by_category) { { category_without_changelog => nil } }
let(:mr_labels) { [] }
let(:changes) { changes_class.new([change_class.new('foo', :modified, category_without_changelog)]) }
 
it 'is falsey' do
is_expected.to be_falsy
Loading
Loading
@@ -139,7 +94,7 @@
end
 
context 'when MR contains a label that require no changelog' do
let(:changes_by_category) { { category_with_changelog => nil } }
let(:changes) { changes_class.new([change_class.new('foo', :modified, category_with_changelog)]) }
let(:mr_labels) { [label_with_changelog, label_without_changelog] }
 
it 'is falsey' do
Loading
Loading
@@ -148,29 +103,28 @@
end
 
context 'when MR contains a category that require changelog and a category that require no changelog' do
let(:changes_by_category) { { category_with_changelog => nil, category_without_changelog => nil } }
let(:mr_labels) { [] }
let(:changes) { changes_class.new([change_class.new('foo', :modified, category_with_changelog), change_class.new('foo', :modified, category_without_changelog)]) }
 
it 'is truthy' do
is_expected.to be_truthy
context 'with no labels' do
it 'is truthy' do
is_expected.to be_truthy
end
end
end
 
context 'when MR contains a category that require changelog and a category that require no changelog with changelog label' do
let(:changes_by_category) { { category_with_changelog => nil, category_without_changelog => nil } }
let(:mr_labels) { ['feature'] }
context 'with changelog label' do
let(:mr_labels) { ['feature'] }
 
it 'is truthy' do
is_expected.to be_truthy
it 'is truthy' do
is_expected.to be_truthy
end
end
end
 
context 'when MR contains a category that require changelog and a category that require no changelog with no changelog label' do
let(:changes_by_category) { { category_with_changelog => nil, category_without_changelog => nil } }
let(:mr_labels) { ['tooling'] }
context 'with no changelog label' do
let(:mr_labels) { ['tooling'] }
 
it 'is truthy' do
is_expected.to be_falsey
it 'is truthy' do
is_expected.to be_falsey
end
end
end
end
Loading
Loading
@@ -179,50 +133,35 @@
subject { changelog.found }
 
context 'added files contain a changelog' do
[
'changelogs/unreleased/entry.yml',
'ee/changelogs/unreleased/entry.yml'
].each do |file_path|
let(:added_files) { [file_path] }
let(:changes) { changes_class.new([change_class.new('foo', :added, :changelog)]) }
 
it { is_expected.to be_truthy }
end
it { is_expected.to be_truthy }
end
 
context 'added files do not contain a changelog' do
[
'app/models/model.rb',
'app/assets/javascripts/file.js'
].each do |file_path|
let(:added_files) { [file_path] }
it { is_expected.to eq(nil) }
end
let(:changes) { changes_class.new([change_class.new('foo', :added, :backend)]) }
it { is_expected.to eq(nil) }
end
end
 
describe '#ee_changelog?' do
subject { changelog.ee_changelog? }
 
before do
allow(changelog).to receive(:found).and_return(file_path)
end
context 'is ee changelog' do
let(:file_path) { 'ee/changelogs/unreleased/entry.yml' }
let(:changes) { changes_class.new([change_class.new('ee/changelogs/unreleased/entry.yml', :added, :changelog)]) }
 
it { is_expected.to be_truthy }
end
 
context 'is not ee changelog' do
let(:file_path) { 'changelogs/unreleased/entry.yml' }
let(:changes) { changes_class.new([change_class.new('changelogs/unreleased/entry.yml', :added, :changelog)]) }
 
it { is_expected.to be_falsy }
end
end
 
describe '#modified_text' do
let(:mr_json) { { "iid" => 1234, "title" => sanitize_mr_title } }
subject { changelog.modified_text }
 
context "when title is not changed from sanitization", :aggregate_failures do
Loading
Loading
@@ -248,7 +187,6 @@
 
describe '#required_texts' do
let(:sanitize_mr_title) { 'Fake Title' }
let(:mr_json) { { "iid" => 1234, "title" => sanitize_mr_title } }
 
subject { changelog.required_texts }
 
Loading
Loading
@@ -262,7 +200,7 @@
end
 
context 'with a new migration file' do
let(:added_files) { ['db/migrate/20200000000000_new_migration.rb'] }
let(:changes) { changes_class.new([change_class.new('foo', :added, :migration)]) }
 
context "when title is not changed from sanitization", :aggregate_failures do
it_behaves_like 'changelog required text', :db_changes
Loading
Loading
@@ -276,23 +214,13 @@
end
 
context 'with a removed feature flag file' do
let(:removed_feature_flag_files) { ['config/feature_flags/foo.yml'] }
let(:changes) { changes_class.new([change_class.new('foo', :deleted, :feature_flag)]) }
 
context 'when no feature_flag_helper is given' do
it { is_expected.to be_empty }
end
context 'when a feature_flag_helper is given' do
subject { changelog.required_texts(feature_flag_helper: fake_feature_flag) }
it_behaves_like 'changelog required text', :feature_flag_removed
end
it_behaves_like 'changelog required text', :feature_flag_removed
end
end
 
describe '#optional_text' do
let(:mr_json) { { "iid" => 1234, "title" => sanitize_mr_title } }
subject { changelog.optional_text }
 
context "when title is not changed from sanitization", :aggregate_failures do
Loading
Loading
Loading
Loading
@@ -10,13 +10,27 @@
using RSpec::Parameterized::TableSyntax
include DangerSpecHelper
 
let(:fake_git) { double('fake-git') }
let(:mr_author) { nil }
let(:fake_gitlab) { double('fake-gitlab', mr_author: mr_author) }
 
let(:fake_danger) { new_fake_danger.include(described_class) }
 
let(:added_files) { %w[added1] }
let(:modified_files) { %w[modified1] }
let(:deleted_files) { %w[deleted1] }
let(:renamed_before_file) { 'renamed_before' }
let(:renamed_after_file) { 'renamed_after' }
let(:renamed_files) { [{ before: renamed_before_file, after: renamed_after_file }] }
let(:fake_git) { double('fake-git') }
before do
allow(fake_git).to receive(:added_files) { added_files }
allow(fake_git).to receive(:modified_files) { modified_files }
allow(fake_git).to receive(:deleted_files) { deleted_files }
allow(fake_git).to receive(:renamed_files).at_least(:twice) { renamed_files }
end
subject(:helper) { fake_danger.new(git: fake_git, gitlab: fake_gitlab) }
 
describe '#gitlab_helper' do
Loading
Loading
@@ -191,15 +205,16 @@
end
 
describe '#changes_by_category' do
it 'categorizes changed files' do
expect(fake_git).to receive(:added_files) { %w[foo foo.md foo.rb foo.js db/migrate/foo lib/gitlab/database/foo.rb qa/foo ee/changelogs/foo.yml] }
allow(fake_git).to receive(:modified_files) { [] }
allow(fake_git).to receive(:renamed_files) { [] }
let(:added_files) { %w[foo foo.md foo.rb foo.js] }
let(:modified_files) { %w[db/migrate/foo lib/gitlab/database/foo.rb] }
let(:renamed_files) { [{ before: '', after: 'qa/foo' }, { before: '', after: 'ee/changelogs/foo.yml' }] }
 
it 'categorizes changed files' do
expect(helper.changes_by_category).to eq(
backend: %w[foo.rb],
database: %w[db/migrate/foo lib/gitlab/database/foo.rb],
frontend: %w[foo.js],
migration: %w[db/migrate/foo],
none: %w[ee/changelogs/foo.yml foo.md],
qa: %w[qa/foo],
unknown: %w[foo]
Loading
Loading
@@ -207,6 +222,62 @@
end
end
 
describe 'Tooling::Danger::Helper::Changes', :aggregate_failures do
let(:added_files) { %w[db/migrate/foo ee/changelogs/unreleased/foo.yml] }
describe '#has_category?' do
it 'returns true when changes include given category, false otherwise' do
changes = helper.changes
expect(changes.has_category?(:migration)).to eq(true)
expect(changes.has_category?(:changelog)).to eq(true)
expect(changes.has_category?(:backend)).to eq(false)
end
end
describe '#by_category' do
it 'returns an array of Change objects' do
expect(helper.changes.by_category(:migration)).to all(be_an(described_class::Change))
end
it 'returns an array of Change objects with the given category' do
changes = helper.changes
expect(changes.by_category(:migration).files).to eq(['db/migrate/foo'])
expect(changes.by_category(:changelog).files).to eq(['ee/changelogs/unreleased/foo.yml'])
expect(changes.by_category(:backend)).to be_empty
end
end
describe '#categories' do
it 'returns an array of category symbols' do
expect(helper.changes.categories).to contain_exactly(:database, :migration, :changelog, :unknown)
end
end
describe '#files' do
it 'returns an array of files' do
expect(helper.changes.files).to include(*added_files)
end
end
end
describe '#changes' do
it 'returns an array of Change objects' do
expect(helper.changes).to all(be_an(described_class::Change))
end
it 'groups changes by change type' do
changes = helper.changes
expect(changes.added.files).to eq(added_files)
expect(changes.modified.files).to eq(modified_files)
expect(changes.deleted.files).to eq(deleted_files)
expect(changes.renamed_before.files).to eq([renamed_before_file])
expect(changes.renamed_after.files).to eq([renamed_after_file])
end
end
describe '#categories_for_file' do
before do
allow(fake_git).to receive(:diff_for_file).with('usage_data.rb') { double(:diff, patch: "+ count(User.active)") }
Loading
Loading
@@ -304,12 +375,10 @@
 
'db/schema.rb' | [:database]
'db/structure.sql' | [:database]
'db/migrate/foo' | [:database]
'db/post_migrate/foo' | [:database]
'ee/db/migrate/foo' | [:database]
'ee/db/post_migrate/foo' | [:database]
'ee/db/geo/migrate/foo' | [:database]
'ee/db/geo/post_migrate/foo' | [:database]
'db/migrate/foo' | [:database, :migration]
'db/post_migrate/foo' | [:database, :migration]
'ee/db/geo/migrate/foo' | [:database, :migration]
'ee/db/geo/post_migrate/foo' | [:database, :migration]
'app/models/project_authorization.rb' | [:database]
'app/services/users/refresh_authorized_projects_service.rb' | [:database]
'lib/gitlab/background_migration.rb' | [:database]
Loading
Loading
@@ -400,6 +469,22 @@
end
end
 
describe '#mr_iid' do
it 'returns "" when `gitlab_helper` is unavailable' do
expect(helper).to receive(:gitlab_helper).and_return(nil)
expect(helper.mr_iid).to eq('')
end
it 'returns the MR IID when `gitlab_helper` is available' do
mr_iid = '1234'
expect(fake_gitlab).to receive(:mr_json)
.and_return('iid' => mr_iid)
expect(helper.mr_iid).to eq(mr_iid)
end
end
describe '#mr_title' do
it 'returns "" when `gitlab_helper` is unavailable' do
expect(helper).to receive(:gitlab_helper).and_return(nil)
Loading
Loading
@@ -432,6 +517,22 @@
end
end
 
describe '#mr_labels' do
it 'returns "" when `gitlab_helper` is unavailable' do
expect(helper).to receive(:gitlab_helper).and_return(nil)
expect(helper.mr_labels).to eq([])
end
it 'returns the MR labels when `gitlab_helper` is available' do
mr_labels = %w[foo bar baz]
expect(fake_gitlab).to receive(:mr_labels)
.and_return(mr_labels)
expect(helper.mr_labels).to eq(mr_labels)
end
end
describe '#mr_target_branch' do
it 'returns "" when `gitlab_helper` is unavailable' do
expect(helper).to receive(:gitlab_helper).and_return(nil)
Loading
Loading
Loading
Loading
@@ -42,15 +42,15 @@ module Changelog
This merge request requires a changelog entry because it [%<reason>s](https://docs.gitlab.com/ee/development/changelog.html#what-warrants-a-changelog-entry).
MSG
 
def required_reasons(feature_flag_helper: nil)
def required_reasons
[].tap do |reasons|
reasons << :db_changes if git.added_files.any? { |path| path =~ %r{\Adb/(migrate|post_migrate)/} }
reasons << :feature_flag_removed if feature_flag_helper&.respond_to?(:feature_flag_files) && feature_flag_helper.feature_flag_files(change_type: :deleted).any?
reasons << :db_changes if helper.changes.added.has_category?(:migration)
reasons << :feature_flag_removed if helper.changes.deleted.has_category?(:feature_flag)
end
end
 
def required?(feature_flag_helper: nil)
required_reasons(feature_flag_helper: feature_flag_helper).any?
def required?
required_reasons.any?
end
 
def optional?
Loading
Loading
@@ -58,7 +58,7 @@ def optional?
end
 
def found
@found ||= git.added_files.find { |path| path =~ %r{\A(ee/)?(changelogs/unreleased)(-ee)?/} }
@found ||= helper.changes.added.by_category(:changelog).files.first
end
 
def ee_changelog?
Loading
Loading
@@ -67,38 +67,34 @@ def ee_changelog?
 
def modified_text
CHANGELOG_MODIFIED_URL_TEXT +
format(OPTIONAL_CHANGELOG_MESSAGE, mr_iid: mr_iid, mr_title: sanitized_mr_title)
format(OPTIONAL_CHANGELOG_MESSAGE, mr_iid: helper.mr_iid, mr_title: sanitized_mr_title)
end
 
def required_texts(feature_flag_helper: nil)
required_reasons(feature_flag_helper: feature_flag_helper).each_with_object({}) do |required_reason, memo|
def required_texts
required_reasons.each_with_object({}) do |required_reason, memo|
memo[required_reason] =
CHANGELOG_MISSING_URL_TEXT +
format(REQUIRED_CHANGELOG_MESSAGE, reason: REQUIRED_CHANGELOG_REASONS.fetch(required_reason), mr_iid: mr_iid, mr_title: sanitized_mr_title)
format(REQUIRED_CHANGELOG_MESSAGE, reason: REQUIRED_CHANGELOG_REASONS.fetch(required_reason), mr_iid: helper.mr_iid, mr_title: sanitized_mr_title)
end
end
 
def optional_text
CHANGELOG_MISSING_URL_TEXT +
format(OPTIONAL_CHANGELOG_MESSAGE, mr_iid: mr_iid, mr_title: sanitized_mr_title)
format(OPTIONAL_CHANGELOG_MESSAGE, mr_iid: helper.mr_iid, mr_title: sanitized_mr_title)
end
 
private
 
def mr_iid
gitlab.mr_json["iid"]
end
def sanitized_mr_title
TitleLinting.sanitize_mr_title(gitlab.mr_json["title"])
TitleLinting.sanitize_mr_title(helper.mr_title)
end
 
def categories_need_changelog?
(helper.changes_by_category.keys - NO_CHANGELOG_CATEGORIES).any?
(helper.changes.categories - NO_CHANGELOG_CATEGORIES).any?
end
 
def without_no_changelog_label?
(gitlab.mr_labels & NO_CHANGELOG_LABELS).empty?
(helper.mr_labels & NO_CHANGELOG_LABELS).empty?
end
end
end
Loading
Loading
# frozen_string_literal: true
 
require 'delegate'
require_relative 'teammate'
require_relative 'title_linting'
 
Loading
Loading
@@ -86,13 +88,84 @@ def markdown_list(items)
end
end
 
# @return [Hash<String,Array<String>>]
Change = Struct.new(:file, :change_type, :category)
class Changes < ::SimpleDelegator
def added
select_by_change_type(:added)
end
def modified
select_by_change_type(:modified)
end
def deleted
select_by_change_type(:deleted)
end
def renamed_before
select_by_change_type(:renamed_before)
end
def renamed_after
select_by_change_type(:renamed_after)
end
def has_category?(category)
any? { |change| change.category == category }
end
def by_category(category)
Changes.new(select { |change| change.category == category })
end
def categories
map(&:category).uniq
end
def files
map(&:file)
end
private
def select_by_change_type(change_type)
Changes.new(select { |change| change.change_type == change_type })
end
end
# @return [Hash<Symbol,Array<String>>]
def changes_by_category
all_changed_files.each_with_object(Hash.new { |h, k| h[k] = [] }) do |file, hash|
categories_for_file(file).each { |category| hash[category] << file }
end
end
 
# @return [Changes]
def changes
Changes.new([]).tap do |changes|
git.added_files.each do |file|
categories_for_file(file).each { |category| changes << Change.new(file, :added, category) }
end
git.modified_files.each do |file|
categories_for_file(file).each { |category| changes << Change.new(file, :modified, category) }
end
git.deleted_files.each do |file|
categories_for_file(file).each { |category| changes << Change.new(file, :deleted, category) }
end
git.renamed_files.map { |x| x[:before] }.each do |file|
categories_for_file(file).each { |category| changes << Change.new(file, :renamed_before, category) }
end
git.renamed_files.map { |x| x[:after] }.each do |file|
categories_for_file(file).each { |category| changes << Change.new(file, :renamed_after, category) }
end
end
end
# Determines the categories a file is in, e.g., `[:frontend]`, `[:backend]`, or `%i[frontend engineering_productivity]`
# using filename regex and specific change regex if given.
#
Loading
Loading
@@ -130,6 +203,10 @@ def label_for_category(category)
CATEGORIES = {
[%r{usage_data\.rb}, %r{^(\+|-).*\s+(count|distinct_count|estimate_batch_distinct_count)\(.*\)(.*)$}] => [:database, :backend],
 
%r{\A(ee/)?config/feature_flags/} => :feature_flag,
%r{\A(ee/)?(changelogs/unreleased)(-ee)?/} => :changelog,
%r{\Adoc/.*(\.(md|png|gif|jpg))\z} => :docs,
%r{\A(CONTRIBUTING|LICENSE|MAINTENANCE|PHILOSOPHY|PROCESS|README)(\.md)?\z} => :docs,
 
Loading
Loading
@@ -159,6 +236,7 @@ def label_for_category(category)
\.gitlab/ci/frontend\.gitlab-ci\.yml
)\z}x => %i[frontend engineering_productivity],
 
%r{\A(ee/)?db/(geo/)?(migrate|post_migrate)/} => [:database, :migration],
%r{\A(ee/)?db/(?!fixtures)[^/]+} => :database,
%r{\A(ee/)?lib/gitlab/(database|background_migration|sql|github_import)(/|\.rb)} => :database,
%r{\A(app/models/project_authorization|app/services/users/refresh_authorized_projects_service)(/|\.rb)} => :database,
Loading
Loading
@@ -214,6 +292,12 @@ def new_teammates(usernames)
usernames.map { |u| Tooling::Danger::Teammate.new('username' => u) }
end
 
def mr_iid
return '' unless gitlab_helper
gitlab_helper.mr_json['iid']
end
def mr_title
return '' unless gitlab_helper
 
Loading
Loading
@@ -226,6 +310,12 @@ def mr_web_url
gitlab_helper.mr_json['web_url']
end
 
def mr_labels
return [] unless gitlab_helper
gitlab_helper.mr_labels
end
def mr_target_branch
return '' unless gitlab_helper
 
Loading
Loading
@@ -257,10 +347,9 @@ def stable_branch?
end
 
def mr_has_labels?(*labels)
return false unless gitlab_helper
labels = labels.flatten.uniq
(labels & gitlab_helper.mr_labels) == labels
(labels & mr_labels) == labels
end
 
def labels_list(labels, sep: ', ')
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment