summaryrefslogtreecommitdiff
path: root/qa/qa/specs/features/browser_ui/1_manage/integrations/pipeline_status_emails_spec.rb
blob: 4495d83f33649302f27dc39987eed42d3082ce42 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# frozen_string_literal: true

module QA
  RSpec.shared_examples 'notifies on a pipeline' do |exit_code|
    before do
      push_commit(exit_code: exit_code)
    end

    it 'sends an email' do
      meta = exit_code_meta(exit_code)

      project.visit!
      Flow::Pipeline.wait_for_latest_pipeline(status: meta[:status])

      messages = mail_hog_messages(mail_hog)
      subjects = messages.map(&:subject)
      targets = messages.map(&:to)

      aggregate_failures do
        expect(subjects).to include(meta[:email_subject])
        expect(subjects).to include(/#{Regexp.escape(project.name)}/)
        expect(targets).to include(*emails)
      end
    end
  end

  RSpec.describe 'Manage', :orchestrated, :runner, :requires_admin, :smtp, product_group: :integrations do
    describe 'Pipeline status emails' do
      let(:executor) { "qa-runner-#{Time.now.to_i}" }
      let(:emails) { %w[foo@bar.com baz@buzz.com] }

      let(:project) do
        Resource::Project.fabricate_via_api! do |project|
          project.name = 'pipeline-status-project'
        end
      end

      let!(:runner) do
        Resource::Runner.fabricate! do |runner|
          runner.project = project
          runner.name = executor
          runner.tags = [executor]
        end
      end

      let(:mail_hog) { Vendor::MailHog::API.new }

      before(:all) do
        Runtime::ApplicationSettings.set_application_settings(allow_local_requests_from_web_hooks_and_services: true)
      end

      before do
        setup_pipeline_emails(emails)
      end

      describe 'when pipeline passes', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/366240' do
        include_examples 'notifies on a pipeline', 0
      end

      describe 'when pipeline fails', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/366241' do
        include_examples 'notifies on a pipeline', 1
      end

      def push_commit(exit_code: 0)
        Resource::Repository::Commit.fabricate_via_api! do |commit|
          commit.project = project
          commit.commit_message = 'Add .gitlab-ci.yml'
          commit.add_files(
            [
              {
                file_path: '.gitlab-ci.yml',
                content: gitlab_ci_yaml(exit_code: exit_code)
              }
            ]
          )
        end
      end

      def setup_pipeline_emails(emails)
        page.visit Runtime::Scenario.gitlab_address
        Flow::Login.sign_in_unless_signed_in

        project.visit!

        Page::Project::Menu.perform(&:go_to_integrations_settings)
        QA::Page::Project::Settings::Integrations.perform(&:click_pipelines_email_link)

        QA::Page::Project::Settings::Services::PipelineStatusEmails.perform do |pipeline_status_emails|
          pipeline_status_emails.toggle_notify_broken_pipelines # notify on pass and fail
          pipeline_status_emails.set_recipients(emails)
          pipeline_status_emails.click_save_button
        end
      end

      def gitlab_ci_yaml(exit_code: 0, tag: executor)
        <<~YAML
          test-pipeline-email:
            tags:
              - #{tag}
            script: sleep 5; exit #{exit_code};
        YAML
      end

      private

      def exit_code_meta(exit_code)
        {
          0 => { status: 'passed', email_subject: /Successful pipeline/ },
          1 => { status: 'failed', email_subject: /Failed pipeline/ }
        }[exit_code]
      end

      def mail_hog_messages(mail_hog_api)
        Support::Retrier.retry_until(sleep_interval: 1) do
          Runtime::Logger.debug('Fetching email...')

          messages = mail_hog_api.fetch_messages
          logs = messages.map { |m| "#{m.to}: #{m.subject}" }

          Runtime::Logger.debug("MailHog Logs: #{logs.join("\n")}")

          # for failing pipelines we have three messages
          # one for the owner
          # and one for each recipient
          messages if mail_hog_pipeline_count(messages) >= 2
        end
      end

      def mail_hog_pipeline_count(messages)
        messages.count { |message| message.subject.include?('pipeline') }
      end
    end
  end
end