Commit f8e7ad51 authored by Mark Lapierre's avatar Mark Lapierre

Merge branch 'acunskis-qa-octokit' into 'master'

E2E: Replace github_api gem with octokit

See merge request gitlab-org/gitlab!66066
parents 7c55cc72 96b5bc73
...@@ -22,7 +22,7 @@ gem 'rotp', '~> 3.1.0' ...@@ -22,7 +22,7 @@ gem 'rotp', '~> 3.1.0'
gem 'timecop', '~> 0.9.1' gem 'timecop', '~> 0.9.1'
gem 'parallel', '~> 1.19' gem 'parallel', '~> 1.19'
gem 'rspec-parameterized', '~> 0.4.2' gem 'rspec-parameterized', '~> 0.4.2'
gem 'github_api', '~> 0.18.2' gem "octokit", "~> 4.21"
gem "webdrivers", "~> 4.6" gem "webdrivers", "~> 4.6"
gem 'chemlab', '~> 0.7' gem 'chemlab', '~> 0.7'
......
...@@ -56,31 +56,36 @@ GEM ...@@ -56,31 +56,36 @@ GEM
adamantium (~> 0.2.0) adamantium (~> 0.2.0)
equalizer (~> 0.0.9) equalizer (~> 0.0.9)
concurrent-ruby (1.1.9) concurrent-ruby (1.1.9)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
diff-lcs (1.3) diff-lcs (1.3)
domain_name (0.5.20190701) domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0) unf (>= 0.0.5, < 1.0.0)
equalizer (0.0.11) equalizer (0.0.11)
faker (1.9.3) faker (1.9.3)
i18n (>= 0.7) i18n (>= 0.7)
faraday (0.17.3) faraday (1.5.1)
faraday-em_http (~> 1.0)
faraday-em_synchrony (~> 1.0)
faraday-excon (~> 1.1)
faraday-httpclient (~> 1.0.1)
faraday-net_http (~> 1.0)
faraday-net_http_persistent (~> 1.1)
faraday-patron (~> 1.0)
multipart-post (>= 1.2, < 3) multipart-post (>= 1.2, < 3)
github_api (0.18.2) ruby2_keywords (>= 0.0.4)
addressable (~> 2.4) faraday-em_http (1.0.0)
descendants_tracker (~> 0.0.4) faraday-em_synchrony (1.0.0)
faraday (~> 0.8) faraday-excon (1.1.0)
hashie (~> 3.5, >= 3.5.2) faraday-httpclient (1.0.1)
oauth2 (~> 1.0) faraday-net_http (1.0.1)
faraday-net_http_persistent (1.2.0)
faraday-patron (1.0.0)
gitlab-qa (4.0.0) gitlab-qa (4.0.0)
hashie (3.6.0)
http-accept (1.7.0) http-accept (1.7.0)
http-cookie (1.0.3) http-cookie (1.0.3)
domain_name (~> 0.5) domain_name (~> 0.5)
i18n (1.8.10) i18n (1.8.10)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
ice_nine (0.11.2) ice_nine (0.11.2)
jwt (2.2.2)
knapsack (1.17.1) knapsack (1.17.1)
rake rake
launchy (2.4.3) launchy (2.4.3)
...@@ -96,19 +101,14 @@ GEM ...@@ -96,19 +101,14 @@ GEM
mini_mime (1.0.2) mini_mime (1.0.2)
mini_portile2 (2.5.0) mini_portile2 (2.5.0)
minitest (5.14.4) minitest (5.14.4)
multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.1.1) multipart-post (2.1.1)
netrc (0.11.0) netrc (0.11.0)
nokogiri (1.11.1) nokogiri (1.11.1)
mini_portile2 (~> 2.5.0) mini_portile2 (~> 2.5.0)
racc (~> 1.4) racc (~> 1.4)
oauth2 (1.4.4) octokit (4.21.0)
faraday (>= 0.8, < 2.0) faraday (>= 0.9)
jwt (>= 1.0, < 3.0) sawyer (~> 0.8.0, >= 0.5.3)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
oj (3.11.5) oj (3.11.5)
parallel (1.19.2) parallel (1.19.2)
parallel_tests (2.29.0) parallel_tests (2.29.0)
...@@ -166,7 +166,11 @@ GEM ...@@ -166,7 +166,11 @@ GEM
rspec-core (>= 2, < 4, != 2.12.0) rspec-core (>= 2, < 4, != 2.12.0)
ruby-debug-ide (0.7.2) ruby-debug-ide (0.7.2)
rake (>= 0.8.1) rake (>= 0.8.1)
ruby2_keywords (0.0.4)
rubyzip (2.3.2) rubyzip (2.3.2)
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
selenium-webdriver (4.0.0.beta4) selenium-webdriver (4.0.0.beta4)
childprocess (>= 0.5, < 5.0) childprocess (>= 0.5, < 5.0)
rexml (~> 3.2) rexml (~> 3.2)
...@@ -212,10 +216,10 @@ DEPENDENCIES ...@@ -212,10 +216,10 @@ DEPENDENCIES
chemlab (~> 0.7) chemlab (~> 0.7)
chemlab-library-www-gitlab-com (~> 0.1) chemlab-library-www-gitlab-com (~> 0.1)
faker (~> 1.6, >= 1.6.6) faker (~> 1.6, >= 1.6.6)
github_api (~> 0.18.2)
gitlab-qa gitlab-qa
knapsack (~> 1.17) knapsack (~> 1.17)
nokogiri (~> 1.11.1) nokogiri (~> 1.11.1)
octokit (~> 4.21)
parallel (~> 1.19) parallel (~> 1.19)
parallel_tests (~> 2.29) parallel_tests (~> 2.29)
pry-byebug (~> 3.5.1) pry-byebug (~> 3.5.1)
......
...@@ -48,7 +48,7 @@ module QA ...@@ -48,7 +48,7 @@ module QA
end end
def mirror_direction=(value) def mirror_direction=(value)
raise ArgumentError, "Mirror direction must be 'Push' or 'Pull'" unless %w(Push Pull).include? value raise ArgumentError, "Mirror direction must be 'Push' or 'Pull'" unless %w[Push Pull].include?(value)
select_element(:mirror_direction, value) select_element(:mirror_direction, value)
...@@ -59,7 +59,9 @@ module QA ...@@ -59,7 +59,9 @@ module QA
end end
def authentication_method=(value) def authentication_method=(value)
raise ArgumentError, "Authentication method must be 'SSH public key', 'Password', or 'None'" unless %w(Password None SSH\ public\ key).include? value unless %w[Password None SSH\ public\ key].include?(value)
raise ArgumentError, "Authentication method must be 'SSH public key', 'Password', or 'None'"
end
select_element(:authentication_method, value) select_element(:authentication_method, value)
end end
...@@ -129,4 +131,7 @@ module QA ...@@ -129,4 +131,7 @@ module QA
end end
end end
QA::Page::Project::Settings::MirroringRepositories.prepend_mod_with('Page::Project::Settings::MirroringRepositories', namespace: QA) QA::Page::Project::Settings::MirroringRepositories.prepend_mod_with( # rubocop:disable Cop/InjectEnterpriseEditionModule
'Page::Project::Settings::MirroringRepositories',
namespace: QA
)
# frozen_string_literal: true # frozen_string_literal: true
require 'github_api' require 'octokit'
module QA module QA
module Resource module Resource
class ProjectImportedFromGithub < Resource::Project class ProjectImportedFromGithub < Resource::Project
attribute :github_repo_id do attribute :github_repo_id do
github_repository_path.split('/').yield_self do |path| github_client.repository(github_repository_path).id
github_client.repos.get(user: path[0], repo: path[1]).id
end
end end
def fabricate! def fabricate!
...@@ -42,6 +40,10 @@ module QA ...@@ -42,6 +40,10 @@ module QA
'/import/github' '/import/github'
end end
def api_trigger_mirror_pull_path
"#{api_get_path}/mirror/pull"
end
def api_post_body def api_post_body
{ {
repo_id: github_repo_id, repo_id: github_repo_id,
...@@ -56,13 +58,24 @@ module QA ...@@ -56,13 +58,24 @@ module QA
api_resource api_resource
end end
def trigger_project_mirror
Runtime::Logger.info "Triggering pull mirror request"
Support::Retrier.retry_until(max_attempts: 6, sleep_interval: 10) do
response = post(request_url(api_trigger_mirror_pull_path), nil)
Runtime::Logger.info "Mirror pull request response: #{response}"
response.code == Support::Api::HTTP_STATUS_OK
end
end
private private
# Github client # Github client
# #
# @return [Github::Client] # @return [Octokit::Client]
def github_client def github_client
@github_client ||= Github.new(oauth_token: github_personal_access_token) @github_client ||= Octokit::Client.new(access_token: github_personal_access_token)
end end
end end
end end
......
# frozen_string_literal: true # frozen_string_literal: true
require 'github_api' require 'octokit'
require 'faker' require 'faker'
require 'base64' require 'base64'
module QA module QA
context 'Verify', :github, :requires_admin, only: { subdomain: :staging } do describe 'Verify', :github, :requires_admin, only: { subdomain: :staging } do
include Support::Api
describe 'Pipeline for project mirrors Github' do describe 'Pipeline for project mirrors Github' do
let(:commit_message) { "Update #{github_data[:file_name]} - #{Time.now}" } let(:commit_message) { "Update #{github_data[:file_name]} - #{Time.now}" }
let(:project_name) { 'github-project-with-pipeline' } let(:project_name) { 'github-project-with-pipeline' }
let(:github_client) { Github::Client::Repos::Contents.new oauth_token: github_data[:access_token] } let(:github_client) { Octokit::Client.new(access_token: github_data[:access_token]) }
let(:admin_api_client) { Runtime::API::Client.as_admin } let(:admin_api_client) { Runtime::API::Client.as_admin }
let(:user_api_client) { Runtime::API::Client.new(:gitlab, user: user) } let(:user_api_client) { Runtime::API::Client.new(:gitlab, user: user) }
let(:github_data) do
{
access_token: Runtime::Env.github_access_token,
file_name: 'text_file.txt',
repo: 'gitlab-qa-github/test-project'
}
end
let(:group) do let(:group) do
Resource::Group.fabricate_via_api! Resource::Group.fabricate_via_api! do |resource|
resource.api_client = admin_api_client
end
end end
let(:user) do let(:user) do
...@@ -26,12 +33,14 @@ module QA ...@@ -26,12 +33,14 @@ module QA
end end
end end
let(:import_project) do let(:imported_project) do
EE::Resource::ImportRepoWithCiCd.fabricate_via_browser_ui! do |project| EE::Resource::ImportRepoWithCiCd.fabricate_via_browser_ui! do |project|
project.import = true project.import = true
project.name = project_name project.name = project_name
project.group = group
project.github_personal_access_token = github_data[:access_token] project.github_personal_access_token = github_data[:access_token]
project.github_repository_path = github_data[:repo_name] project.github_repository_path = github_data[:repo]
project.api_client = user_api_client
end end
end end
...@@ -39,81 +48,58 @@ module QA ...@@ -39,81 +48,58 @@ module QA
# Create both tokens before logging in the first time so that we don't need to log out in the middle of the test # Create both tokens before logging in the first time so that we don't need to log out in the middle of the test
admin_api_client.personal_access_token admin_api_client.personal_access_token
user_api_client.personal_access_token user_api_client.personal_access_token
group.add_member(user, Resource::Members::AccessLevel::OWNER) group.add_member(user, Resource::Members::AccessLevel::OWNER)
Flow::Login.sign_in(as: user) Flow::Login.sign_in(as: user)
group.visit! imported_project.reload! # import project and populate attributes
import_project
end end
after do after do
remove_project imported_project.remove_via_api!
group.remove_via_api! group.remove_via_api!
user.remove_via_api! user.remove_via_api!
end end
it 'user commits to GitHub triggers CI pipeline', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/144' do it(
'user commits to GitHub triggers CI pipeline',
testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/144'
) do
Page::Project::Menu.perform(&:click_ci_cd_pipelines) Page::Project::Menu.perform(&:click_ci_cd_pipelines)
Page::Project::Pipeline::Index.perform do |index| Page::Project::Pipeline::Index.perform do |index|
expect(index).to have_no_pipeline, 'Expect to have NO pipeline before mirroring.' expect(index).to have_no_pipeline, 'Expect to have NO pipeline before mirroring.'
edit_github_file edit_github_file
trigger_project_mirror imported_project.trigger_project_mirror
index.wait_until(reload: false) { index.has_pipeline? } index.wait_until(reload: false) { index.has_pipeline? }
expect(index).to have_content(commit_message), 'Expect new pipeline to have latest commit message from Github.' expect(index).to have_content(commit_message), 'Expect new pipeline to have latest commit message from Github'
end end
end end
private private
def github_data
{
access_token: Runtime::Env.github_access_token,
repo_owner: 'gitlab-qa-github',
repo_name: 'test-project',
file_name: 'text_file.txt'
}
end
def edit_github_file def edit_github_file
Runtime::Logger.info "Making changes to Github file." Runtime::Logger.info "Making changes to Github file."
file = github_client.get github_data[:repo_owner], github_data[:repo_name], github_data[:file_name] github_file_contents = -> { github_client.contents(github_data[:repo], path: github_data[:file_name]) }
file_sha = file.body['sha']
file_path = file.body['path'] file_contents = github_file_contents.call
file_sha = file_contents.sha
file_new_content = Faker::Lorem.sentence file_new_content = Faker::Lorem.sentence
github_client.update(github_data[:repo_owner], github_data[:repo_name], github_data[:file_name], github_client.update_contents(
path: file_path, message: commit_message, github_data[:repo],
content: file_new_content, github_data[:file_name],
sha: file_sha) commit_message,
file_sha,
file_new_content
)
Support::Retrier.retry_until(max_attempts: 5, sleep_interval: 2) do Support::Retrier.retry_until(max_attempts: 5, sleep_interval: 2) do
Base64.decode64(github_client.get(user: github_data[:repo_owner], repo: github_data[:repo_name], path: file_path)&.content) == file_new_content contents = github_file_contents.call&.content
end Base64.decode64(contents) == file_new_content
end
def import_project_id
request = Runtime::API::Request.new(user_api_client, import_project.api_get_path)
JSON.parse(get(request.url))['id']
end
def trigger_project_mirror
Runtime::Logger.info "Triggering pull mirror request."
request = Runtime::API::Request.new(user_api_client, "/projects/#{import_project_id}/mirror/pull")
Support::Retrier.retry_until(max_attempts: 6, sleep_interval: 10) do
response = post(request.url, nil)
Runtime::Logger.info "Mirror pull request response: #{response}"
response.code == Support::Api::HTTP_STATUS_OK
end end
end end
def remove_project
delete_project_request = Runtime::API::Request.new(user_api_client, "/projects/#{CGI.escape("#{Runtime::Namespace.path}/#{import_project.name}")}")
delete delete_project_request.url
end
end end
end end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment