Commit 1c91c4e3 authored by Grzegorz Bizon's avatar Grzegorz Bizon

Merge branch 'qa-clone-with-deploy-key' into 'master'

QA with runner cloning the repo with a deploy key

Closes gitlab-qa#148

See merge request gitlab-org/gitlab-ce!16859
parents 6085656b 36c76ec6
......@@ -117,6 +117,10 @@ module QA
autoload :Show, 'qa/page/project/pipeline/show'
end
module Job
autoload :Show, 'qa/page/project/job/show'
end
module Settings
autoload :Common, 'qa/page/project/settings/common'
autoload :Advanced, 'qa/page/project/settings/advanced'
......@@ -165,6 +169,7 @@ module QA
#
module Git
autoload :Repository, 'qa/git/repository'
autoload :Location, 'qa/git/location'
end
##
......
......@@ -4,7 +4,7 @@ module QA
module Factory
module Resource
class Runner < Factory::Base
attr_writer :name, :tags
attr_writer :name, :tags, :image
dependency Factory::Resource::Project, as: :project do |project|
project.name = 'project-with-ci-cd'
......@@ -19,6 +19,10 @@ module QA
@tags || %w[qa e2e]
end
def image
@image || 'gitlab/gitlab-runner:alpine'
end
def fabricate!
project.visit!
......@@ -31,6 +35,7 @@ module QA
runner.token = runners.registration_token
runner.address = runners.coordinator_address
runner.tags = tags
runner.image = image
runner.register!
end
end
......
require 'uri'
require 'forwardable'
module QA
module Git
class Location
extend Forwardable
attr_reader :git_uri, :uri
def_delegators :@uri, :user, :host, :path
# See: config/initializers/1_settings.rb
# Settings#build_gitlab_shell_ssh_path_prefix
def initialize(git_uri)
@git_uri = git_uri
@uri =
if git_uri.start_with?('ssh://')
URI.parse(git_uri)
else
*rest, path = git_uri.split(':')
# Host cannot have : so we'll need to escape it
user_host = rest.join('%3A').sub(/\A\[(.+)\]\z/, '\1')
URI.parse("ssh://#{user_host}/#{path}")
end
end
def port
uri.port || 22
end
end
end
end
require 'cgi'
require 'uri'
module QA
......
......@@ -17,7 +17,8 @@ module QA
start = Time.now
while Time.now - start < max
return true if yield
result = yield
return result if result
sleep(time)
......
module QA::Page
module Project::Job
class Show < QA::Page::Base
view 'app/views/projects/jobs/show.html.haml' do
element :build_output, '.js-build-output'
end
def output
css = '.js-build-output'
wait(reload: false) do
has_css?(css)
end
find(css).text
end
end
end
end
......@@ -6,7 +6,13 @@ module QA::Page
end
def go_to_latest_pipeline
first('.js-pipeline-url-link').click
css = '.js-pipeline-url-link'
link = wait(reload: false) do
first(css)
end
link.click
end
end
end
......
......@@ -11,6 +11,7 @@ module QA::Page
view 'app/assets/javascripts/pipelines/components/graph/job_component.vue' do
element :job_component, /class.*ci-job-component.*/
element :job_link, /class.*js-pipeline-graph-job-link.*/
end
view 'app/assets/javascripts/vue_shared/components/ci_icon.vue' do
......@@ -30,6 +31,16 @@ module QA::Page
end
end
end
def go_to_first_job
css = '.js-pipeline-graph-job-link'
wait(reload: false) do
has_css?(css)
end
first(css).click
end
end
end
end
......@@ -22,22 +22,24 @@ module QA
end
def choose_repository_clone_http
wait(reload: false) do
click_element :clone_dropdown
page.within('.clone-options-dropdown') do
click_link('HTTP')
end
choose_repository_clone('HTTP', 'http')
end
# Ensure git clone textbox was updated to http URI
repository_location.include?('http')
end
def choose_repository_clone_ssh
# It's not always beginning with ssh:// so detecting with @
# would be more reliable because ssh would always contain it.
# We can't use .git because HTTP also contain that part.
choose_repository_clone('SSH', '@')
end
def repository_location
find('#project_clone').value
end
def repository_location_uri
Git::Location.new(repository_location)
end
def project_name
find('.qa-project-name').text
end
......@@ -56,6 +58,21 @@ module QA
click_link 'New issue'
end
private
def choose_repository_clone(kind, detect_text)
wait(reload: false) do
click_element :clone_dropdown
page.within('.clone-options-dropdown') do
click_link(kind)
end
# Ensure git clone textbox was updated
repository_location.include?(detect_text)
end
end
end
end
end
......
......@@ -7,7 +7,7 @@ module QA
extend Forwardable
attr_reader :key
def_delegators :@key, :fingerprint
def_delegators :@key, :fingerprint, :to_pem
def initialize(bits = 4096)
@key = OpenSSL::PKey::RSA.new(bits)
......
require 'digest/sha1'
module QA
feature 'cloning code using a deploy key', :core, :docker do
let(:runner_name) { "qa-runner-#{Time.now.to_i}" }
let(:key) { Runtime::RSAKey.new }
given(:project) do
Factory::Resource::Project.fabricate! do |resource|
resource.name = 'deploy-key-clone-project'
end
end
after do
Service::Runner.new(runner_name).remove!
end
scenario 'user sets up a deploy key to clone code using pipelines' do
Runtime::Browser.visit(:gitlab, Page::Main::Login)
Page::Main::Login.act { sign_in_using_credentials }
Factory::Resource::Runner.fabricate! do |resource|
resource.project = project
resource.name = runner_name
resource.tags = %w[qa docker]
resource.image = 'gitlab/gitlab-runner:ubuntu'
end
Factory::Resource::DeployKey.fabricate! do |resource|
resource.project = project
resource.title = 'deploy key title'
resource.key = key.public_key
end
Factory::Resource::SecretVariable.fabricate! do |resource|
resource.project = project
resource.key = 'DEPLOY_KEY'
resource.value = key.to_pem
end
project.visit!
repository_uri = Page::Project::Show.act do
choose_repository_clone_ssh
repository_location_uri
end
gitlab_ci = <<~YAML
cat-config:
script:
- mkdir -p ~/.ssh
- ssh-keyscan -p #{repository_uri.port} #{repository_uri.host} >> ~/.ssh/known_hosts
- eval $(ssh-agent -s)
- echo "$DEPLOY_KEY" | ssh-add -
- git clone #{repository_uri.git_uri}
- sha1sum #{project.name}/.gitlab-ci.yml
tags:
- qa
- docker
YAML
Factory::Repository::Push.fabricate! do |resource|
resource.project = project
resource.file_name = '.gitlab-ci.yml'
resource.commit_message = 'Add .gitlab-ci.yml'
resource.file_content = gitlab_ci
end
sha1sum = Digest::SHA1.hexdigest(gitlab_ci)
Page::Project::Show.act { wait_for_push }
Page::Menu::Side.act { click_ci_cd_pipelines }
Page::Project::Pipeline::Index.act { go_to_latest_pipeline }
Page::Project::Pipeline::Show.act { go_to_first_job }
Page::Project::Job::Show.perform do |job|
expect(job.output).to include(sha1sum)
end
end
end
end
describe QA::Git::Location do
describe '.new' do
context 'when URI starts with ssh://' do
context 'when URI has port' do
it 'parses correctly' do
uri = described_class
.new('ssh://git@qa.test:2222/sandbox/qa/repo.git')
expect(uri.user).to eq('git')
expect(uri.host).to eq('qa.test')
expect(uri.port).to eq(2222)
expect(uri.path).to eq('/sandbox/qa/repo.git')
end
end
context 'when URI does not have port' do
it 'parses correctly' do
uri = described_class
.new('ssh://git@qa.test/sandbox/qa/repo.git')
expect(uri.user).to eq('git')
expect(uri.host).to eq('qa.test')
expect(uri.port).to eq(22)
expect(uri.path).to eq('/sandbox/qa/repo.git')
end
end
end
context 'when URI does not start with ssh://' do
context 'when host does not have colons' do
it 'parses correctly' do
uri = described_class
.new('git@qa.test:sandbox/qa/repo.git')
expect(uri.user).to eq('git')
expect(uri.host).to eq('qa.test')
expect(uri.port).to eq(22)
expect(uri.path).to eq('/sandbox/qa/repo.git')
end
end
context 'when host has a colon' do
it 'parses correctly' do
uri = described_class
.new('[git@qa:test]:sandbox/qa/repo.git')
expect(uri.user).to eq('git')
expect(uri.host).to eq('qa%3Atest')
expect(uri.port).to eq(22)
expect(uri.path).to eq('/sandbox/qa/repo.git')
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