2020-01-01 13:55:28 +05:30
# frozen_string_literal: true
2021-04-17 20:07:23 +05:30
require 'gitlab-dangerfiles'
require 'gitlab/dangerfiles/spec_helper'
2020-01-01 13:55:28 +05:30
2021-03-11 19:13:27 +05:30
require_relative '../../../tooling/danger/changelog'
2021-04-17 20:07:23 +05:30
require_relative '../../../tooling/danger/project_helper'
2020-01-01 13:55:28 +05:30
2021-03-11 19:13:27 +05:30
RSpec . describe Tooling :: Danger :: Changelog do
2021-04-17 20:07:23 +05:30
include_context " with dangerfile "
2020-01-01 13:55:28 +05:30
2021-04-17 20:07:23 +05:30
let ( :fake_danger ) { DangerSpecHelper . fake_danger . include ( described_class ) }
let ( :fake_project_helper ) { double ( 'fake-project-helper' , helper : fake_helper ) . tap { | h | h . class . include ( Tooling :: Danger :: ProjectHelper ) } }
2020-01-01 13:55:28 +05:30
2021-04-17 20:07:23 +05:30
subject ( :changelog ) { fake_danger . new ( helper : fake_helper ) }
2020-01-01 13:55:28 +05:30
2021-04-17 20:07:23 +05:30
before do
allow ( changelog ) . to receive ( :project_helper ) . and_return ( fake_project_helper )
end
2021-09-04 01:27:46 +05:30
describe '#check_changelog_commit_categories' do
context 'when all changelog commits are correct' do
it 'does not produce any messages' do
commit = double ( :commit , message : " foo \n Changelog: fixed " )
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
allow ( changelog ) . to receive ( :changelog_commits ) . and_return ( [ commit ] )
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
expect ( changelog ) . not_to receive ( :fail )
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
changelog . check_changelog_commit_categories
2021-06-08 01:23:25 +05:30
end
end
2021-09-04 01:27:46 +05:30
context 'when a commit has an incorrect trailer' do
it 'adds a message' do
commit = double ( :commit , message : " foo \n Changelog: foo " , sha : '123' )
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
allow ( changelog ) . to receive ( :changelog_commits ) . and_return ( [ commit ] )
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
expect ( changelog ) . to receive ( :fail )
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
changelog . check_changelog_commit_categories
2021-06-08 01:23:25 +05:30
end
end
2021-09-04 01:27:46 +05:30
end
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
describe '#check_changelog_trailer' do
subject { changelog . check_changelog_trailer ( commit ) }
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
context " when commit include a changelog trailer with an unknown category " do
let ( :commit ) { double ( 'commit' , message : " Hello world \n \n Changelog: foo " , sha : " abc123 " ) }
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
it { is_expected . to have_attributes ( errors : [ " Commit #{ commit . sha } uses an invalid changelog category: foo " ] ) }
2021-06-08 01:23:25 +05:30
end
2021-09-04 01:27:46 +05:30
context 'when a commit uses the wrong casing for a trailer' do
let ( :commit ) { double ( 'commit' , message : " Hello world \n \n changelog: foo " , sha : " abc123 " ) }
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
it { is_expected . to have_attributes ( errors : [ " The changelog trailer for commit #{ commit . sha } must be `Changelog` (starting with a capital C), not `changelog` " ] ) }
2021-06-08 01:23:25 +05:30
end
2021-09-04 01:27:46 +05:30
described_class :: CATEGORIES . each do | category |
context " when commit include a changelog trailer with category set to ' #{ category } ' " do
let ( :commit ) { double ( 'commit' , message : " Hello world \n \n Changelog: #{ category } " , sha : " abc123 " ) }
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
it { is_expected . to have_attributes ( errors : [ ] ) }
2021-06-08 01:23:25 +05:30
end
end
end
describe '#check_changelog_path' do
let ( :changelog_path ) { 'changelog-path.yml' }
let ( :foss_change ) { nil }
let ( :ee_change ) { nil }
let ( :changelog_change ) { nil }
let ( :changes ) { changes_class . new ( [ foss_change , ee_change , changelog_change ] . compact ) }
before do
allow ( changelog ) . to receive ( :present? ) . and_return ( true )
end
subject { changelog . check_changelog_path }
context " when changelog is not present " do
before do
allow ( changelog ) . to receive ( :present? ) . and_return ( false )
end
it { is_expected . to have_attributes ( errors : [ ] , warnings : [ ] , markdowns : [ ] , messages : [ ] ) }
end
context " with EE changes " do
let ( :ee_change ) { change_class . new ( 'ee/app/models/foo.rb' , :added , :backend ) }
context " and a non-EE changelog, and changelog not required " do
before do
allow ( changelog ) . to receive ( :required? ) . and_return ( false )
2021-09-04 01:27:46 +05:30
allow ( changelog ) . to receive ( :ee_changelog? ) . and_return ( false )
2021-06-08 01:23:25 +05:30
end
2021-09-04 01:27:46 +05:30
it { is_expected . to have_attributes ( warnings : [ " 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
context " and a EE changelog " do
before do
allow ( changelog ) . to receive ( :ee_changelog? ) . and_return ( true )
end
it { is_expected . to have_attributes ( errors : [ ] , warnings : [ ] , markdowns : [ ] , messages : [ ] ) }
context " and there are DB changes " do
let ( :foss_change ) { change_class . new ( 'db/migrate/foo.rb' , :added , :migration ) }
it { is_expected . to have_attributes ( warnings : [ " 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
2021-06-08 01:23:25 +05:30
end
end
context " with no EE changes " do
let ( :foss_change ) { change_class . new ( 'app/models/foo.rb' , :added , :backend ) }
context " and a non-EE changelog " do
2021-09-04 01:27:46 +05:30
before do
allow ( changelog ) . to receive ( :ee_changelog? ) . and_return ( false )
end
2021-06-08 01:23:25 +05:30
it { is_expected . to have_attributes ( errors : [ ] , warnings : [ ] , markdowns : [ ] , messages : [ ] ) }
end
context " and a EE changelog " do
2021-09-04 01:27:46 +05:30
before do
allow ( changelog ) . to receive ( :ee_changelog? ) . and_return ( true )
end
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
it { is_expected . to have_attributes ( warnings : [ " This MR has a Changelog commit for EE, but no code changes in `ee/`. Consider removing the `EE: true` trailer from your commits. " ] ) }
2021-06-08 01:23:25 +05:30
end
end
end
2021-04-17 20:07:23 +05:30
describe '#required_reasons' do
subject { changelog . required_reasons }
2021-09-04 01:27:46 +05:30
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
2021-04-17 20:07:23 +05:30
context " removed files contains a feature flag " do
let ( :changes ) { changes_class . new ( [ change_class . new ( 'foo' , :deleted , :feature_flag ) ] ) }
2020-01-01 13:55:28 +05:30
2021-04-17 20:07:23 +05:30
it { is_expected . to include ( :feature_flag_removed ) }
end
2021-09-04 01:27:46 +05:30
context " added files do not contain a migration " do
let ( :changes ) { changes_class . new ( [ change_class . new ( 'foo' , :added , :frontend ) ] ) }
2021-04-17 20:07:23 +05:30
it { is_expected . to be_empty }
end
2021-09-04 01:27:46 +05:30
context " removed files do not contain a feature flag " do
let ( :changes ) { changes_class . new ( [ change_class . new ( 'foo' , :deleted , :backend ) ] ) }
2020-01-01 13:55:28 +05:30
2021-04-17 20:07:23 +05:30
it { is_expected . to be_empty }
end
end
2020-01-01 13:55:28 +05:30
2020-11-24 15:15:51 +05:30
describe '#required?' do
subject { changelog . required? }
2021-09-04 01:27:46 +05:30
context 'added files contain a migration' do
let ( :changes ) { changes_class . new ( [ change_class . new ( 'foo' , :added , :migration ) ] ) }
it { is_expected . to be_truthy }
end
2021-04-17 20:07:23 +05:30
context " removed files contains a feature flag " do
let ( :changes ) { changes_class . new ( [ change_class . new ( 'foo' , :deleted , :feature_flag ) ] ) }
it { is_expected . to be_truthy }
2020-11-24 15:15:51 +05:30
end
2021-09-04 01:27:46 +05:30
context 'added files do not contain a migration' do
let ( :changes ) { changes_class . new ( [ change_class . new ( 'foo' , :added , :frontend ) ] ) }
2020-11-24 15:15:51 +05:30
2021-04-17 20:07:23 +05:30
it { is_expected . to be_falsey }
end
2021-09-04 01:27:46 +05:30
context " removed files do not contain a feature flag " do
let ( :changes ) { changes_class . new ( [ change_class . new ( 'foo' , :deleted , :backend ) ] ) }
2021-04-17 20:07:23 +05:30
it { is_expected . to be_falsey }
2020-11-24 15:15:51 +05:30
end
end
describe '#optional?' do
2020-07-28 23:09:34 +05:30
let ( :category_with_changelog ) { :backend }
let ( :label_with_changelog ) { 'frontend' }
2021-03-11 19:13:27 +05:30
let ( :category_without_changelog ) { Tooling :: Danger :: Changelog :: NO_CHANGELOG_CATEGORIES . first }
let ( :label_without_changelog ) { Tooling :: Danger :: Changelog :: NO_CHANGELOG_LABELS . first }
2020-01-01 13:55:28 +05:30
2020-11-24 15:15:51 +05:30
subject { changelog . optional? }
2020-01-01 13:55:28 +05:30
2020-07-28 23:09:34 +05:30
context 'when MR contains only categories requiring no changelog' do
2021-04-17 20:07:23 +05:30
let ( :changes ) { changes_class . new ( [ change_class . new ( 'foo' , :modified , category_without_changelog ) ] ) }
2020-01-01 13:55:28 +05:30
2020-07-28 23:09:34 +05:30
it 'is falsey' do
2020-01-01 13:55:28 +05:30
is_expected . to be_falsy
end
end
2020-07-28 23:09:34 +05:30
context 'when MR contains a label that require no changelog' do
2021-04-17 20:07:23 +05:30
let ( :changes ) { changes_class . new ( [ change_class . new ( 'foo' , :modified , category_with_changelog ) ] ) }
2020-07-28 23:09:34 +05:30
let ( :mr_labels ) { [ label_with_changelog , label_without_changelog ] }
it 'is falsey' do
is_expected . to be_falsy
end
2020-01-01 13:55:28 +05:30
end
2020-07-28 23:09:34 +05:30
context 'when MR contains a category that require changelog and a category that require no changelog' do
2021-04-17 20:07:23 +05:30
let ( :changes ) { changes_class . new ( [ change_class . new ( 'foo' , :modified , category_with_changelog ) , change_class . new ( 'foo' , :modified , category_without_changelog ) ] ) }
2020-01-01 13:55:28 +05:30
2021-04-17 20:07:23 +05:30
context 'with no labels' do
it 'is truthy' do
is_expected . to be_truthy
end
2020-01-01 13:55:28 +05:30
end
2020-10-24 23:57:45 +05:30
2021-04-17 20:07:23 +05:30
context 'with changelog label' do
2021-12-11 22:18:48 +05:30
let ( :mr_labels ) { [ 'type::feature' ] }
2020-10-24 23:57:45 +05:30
2021-04-17 20:07:23 +05:30
it 'is truthy' do
is_expected . to be_truthy
end
2020-10-24 23:57:45 +05:30
end
2021-04-17 20:07:23 +05:30
context 'with no changelog label' do
2021-12-11 22:18:48 +05:30
let ( :mr_labels ) { [ 'type::tooling' ] }
2020-10-24 23:57:45 +05:30
2021-04-17 20:07:23 +05:30
it 'is truthy' do
is_expected . to be_falsey
end
2020-10-24 23:57:45 +05:30
end
end
2020-01-01 13:55:28 +05:30
end
2021-06-08 01:23:25 +05:30
describe '#present?' do
2021-09-04 01:27:46 +05:30
it 'returns true when a Changelog commit is present' do
allow ( changelog )
. to receive ( :valid_changelog_commits )
. and_return ( [ double ( :commit ) ] )
2020-01-01 13:55:28 +05:30
2021-09-04 01:27:46 +05:30
expect ( changelog ) . to be_present
2020-01-01 13:55:28 +05:30
end
2021-09-04 01:27:46 +05:30
it 'returns false when a Changelog commit is missing' do
allow ( changelog ) . to receive ( :valid_changelog_commits ) . and_return ( [ ] )
2021-04-17 20:07:23 +05:30
2021-09-04 01:27:46 +05:30
expect ( changelog ) . not_to be_present
2020-01-01 13:55:28 +05:30
end
end
2021-09-04 01:27:46 +05:30
describe '#changelog_commits' do
it 'returns the commits that include a Changelog trailer' do
commit1 = double ( :commit , message : " foo \n Changelog: fixed " )
commit2 = double ( :commit , message : " bar \n Changelog: kittens " )
commit3 = double ( :commit , message : 'testing' )
git = double ( :git )
2020-01-01 13:55:28 +05:30
2021-09-04 01:27:46 +05:30
allow ( changelog ) . to receive ( :git ) . and_return ( git )
allow ( git ) . to receive ( :commits ) . and_return ( [ commit1 , commit2 , commit3 ] )
2020-01-01 13:55:28 +05:30
2021-09-04 01:27:46 +05:30
expect ( changelog . changelog_commits ) . to eq ( [ commit1 , commit2 ] )
2020-01-01 13:55:28 +05:30
end
2021-09-04 01:27:46 +05:30
end
describe '#valid_changelog_commits' do
it 'returns the commits with a valid Changelog trailer' do
commit1 = double ( :commit , message : " foo \n Changelog: fixed " )
commit2 = double ( :commit , message : " bar \n Changelog: kittens " )
2020-01-01 13:55:28 +05:30
2021-09-04 01:27:46 +05:30
allow ( changelog )
. to receive ( :changelog_commits )
. and_return ( [ commit1 , commit2 ] )
2020-01-01 13:55:28 +05:30
2021-09-04 01:27:46 +05:30
expect ( changelog . valid_changelog_commits ) . to eq ( [ commit1 ] )
2020-01-01 13:55:28 +05:30
end
end
2020-11-24 15:15:51 +05:30
2021-09-04 01:27:46 +05:30
describe '#ee_changelog?' do
it 'returns true when an EE changelog commit is present' do
commit = double ( :commit , message : " foo \n EE: true " )
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
allow ( changelog ) . to receive ( :changelog_commits ) . and_return ( [ commit ] )
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
expect ( changelog . ee_changelog? ) . to eq ( true )
2021-06-08 01:23:25 +05:30
end
2021-09-04 01:27:46 +05:30
it 'returns false when an EE changelog commit is missing' do
commit = double ( :commit , message : 'foo' )
2021-06-08 01:23:25 +05:30
2021-09-04 01:27:46 +05:30
allow ( changelog ) . to receive ( :changelog_commits ) . and_return ( [ commit ] )
expect ( changelog . ee_changelog? ) . to eq ( false )
2021-06-08 01:23:25 +05:30
end
end
2020-11-24 15:15:51 +05:30
describe '#modified_text' do
subject { changelog . modified_text }
2021-04-29 21:17:54 +05:30
context 'when in CI context' do
shared_examples 'changelog modified text' do | key |
specify do
expect ( subject ) . to include ( 'CHANGELOG.md was edited' )
2021-09-04 01:27:46 +05:30
expect ( subject ) . to include ( '`Changelog` trailer' )
expect ( subject ) . to include ( '`EE: true`' )
2021-04-29 21:17:54 +05:30
end
end
2021-03-08 18:12:59 +05:30
2021-04-29 21:17:54 +05:30
before do
allow ( fake_helper ) . to receive ( :ci? ) . and_return ( true )
end
context " when title is not changed from sanitization " , :aggregate_failures do
let ( :mr_title ) { 'Fake Title' }
it_behaves_like 'changelog modified text'
end
context " when title needs sanitization " , :aggregate_failures do
let ( :mr_title ) { 'DRAFT: Fake Title' }
it_behaves_like 'changelog modified text'
2021-03-08 18:12:59 +05:30
end
end
2021-04-29 21:17:54 +05:30
context 'when in local context' do
let ( :mr_title ) { 'Fake Title' }
before do
allow ( fake_helper ) . to receive ( :ci? ) . and_return ( false )
end
2021-03-08 18:12:59 +05:30
specify do
expect ( subject ) . to include ( 'CHANGELOG.md was edited' )
2021-09-04 01:27:46 +05:30
expect ( subject ) . not_to include ( '`Changelog` trailer' )
2021-03-08 18:12:59 +05:30
end
2020-11-24 15:15:51 +05:30
end
end
2021-04-17 20:07:23 +05:30
describe '#required_texts' do
let ( :mr_title ) { 'Fake Title' }
2020-11-24 15:15:51 +05:30
2021-04-17 20:07:23 +05:30
subject { changelog . required_texts }
2021-03-08 18:12:59 +05:30
2021-04-29 21:17:54 +05:30
context 'when in CI context' do
before do
allow ( fake_helper ) . to receive ( :ci? ) . and_return ( true )
2021-03-08 18:12:59 +05:30
end
2021-04-29 21:17:54 +05:30
shared_examples 'changelog required text' do | key |
specify do
expect ( subject ) . to have_key ( key )
expect ( subject [ key ] ) . to include ( 'CHANGELOG missing' )
2021-09-04 01:27:46 +05:30
expect ( subject [ key ] ) . to include ( '`Changelog` trailer' )
end
end
context 'with a new migration file' do
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
end
context " when title needs sanitization " , :aggregate_failures do
let ( :mr_title ) { 'DRAFT: Fake Title' }
it_behaves_like 'changelog required text' , :db_changes
2021-04-29 21:17:54 +05:30
end
end
2021-03-08 18:12:59 +05:30
2021-04-29 21:17:54 +05:30
context 'with a removed feature flag file' do
let ( :changes ) { changes_class . new ( [ change_class . new ( 'foo' , :deleted , :feature_flag ) ] ) }
2021-04-17 20:07:23 +05:30
2021-04-29 21:17:54 +05:30
it_behaves_like 'changelog required text' , :feature_flag_removed
2021-03-08 18:12:59 +05:30
end
2020-11-24 15:15:51 +05:30
end
2021-04-17 20:07:23 +05:30
2021-04-29 21:17:54 +05:30
context 'when in local context' do
before do
allow ( fake_helper ) . to receive ( :ci? ) . and_return ( false )
end
shared_examples 'changelog required text' do | key |
specify do
expect ( subject ) . to have_key ( key )
expect ( subject [ key ] ) . to include ( 'CHANGELOG missing' )
2021-09-04 01:27:46 +05:30
expect ( subject [ key ] ) . not_to include ( '`Changelog` trailer' )
end
end
context 'with a new migration file' do
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
end
context " when title needs sanitization " , :aggregate_failures do
let ( :mr_title ) { 'DRAFT: Fake Title' }
it_behaves_like 'changelog required text' , :db_changes
2021-04-29 21:17:54 +05:30
end
end
context 'with a removed feature flag file' do
let ( :changes ) { changes_class . new ( [ change_class . new ( 'foo' , :deleted , :feature_flag ) ] ) }
it_behaves_like 'changelog required text' , :feature_flag_removed
end
2021-04-17 20:07:23 +05:30
end
2020-11-24 15:15:51 +05:30
end
2021-03-08 18:12:59 +05:30
describe '#optional_text' do
2020-11-24 15:15:51 +05:30
subject { changelog . optional_text }
2021-04-29 21:17:54 +05:30
context 'when in CI context' do
shared_examples 'changelog optional text' do | key |
specify do
expect ( subject ) . to include ( 'CHANGELOG missing' )
2021-09-04 01:27:46 +05:30
expect ( subject ) . to include ( '`Changelog` trailer' )
expect ( subject ) . to include ( 'EE: true' )
2021-04-29 21:17:54 +05:30
end
end
2021-03-08 18:12:59 +05:30
2021-04-29 21:17:54 +05:30
before do
allow ( fake_helper ) . to receive ( :ci? ) . and_return ( true )
end
context " when title is not changed from sanitization " , :aggregate_failures do
let ( :mr_title ) { 'Fake Title' }
it_behaves_like 'changelog optional text'
end
context " when title needs sanitization " , :aggregate_failures do
let ( :mr_title ) { 'DRAFT: Fake Title' }
it_behaves_like 'changelog optional text'
2021-03-08 18:12:59 +05:30
end
end
2021-04-29 21:17:54 +05:30
context 'when in local context' do
let ( :mr_title ) { 'Fake Title' }
before do
allow ( fake_helper ) . to receive ( :ci? ) . and_return ( false )
end
2021-03-08 18:12:59 +05:30
specify do
expect ( subject ) . to include ( 'CHANGELOG missing' )
end
2020-11-24 15:15:51 +05:30
end
end
2020-01-01 13:55:28 +05:30
end