diff --git a/Gemfile b/Gemfile index d15628eb83c..13303c2f7a2 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,6 @@ source 'https://rubygems.org' -gem 'rails', '6.0.2' +gem 'rails', '~> 6.0.2.2' gem 'bootsnap', '~> 1.4.6' diff --git a/Gemfile.lock b/Gemfile.lock index 64bf4ec44d7..68e87fc3304 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,59 +6,59 @@ GEM ace-rails-ap (4.1.2) acme-client (2.0.5) faraday (~> 0.9, >= 0.9.1) - actioncable (6.0.2) - actionpack (= 6.0.2) + actioncable (6.0.2.2) + actionpack (= 6.0.2.2) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailbox (6.0.2) - actionpack (= 6.0.2) - activejob (= 6.0.2) - activerecord (= 6.0.2) - activestorage (= 6.0.2) - activesupport (= 6.0.2) + actionmailbox (6.0.2.2) + actionpack (= 6.0.2.2) + activejob (= 6.0.2.2) + activerecord (= 6.0.2.2) + activestorage (= 6.0.2.2) + activesupport (= 6.0.2.2) mail (>= 2.7.1) - actionmailer (6.0.2) - actionpack (= 6.0.2) - actionview (= 6.0.2) - activejob (= 6.0.2) + actionmailer (6.0.2.2) + actionpack (= 6.0.2.2) + actionview (= 6.0.2.2) + activejob (= 6.0.2.2) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (6.0.2) - actionview (= 6.0.2) - activesupport (= 6.0.2) - rack (~> 2.0) + actionpack (6.0.2.2) + actionview (= 6.0.2.2) + activesupport (= 6.0.2.2) + rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actiontext (6.0.2) - actionpack (= 6.0.2) - activerecord (= 6.0.2) - activestorage (= 6.0.2) - activesupport (= 6.0.2) + actiontext (6.0.2.2) + actionpack (= 6.0.2.2) + activerecord (= 6.0.2.2) + activestorage (= 6.0.2.2) + activesupport (= 6.0.2.2) nokogiri (>= 1.8.5) - actionview (6.0.2) - activesupport (= 6.0.2) + actionview (6.0.2.2) + activesupport (= 6.0.2.2) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activejob (6.0.2) - activesupport (= 6.0.2) + activejob (6.0.2.2) + activesupport (= 6.0.2.2) globalid (>= 0.3.6) - activemodel (6.0.2) - activesupport (= 6.0.2) - activerecord (6.0.2) - activemodel (= 6.0.2) - activesupport (= 6.0.2) + activemodel (6.0.2.2) + activesupport (= 6.0.2.2) + activerecord (6.0.2.2) + activemodel (= 6.0.2.2) + activesupport (= 6.0.2.2) activerecord-explain-analyze (0.1.0) activerecord (>= 4) pg - activestorage (6.0.2) - actionpack (= 6.0.2) - activejob (= 6.0.2) - activerecord (= 6.0.2) + activestorage (6.0.2.2) + actionpack (= 6.0.2.2) + activejob (= 6.0.2.2) + activerecord (= 6.0.2.2) marcel (~> 0.3.1) - activesupport (6.0.2) + activesupport (6.0.2.2) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) @@ -808,20 +808,20 @@ GEM rack-test (1.1.0) rack (>= 1.0, < 3) rack-timeout (0.5.1) - rails (6.0.2) - actioncable (= 6.0.2) - actionmailbox (= 6.0.2) - actionmailer (= 6.0.2) - actionpack (= 6.0.2) - actiontext (= 6.0.2) - actionview (= 6.0.2) - activejob (= 6.0.2) - activemodel (= 6.0.2) - activerecord (= 6.0.2) - activestorage (= 6.0.2) - activesupport (= 6.0.2) + rails (6.0.2.2) + actioncable (= 6.0.2.2) + actionmailbox (= 6.0.2.2) + actionmailer (= 6.0.2.2) + actionpack (= 6.0.2.2) + actiontext (= 6.0.2.2) + actionview (= 6.0.2.2) + activejob (= 6.0.2.2) + activemodel (= 6.0.2.2) + activerecord (= 6.0.2.2) + activestorage (= 6.0.2.2) + activesupport (= 6.0.2.2) bundler (>= 1.3.0) - railties (= 6.0.2) + railties (= 6.0.2.2) sprockets-rails (>= 2.0.0) rails-controller-testing (1.0.4) actionpack (>= 5.0.1.x) @@ -835,9 +835,9 @@ GEM rails-i18n (6.0.0) i18n (>= 0.7, < 2) railties (>= 6.0.0, < 7) - railties (6.0.2) - actionpack (= 6.0.2) - activesupport (= 6.0.2) + railties (6.0.2.2) + actionpack (= 6.0.2.2) + activesupport (= 6.0.2.2) method_source rake (>= 0.8.7) thor (>= 0.20.3, < 2.0) @@ -1146,7 +1146,7 @@ GEM xml-simple (1.1.5) xpath (3.2.0) nokogiri (~> 1.8) - zeitwerk (2.2.2) + zeitwerk (2.3.0) PLATFORMS ruby @@ -1337,7 +1337,7 @@ DEPENDENCIES rack-oauth2 (~> 1.9.3) rack-proxy (~> 0.6.0) rack-timeout - rails (= 6.0.2) + rails (~> 6.0.2.2) rails-controller-testing rails-i18n (~> 6.0) rainbow (~> 3.0) diff --git a/app/models/project_services/chat_message/pipeline_message.rb b/app/models/project_services/chat_message/pipeline_message.rb index 50b982a803f..1cd3837433f 100644 --- a/app/models/project_services/chat_message/pipeline_message.rb +++ b/app/models/project_services/chat_message/pipeline_message.rb @@ -52,8 +52,6 @@ module ChatMessage def attachments return message if markdown - return [{ text: format(message), color: attachment_color }] unless fancy_notifications? - [{ fallback: format(message), color: attachment_color, @@ -103,10 +101,6 @@ module ChatMessage failed_jobs.uniq { |job| job[:name] }.reverse end - def fancy_notifications? - Feature.enabled?(:fancy_pipeline_slack_notifications, default_enabled: true) - end - def failed_stages_field { title: s_("ChatMessage|Failed stage").pluralize(failed_stages.length), @@ -166,42 +160,22 @@ module ChatMessage end def humanized_status - if fancy_notifications? - case status - when 'success' - detailed_status == "passed with warnings" ? s_("ChatMessage|has passed with warnings") : s_("ChatMessage|has passed") - when 'failed' - s_("ChatMessage|has failed") - else - status - end + case status + when 'success' + detailed_status == "passed with warnings" ? s_("ChatMessage|has passed with warnings") : s_("ChatMessage|has passed") + when 'failed' + s_("ChatMessage|has failed") else - case status - when 'success' - s_("ChatMessage|passed") - when 'failed' - s_("ChatMessage|failed") - else - status - end + status end end def attachment_color - if fancy_notifications? - case status - when 'success' - detailed_status == 'passed with warnings' ? 'warning' : 'good' - else - 'danger' - end + case status + when 'success' + detailed_status == 'passed with warnings' ? 'warning' : 'good' else - case status - when 'success' - 'good' - else - 'danger' - end + 'danger' end end @@ -230,7 +204,7 @@ module ChatMessage end def pipeline_url - if fancy_notifications? && failed_jobs.any? + if failed_jobs.any? pipeline_failed_jobs_url else "#{project_url}/pipelines/#{pipeline_id}" diff --git a/changelogs/unreleased/sh-update-rails-6-0-2-2.yml b/changelogs/unreleased/sh-update-rails-6-0-2-2.yml new file mode 100644 index 00000000000..0359c42c678 --- /dev/null +++ b/changelogs/unreleased/sh-update-rails-6-0-2-2.yml @@ -0,0 +1,5 @@ +--- +title: Update to Rails 6.0.2.2 +merge_request: 29743 +author: +type: other diff --git a/config/initializers/active_record_fix_insert_all.rb b/config/initializers/active_record_fix_insert_all.rb index 8ae208dd0e5..08d504734a5 100644 --- a/config/initializers/active_record_fix_insert_all.rb +++ b/config/initializers/active_record_fix_insert_all.rb @@ -7,7 +7,7 @@ # This is covered by tests in `BulkInsertSafe` # that validates handling of different data types -if Rails.gem_version > Gem::Version.new("6.0.2") +if Rails.gem_version > Gem::Version.new("6.0.2.2") raise Gem::DependencyError, "Remove patch once the https://github.com/rails/rails/pull/38763 is included" end diff --git a/doc/development/documentation/styleguide.md b/doc/development/documentation/styleguide.md index aeda66eeb95..3431456363b 100644 --- a/doc/development/documentation/styleguide.md +++ b/doc/development/documentation/styleguide.md @@ -1244,6 +1244,20 @@ a helpful link back to how the feature was developed. NOTE: **Note:** Version text must be on its own line and surounded by blank lines to render correctly. +### Versions in the past or future + +When describing functionality available in past or future versions, use: + +- **Earlier**, and not **older** or **before**. +- **Later**, and not **newer** or **after**. + +For example: + +- Available in GitLab 12.3 and earlier. +- Available in GitLab 12.4 and later. +- If using GitLab 11.4 or earlier, ... +- If using GitLab 10.6 or later, ... + ### Importance of referencing GitLab versions and tiers Mentioning GitLab versions and tiers is important to all users and contributors diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md index abf194aae48..3a9f0ead2ba 100644 --- a/doc/user/application_security/dast/index.md +++ b/doc/user/application_security/dast/index.md @@ -608,6 +608,17 @@ Each scenario can be a third-level heading, e.g. `### Getting error message X`. If you have none to add when creating a doc, leave this section in place but commented out to help encourage others to add to it in the future. --> +## Optimizing DAST + +By default, DAST will download all artifacts defined by previous jobs in the pipeline. If +your DAST job does not rely on `environment_url.txt` to define the URL under test or any other files created +in previous jobs, we recommend you don't download artifacts. To avoid downloading artifacts, add the following to your `gitlab-ci.yml` file: + +```json +dast: + dependencies: [] +``` + ## Troubleshooting ### Running out of memory diff --git a/locale/gitlab.pot b/locale/gitlab.pot index f38491dcc18..0454e558daf 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -3639,9 +3639,6 @@ msgstr "" msgid "ChatMessage|and [%{count} more](%{pipeline_failed_jobs_url})" msgstr "" -msgid "ChatMessage|failed" -msgstr "" - msgid "ChatMessage|has failed" msgstr "" @@ -3657,9 +3654,6 @@ msgstr "" msgid "ChatMessage|in %{project_link}" msgstr "" -msgid "ChatMessage|passed" -msgstr "" - msgid "Check again" msgstr "" diff --git a/spec/models/project_services/chat_message/pipeline_message_spec.rb b/spec/models/project_services/chat_message/pipeline_message_spec.rb index e99148d1d1f..7c3e48f572a 100644 --- a/spec/models/project_services/chat_message/pipeline_message_spec.rb +++ b/spec/models/project_services/chat_message/pipeline_message_spec.rb @@ -55,475 +55,324 @@ describe ChatMessage::PipelineMessage do allow(Gitlab::UrlBuilder).to receive(:build).with(args[:user]).and_return("http://example.gitlab.com/hacker") end - context 'when the fancy_pipeline_slack_notifications feature flag is disabled' do + it 'returns an empty pretext' do + expect(subject.pretext).to be_empty + end + + it "returns the pipeline summary in the activity's title" do + expect(subject.activity[:title]).to eq( + "Pipeline [#123](http://example.gitlab.com/pipelines/123)" \ + " of branch [develop](http://example.gitlab.com/commits/develop)" \ + " by The Hacker (hacker) has passed" + ) + end + + context "when the pipeline failed" do before do - stub_feature_flags(fancy_pipeline_slack_notifications: false) + args[:object_attributes][:status] = 'failed' end - it 'returns an empty pretext' do - expect(subject.pretext).to be_empty - end - - it "returns the pipeline summary in the activity's title" do + it "returns the summary with a 'failed' status" do expect(subject.activity[:title]).to eq( "Pipeline [#123](http://example.gitlab.com/pipelines/123)" \ " of branch [develop](http://example.gitlab.com/commits/develop)" \ - " by The Hacker (hacker) passed" + " by The Hacker (hacker) has failed" ) end - - context "when the pipeline failed" do - before do - args[:object_attributes][:status] = 'failed' - end - - it "returns the summary with a 'failed' status" do - expect(subject.activity[:title]).to eq( - "Pipeline [#123](http://example.gitlab.com/pipelines/123)" \ - " of branch [develop](http://example.gitlab.com/commits/develop)" \ - " by The Hacker (hacker) failed" - ) - end - end - - context 'when no user is provided because the pipeline was triggered by the API' do - before do - args[:user] = nil - end - - it "returns the summary with 'API' as the username" do - expect(subject.activity[:title]).to eq( - "Pipeline [#123](http://example.gitlab.com/pipelines/123)" \ - " of branch [develop](http://example.gitlab.com/commits/develop)" \ - " by API passed" - ) - end - end - - it "returns a link to the project in the activity's subtitle" do - expect(subject.activity[:subtitle]).to eq("in [project_name](http://example.gitlab.com)") - end - - it "returns the build duration in the activity's text property" do - expect(subject.activity[:text]).to eq("in 02:00:10") - end - - it "returns the user's avatar image URL in the activity's image property" do - expect(subject.activity[:image]).to eq("http://example.com/avatar") - end - - context 'when the user does not have an avatar' do - before do - args[:user][:avatar_url] = nil - end - - it "returns an empty string in the activity's image property" do - expect(subject.activity[:image]).to be_empty - end - end - - it "returns the pipeline summary as the attachment's text property" do - expect(subject.attachments.first[:text]).to eq( - ":" \ - " Pipeline " \ - " of branch " \ - " by The Hacker (hacker) passed in 02:00:10" - ) - end - - it "returns 'good' as the attachment's color property" do - expect(subject.attachments.first[:color]).to eq('good') - end - - context "when the pipeline failed" do - before do - args[:object_attributes][:status] = 'failed' - end - - it "returns 'danger' as the attachment's color property" do - expect(subject.attachments.first[:color]).to eq('danger') - end - end - - context 'when rendering markdown' do - before do - args[:markdown] = true - end - - it 'returns the pipeline summary as the attachments in markdown format' do - expect(subject.attachments).to eq( - "[project_name](http://example.gitlab.com):" \ - " Pipeline [#123](http://example.gitlab.com/pipelines/123)" \ - " of branch [develop](http://example.gitlab.com/commits/develop)" \ - " by The Hacker (hacker) passed in 02:00:10" - ) - end - end - - context 'when ref type is tag' do - before do - args[:object_attributes][:tag] = true - args[:object_attributes][:ref] = 'new_tag' - end - - it "returns the pipeline summary in the activity's title" do - expect(subject.activity[:title]).to eq( - "Pipeline [#123](http://example.gitlab.com/pipelines/123)" \ - " of tag [new_tag](http://example.gitlab.com/-/tags/new_tag)" \ - " by The Hacker (hacker) passed" - ) - end - - it "returns the pipeline summary as the attachment's text property" do - expect(subject.attachments.first[:text]).to eq( - ":" \ - " Pipeline " \ - " of tag " \ - " by The Hacker (hacker) passed in 02:00:10" - ) - end - - context 'when rendering markdown' do - before do - args[:markdown] = true - end - - it 'returns the pipeline summary as the attachments in markdown format' do - expect(subject.attachments).to eq( - "[project_name](http://example.gitlab.com):" \ - " Pipeline [#123](http://example.gitlab.com/pipelines/123)" \ - " of tag [new_tag](http://example.gitlab.com/-/tags/new_tag)" \ - " by The Hacker (hacker) passed in 02:00:10" - ) - end - end - end end - context 'when the fancy_pipeline_slack_notifications feature flag is enabled' do + context "when the pipeline passed with warnings" do before do - stub_feature_flags(fancy_pipeline_slack_notifications: true) + args[:object_attributes][:detailed_status] = 'passed with warnings' end - it 'returns an empty pretext' do - expect(subject.pretext).to be_empty - end - - it "returns the pipeline summary in the activity's title" do + it "returns the summary with a 'passed with warnings' status" do expect(subject.activity[:title]).to eq( "Pipeline [#123](http://example.gitlab.com/pipelines/123)" \ " of branch [develop](http://example.gitlab.com/commits/develop)" \ - " by The Hacker (hacker) has passed" + " by The Hacker (hacker) has passed with warnings" ) end + end - context "when the pipeline failed" do - before do - args[:object_attributes][:status] = 'failed' - end - - it "returns the summary with a 'failed' status" do - expect(subject.activity[:title]).to eq( - "Pipeline [#123](http://example.gitlab.com/pipelines/123)" \ - " of branch [develop](http://example.gitlab.com/commits/develop)" \ - " by The Hacker (hacker) has failed" - ) - end + context 'when no user is provided because the pipeline was triggered by the API' do + before do + args[:user] = nil end - context "when the pipeline passed with warnings" do - before do - args[:object_attributes][:detailed_status] = 'passed with warnings' - end - - it "returns the summary with a 'passed with warnings' status" do - expect(subject.activity[:title]).to eq( - "Pipeline [#123](http://example.gitlab.com/pipelines/123)" \ - " of branch [develop](http://example.gitlab.com/commits/develop)" \ - " by The Hacker (hacker) has passed with warnings" - ) - end - end - - context 'when no user is provided because the pipeline was triggered by the API' do - before do - args[:user] = nil - end - - it "returns the summary with 'API' as the username" do - expect(subject.activity[:title]).to eq( - "Pipeline [#123](http://example.gitlab.com/pipelines/123)" \ - " of branch [develop](http://example.gitlab.com/commits/develop)" \ - " by API has passed" - ) - end - end - - it "returns a link to the project in the activity's subtitle" do - expect(subject.activity[:subtitle]).to eq("in [project_name](http://example.gitlab.com)") - end - - it "returns the build duration in the activity's text property" do - expect(subject.activity[:text]).to eq("in 02:00:10") - end - - it "returns the user's avatar image URL in the activity's image property" do - expect(subject.activity[:image]).to eq("http://example.com/avatar") - end - - context 'when the user does not have an avatar' do - before do - args[:user][:avatar_url] = nil - end - - it "returns an empty string in the activity's image property" do - expect(subject.activity[:image]).to be_empty - end - end - - it "returns the pipeline summary as the attachment's fallback property" do - expect(subject.attachments.first[:fallback]).to eq( - ":" \ - " Pipeline " \ - " of branch " \ - " by The Hacker (hacker) has passed in 02:00:10" + it "returns the summary with 'API' as the username" do + expect(subject.activity[:title]).to eq( + "Pipeline [#123](http://example.gitlab.com/pipelines/123)" \ + " of branch [develop](http://example.gitlab.com/commits/develop)" \ + " by API has passed" ) end + end - it "returns 'good' as the attachment's color property" do - expect(subject.attachments.first[:color]).to eq('good') + it "returns a link to the project in the activity's subtitle" do + expect(subject.activity[:subtitle]).to eq("in [project_name](http://example.gitlab.com)") + end + + it "returns the build duration in the activity's text property" do + expect(subject.activity[:text]).to eq("in 02:00:10") + end + + it "returns the user's avatar image URL in the activity's image property" do + expect(subject.activity[:image]).to eq("http://example.com/avatar") + end + + context 'when the user does not have an avatar' do + before do + args[:user][:avatar_url] = nil end - context "when the pipeline failed" do - before do - args[:object_attributes][:status] = 'failed' - end + it "returns an empty string in the activity's image property" do + expect(subject.activity[:image]).to be_empty + end + end - it "returns 'danger' as the attachment's color property" do - expect(subject.attachments.first[:color]).to eq('danger') - end + it "returns the pipeline summary as the attachment's fallback property" do + expect(subject.attachments.first[:fallback]).to eq( + ":" \ + " Pipeline " \ + " of branch " \ + " by The Hacker (hacker) has passed in 02:00:10" + ) + end + + it "returns 'good' as the attachment's color property" do + expect(subject.attachments.first[:color]).to eq('good') + end + + context "when the pipeline failed" do + before do + args[:object_attributes][:status] = 'failed' end - context "when the pipeline passed with warnings" do - before do - args[:object_attributes][:detailed_status] = 'passed with warnings' - end + it "returns 'danger' as the attachment's color property" do + expect(subject.attachments.first[:color]).to eq('danger') + end + end - it "returns 'warning' as the attachment's color property" do - expect(subject.attachments.first[:color]).to eq('warning') - end + context "when the pipeline passed with warnings" do + before do + args[:object_attributes][:detailed_status] = 'passed with warnings' + end + + it "returns 'warning' as the attachment's color property" do + expect(subject.attachments.first[:color]).to eq('warning') + end + end + + it "returns the committer's name and username as the attachment's author_name property" do + expect(subject.attachments.first[:author_name]).to eq('The Hacker (hacker)') + end + + it "returns the committer's avatar URL as the attachment's author_icon property" do + expect(subject.attachments.first[:author_icon]).to eq('http://example.com/avatar') + end + + it "returns the committer's GitLab profile URL as the attachment's author_link property" do + expect(subject.attachments.first[:author_link]).to eq('http://example.gitlab.com/hacker') + end + + context 'when no user is provided because the pipeline was triggered by the API' do + before do + args[:user] = nil end it "returns the committer's name and username as the attachment's author_name property" do - expect(subject.attachments.first[:author_name]).to eq('The Hacker (hacker)') + expect(subject.attachments.first[:author_name]).to eq('API') end - it "returns the committer's avatar URL as the attachment's author_icon property" do - expect(subject.attachments.first[:author_icon]).to eq('http://example.com/avatar') + it "returns nil as the attachment's author_icon property" do + expect(subject.attachments.first[:author_icon]).to be_nil end - it "returns the committer's GitLab profile URL as the attachment's author_link property" do - expect(subject.attachments.first[:author_link]).to eq('http://example.gitlab.com/hacker') + it "returns nil as the attachment's author_link property" do + expect(subject.attachments.first[:author_link]).to be_nil + end + end + + it "returns the pipeline ID, status, and duration as the attachment's title property" do + expect(subject.attachments.first[:title]).to eq("Pipeline #123 has passed in 02:00:10") + end + + it "returns the pipeline URL as the attachment's title_link property" do + expect(subject.attachments.first[:title_link]).to eq("http://example.gitlab.com/pipelines/123") + end + + it "returns two attachment fields" do + expect(subject.attachments.first[:fields].count).to eq(2) + end + + it "returns the commit message as the attachment's second field property" do + expect(subject.attachments.first[:fields][0]).to eq({ + title: "Branch", + value: "", + short: true + }) + end + + it "returns the ref name and link as the attachment's second field property" do + expect(subject.attachments.first[:fields][1]).to eq({ + title: "Commit", + value: "", + short: true + }) + end + + context "when a job in the pipeline fails" do + before do + args[:builds] = [ + { id: 1, name: "rspec", status: "failed", stage: "test" }, + { id: 2, name: "karma", status: "success", stage: "test" } + ] end - context 'when no user is provided because the pipeline was triggered by the API' do - before do - args[:user] = nil - end - - it "returns the committer's name and username as the attachment's author_name property" do - expect(subject.attachments.first[:author_name]).to eq('API') - end - - it "returns nil as the attachment's author_icon property" do - expect(subject.attachments.first[:author_icon]).to be_nil - end - - it "returns nil as the attachment's author_link property" do - expect(subject.attachments.first[:author_link]).to be_nil - end + it "returns four attachment fields" do + expect(subject.attachments.first[:fields].count).to eq(4) end - it "returns the pipeline ID, status, and duration as the attachment's title property" do - expect(subject.attachments.first[:title]).to eq("Pipeline #123 has passed in 02:00:10") - end - - it "returns the pipeline URL as the attachment's title_link property" do - expect(subject.attachments.first[:title_link]).to eq("http://example.gitlab.com/pipelines/123") - end - - it "returns two attachment fields" do - expect(subject.attachments.first[:fields].count).to eq(2) - end - - it "returns the commit message as the attachment's second field property" do - expect(subject.attachments.first[:fields][0]).to eq({ - title: "Branch", - value: "", + it "returns the stage name and link to the 'Failed jobs' tab on the pipeline's page as the attachment's third field property" do + expect(subject.attachments.first[:fields][2]).to eq({ + title: "Failed stage", + value: "", short: true }) end - it "returns the ref name and link as the attachment's second field property" do - expect(subject.attachments.first[:fields][1]).to eq({ - title: "Commit", - value: "", + it "returns the job name and link as the attachment's fourth field property" do + expect(subject.attachments.first[:fields][3]).to eq({ + title: "Failed job", + value: "", + short: true + }) + end + end + + context "when lots of jobs across multiple stages fail" do + before do + args[:builds] = (1..25).map do |i| + { id: i, name: "job-#{i}", status: "failed", stage: "stage-" + ((i % 3) + 1).to_s } + end + end + + it "returns the stage names and links to the 'Failed jobs' tab on the pipeline's page as the attachment's third field property" do + expect(subject.attachments.first[:fields][2]).to eq({ + title: "Failed stages", + value: ", , ", short: true }) end - context "when a job in the pipeline fails" do - before do - args[:builds] = [ - { id: 1, name: "rspec", status: "failed", stage: "test" }, - { id: 2, name: "karma", status: "success", stage: "test" } - ] + it "returns the job names and links as the attachment's fourth field property" do + expected_jobs = 25.downto(16).map do |i| + "" end - it "returns four attachment fields" do - expect(subject.attachments.first[:fields].count).to eq(4) - end + expected_jobs << "and " - it "returns the stage name and link to the 'Failed jobs' tab on the pipeline's page as the attachment's third field property" do - expect(subject.attachments.first[:fields][2]).to eq({ - title: "Failed stage", - value: "", - short: true - }) - end + expect(subject.attachments.first[:fields][3]).to eq({ + title: "Failed jobs", + value: expected_jobs.join(", "), + short: true + }) + end + end - it "returns the job name and link as the attachment's fourth field property" do - expect(subject.attachments.first[:fields][3]).to eq({ - title: "Failed job", - value: "", - short: true - }) - end + context "when jobs succeed on retries" do + before do + args[:builds] = [ + { id: 1, name: "job-1", status: "failed", stage: "stage-1" }, + { id: 2, name: "job-2", status: "failed", stage: "stage-2" }, + { id: 3, name: "job-3", status: "failed", stage: "stage-3" }, + { id: 7, name: "job-1", status: "failed", stage: "stage-1" }, + { id: 8, name: "job-1", status: "success", stage: "stage-1" } + ] end - context "when lots of jobs across multiple stages fail" do - before do - args[:builds] = (1..25).map do |i| - { id: i, name: "job-#{i}", status: "failed", stage: "stage-" + ((i % 3) + 1).to_s } - end - end + it "do not return a job which succeeded on retry" do + expected_jobs = [ + "", + "" + ] - it "returns the stage names and links to the 'Failed jobs' tab on the pipeline's page as the attachment's third field property" do - expect(subject.attachments.first[:fields][2]).to eq({ - title: "Failed stages", - value: ", , ", - short: true - }) - end + expect(subject.attachments.first[:fields][3]).to eq( + title: "Failed jobs", + value: expected_jobs.join(", "), + short: true + ) + end + end - it "returns the job names and links as the attachment's fourth field property" do - expected_jobs = 25.downto(16).map do |i| - "" - end - - expected_jobs << "and " - - expect(subject.attachments.first[:fields][3]).to eq({ - title: "Failed jobs", - value: expected_jobs.join(", "), - short: true - }) - end + context "when jobs failed even on retries" do + before do + args[:builds] = [ + { id: 1, name: "job-1", status: "failed", stage: "stage-1" }, + { id: 2, name: "job-2", status: "failed", stage: "stage-2" }, + { id: 3, name: "job-3", status: "failed", stage: "stage-3" }, + { id: 7, name: "job-1", status: "failed", stage: "stage-1" }, + { id: 8, name: "job-1", status: "failed", stage: "stage-1" } + ] end - context "when jobs succeed on retries" do - before do - args[:builds] = [ - { id: 1, name: "job-1", status: "failed", stage: "stage-1" }, - { id: 2, name: "job-2", status: "failed", stage: "stage-2" }, - { id: 3, name: "job-3", status: "failed", stage: "stage-3" }, - { id: 7, name: "job-1", status: "failed", stage: "stage-1" }, - { id: 8, name: "job-1", status: "success", stage: "stage-1" } - ] - end + it "returns only first instance of the failed job" do + expected_jobs = [ + "", + "", + "" + ] - it "do not return a job which succeeded on retry" do - expected_jobs = [ - "", - "" - ] + expect(subject.attachments.first[:fields][3]).to eq( + title: "Failed jobs", + value: expected_jobs.join(", "), + short: true + ) + end + end - expect(subject.attachments.first[:fields][3]).to eq( - title: "Failed jobs", - value: expected_jobs.join(", "), - short: true - ) - end + context "when the CI config file contains a YAML error" do + let(:has_yaml_errors) { true } + + it "returns three attachment fields" do + expect(subject.attachments.first[:fields].count).to eq(3) end - context "when jobs failed even on retries" do - before do - args[:builds] = [ - { id: 1, name: "job-1", status: "failed", stage: "stage-1" }, - { id: 2, name: "job-2", status: "failed", stage: "stage-2" }, - { id: 3, name: "job-3", status: "failed", stage: "stage-3" }, - { id: 7, name: "job-1", status: "failed", stage: "stage-1" }, - { id: 8, name: "job-1", status: "failed", stage: "stage-1" } - ] - end + it "returns the YAML error deatils as the attachment's third field property" do + expect(subject.attachments.first[:fields][2]).to eq({ + title: "Invalid CI config YAML file", + value: "yaml error description here", + short: false + }) + end + end - it "returns only first instance of the failed job" do - expected_jobs = [ - "", - "", - "" - ] + it "returns the project's name as the attachment's footer property" do + expect(subject.attachments.first[:footer]).to eq("project_name") + end - expect(subject.attachments.first[:fields][3]).to eq( - title: "Failed jobs", - value: expected_jobs.join(", "), - short: true - ) - end + it "returns the project's avatar URL as the attachment's footer_icon property" do + expect(subject.attachments.first[:footer_icon]).to eq("http://example.com/project_avatar") + end + + it "returns the pipeline's timestamp as the attachment's ts property" do + expected_ts = Time.parse(args[:object_attributes][:finished_at]).to_i + expect(subject.attachments.first[:ts]).to eq(expected_ts) + end + + context 'when rendering markdown' do + before do + args[:markdown] = true end - context "when the CI config file contains a YAML error" do - let(:has_yaml_errors) { true } - - it "returns three attachment fields" do - expect(subject.attachments.first[:fields].count).to eq(3) - end - - it "returns the YAML error deatils as the attachment's third field property" do - expect(subject.attachments.first[:fields][2]).to eq({ - title: "Invalid CI config YAML file", - value: "yaml error description here", - short: false - }) - end - end - - it "returns the project's name as the attachment's footer property" do - expect(subject.attachments.first[:footer]).to eq("project_name") - end - - it "returns the project's avatar URL as the attachment's footer_icon property" do - expect(subject.attachments.first[:footer_icon]).to eq("http://example.com/project_avatar") - end - - it "returns the pipeline's timestamp as the attachment's ts property" do - expected_ts = Time.parse(args[:object_attributes][:finished_at]).to_i - expect(subject.attachments.first[:ts]).to eq(expected_ts) - end - - context 'when rendering markdown' do - before do - args[:markdown] = true - end - - it 'returns the pipeline summary as the attachments in markdown format' do - expect(subject.attachments).to eq( - "[project_name](http://example.gitlab.com):" \ - " Pipeline [#123](http://example.gitlab.com/pipelines/123)" \ - " of branch [develop](http://example.gitlab.com/commits/develop)" \ - " by The Hacker (hacker) has passed in 02:00:10" - ) - end + it 'returns the pipeline summary as the attachments in markdown format' do + expect(subject.attachments).to eq( + "[project_name](http://example.gitlab.com):" \ + " Pipeline [#123](http://example.gitlab.com/pipelines/123)" \ + " of branch [develop](http://example.gitlab.com/commits/develop)" \ + " by The Hacker (hacker) has passed in 02:00:10" + ) end end end