1# frozen_string_literal: true
2
3module QA
4  RSpec.describe 'Create', :requires_admin, :skip_live_env, quarantine: { issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/195179', type: :flaky } do
5    describe 'Jenkins integration' do
6      let(:project_name) { "project_with_jenkins_#{SecureRandom.hex(4)}" }
7
8      let(:project) do
9        Resource::Project.fabricate_via_api! do |project|
10          project.name = project_name
11          project.initialize_with_readme = true
12          project.auto_devops_enabled = false
13        end
14      end
15
16      before do
17        jenkins_server = run_jenkins_server
18
19        Vendor::Jenkins::Page::Base.host = jenkins_server.host_address
20
21        Runtime::Env.personal_access_token ||= fabricate_personal_access_token
22
23        allow_requests_to_local_networks
24
25        setup_jenkins
26      end
27
28      it 'integrates and displays build status for MR pipeline in GitLab', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347788' do
29        login_to_gitlab
30
31        setup_project_integration_with_jenkins
32
33        expect(page).to have_text("Jenkins CI activated.")
34
35        QA::Support::Retrier.retry_on_exception do
36          Resource::Repository::ProjectPush.fabricate! do |push|
37            push.project = project
38            push.new_branch = false
39            push.file_name = "file_#{SecureRandom.hex(4)}.txt"
40          end
41
42          Vendor::Jenkins::Page::LastJobConsole.perform do |job_console|
43            job_console.job_name = project_name
44
45            job_console.visit!
46
47            Support::Waiter.wait_until(sleep_interval: 2, reload_page: page) do
48              job_console.has_successful_build? && job_console.no_failed_status_update?
49            end
50          end
51
52          project.visit!
53
54          Flow::Pipeline.visit_latest_pipeline
55
56          Page::Project::Pipeline::Show.perform do |show|
57            expect(show).to have_build('jenkins', status: :success, wait: 15)
58          end
59        end
60      end
61
62      after do
63        remove_jenkins_server
64      end
65
66      def setup_jenkins
67        Vendor::Jenkins::Page::Login.perform do |login_page|
68          login_page.visit!
69          login_page.login
70        end
71
72        token_description = "token-#{SecureRandom.hex(8)}"
73
74        Vendor::Jenkins::Page::NewCredentials.perform do |new_credentials|
75          new_credentials.visit_and_set_gitlab_api_token(Runtime::Env.personal_access_token, token_description)
76        end
77
78        Vendor::Jenkins::Page::Configure.perform do |configure|
79          configure.visit_and_setup_gitlab_connection(patch_host_name(Runtime::Scenario.gitlab_address, 'gitlab'), token_description) do
80            configure.click_test_connection
81            expect(configure).to have_success
82          end
83        end
84
85        Vendor::Jenkins::Page::NewJob.perform do |new_job|
86          new_job.visit_and_create_new_job_with_name(project_name)
87        end
88
89        Vendor::Jenkins::Page::ConfigureJob.perform do |configure_job|
90          configure_job.job_name = project_name
91          configure_job.configure(scm_url: patch_host_name(project.repository_http_location.git_uri, 'gitlab'))
92        end
93      end
94
95      def run_jenkins_server
96        Service::DockerRun::Jenkins.new.tap do |runner|
97          runner.pull
98          runner.register!
99        end
100      end
101
102      def remove_jenkins_server
103        Service::DockerRun::Jenkins.new.remove!
104      end
105
106      def fabricate_personal_access_token
107        login_to_gitlab
108
109        token = Resource::PersonalAccessToken.fabricate!.token
110        Page::Main::Menu.perform(&:sign_out)
111        token
112      end
113
114      def login_to_gitlab
115        Flow::Login.sign_in
116      end
117
118      def patch_host_name(host_name, container_name)
119        return host_name unless host_name.include?('localhost')
120
121        ip_address = `docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' #{container_name}`.strip
122        host_name.gsub('localhost', ip_address)
123      end
124
125      def setup_project_integration_with_jenkins
126        project.visit!
127
128        Page::Project::Menu.perform(&:click_project)
129        Page::Project::Menu.perform(&:go_to_integrations_settings)
130        Page::Project::Settings::Integrations.perform(&:click_jenkins_ci_link)
131
132        QA::Page::Project::Settings::Services::Jenkins.perform do |jenkins|
133          jenkins.setup_service_with(jenkins_url: patch_host_name(Vendor::Jenkins::Page::Base.host, 'jenkins-server'),
134            project_name: project_name)
135        end
136      end
137
138      def allow_requests_to_local_networks
139        Page::Main::Menu.perform(&:sign_out_if_signed_in)
140        Flow::Login.sign_in_as_admin
141        Page::Main::Menu.perform(&:go_to_admin_area)
142        Page::Admin::Menu.perform(&:go_to_network_settings)
143
144        Page::Admin::Settings::Network.perform do |network|
145          network.expand_outbound_requests do |outbound_requests|
146            outbound_requests.allow_requests_to_local_network_from_services
147          end
148        end
149
150        Page::Main::Menu.perform(&:sign_out)
151      end
152    end
153  end
154end
155