diff options
-rw-r--r-- | qa/qa.rb | 5 | ||||
-rw-r--r-- | qa/qa/factory/resource/runner.rb | 7 | ||||
-rw-r--r-- | qa/qa/git/location.rb | 31 | ||||
-rw-r--r-- | qa/qa/git/repository.rb | 1 | ||||
-rw-r--r-- | qa/qa/page/base.rb | 3 | ||||
-rw-r--r-- | qa/qa/page/project/job/show.rb | 19 | ||||
-rw-r--r-- | qa/qa/page/project/pipeline/index.rb | 8 | ||||
-rw-r--r-- | qa/qa/page/project/pipeline/show.rb | 11 | ||||
-rw-r--r-- | qa/qa/page/project/show.rb | 35 | ||||
-rw-r--r-- | qa/qa/runtime/rsa_key.rb | 2 | ||||
-rw-r--r-- | qa/qa/specs/features/project/deploy_key_clone_spec.rb | 81 | ||||
-rw-r--r-- | qa/spec/git/location_spec.rb | 55 |
12 files changed, 245 insertions, 13 deletions
@@ -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 ## diff --git a/qa/qa/factory/resource/runner.rb b/qa/qa/factory/resource/runner.rb index 5f37f8ac2e9..03b69eb1bdf 100644 --- a/qa/qa/factory/resource/runner.rb +++ b/qa/qa/factory/resource/runner.rb @@ -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 diff --git a/qa/qa/git/location.rb b/qa/qa/git/location.rb new file mode 100644 index 00000000000..55f7213972d --- /dev/null +++ b/qa/qa/git/location.rb @@ -0,0 +1,31 @@ +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 diff --git a/qa/qa/git/repository.rb b/qa/qa/git/repository.rb index 8f999511d58..8eb7031f609 100644 --- a/qa/qa/git/repository.rb +++ b/qa/qa/git/repository.rb @@ -1,3 +1,4 @@ +require 'cgi' require 'uri' module QA diff --git a/qa/qa/page/base.rb b/qa/qa/page/base.rb index 5c3af4b9115..7924479e2a1 100644 --- a/qa/qa/page/base.rb +++ b/qa/qa/page/base.rb @@ -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) diff --git a/qa/qa/page/project/job/show.rb b/qa/qa/page/project/job/show.rb new file mode 100644 index 00000000000..21bda74efb2 --- /dev/null +++ b/qa/qa/page/project/job/show.rb @@ -0,0 +1,19 @@ +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 diff --git a/qa/qa/page/project/pipeline/index.rb b/qa/qa/page/project/pipeline/index.rb index 32c108393b9..ce430a2a6ee 100644 --- a/qa/qa/page/project/pipeline/index.rb +++ b/qa/qa/page/project/pipeline/index.rb @@ -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 diff --git a/qa/qa/page/project/pipeline/show.rb b/qa/qa/page/project/pipeline/show.rb index 0835173f1cd..b183552d46c 100644 --- a/qa/qa/page/project/pipeline/show.rb +++ b/qa/qa/page/project/pipeline/show.rb @@ -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 diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb index 9d2a84ea644..8d4a8c51184 100644 --- a/qa/qa/page/project/show.rb +++ b/qa/qa/page/project/show.rb @@ -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::Repository::Location.parse(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 diff --git a/qa/qa/runtime/rsa_key.rb b/qa/qa/runtime/rsa_key.rb index d456062bce7..fcd7dcc4f02 100644 --- a/qa/qa/runtime/rsa_key.rb +++ b/qa/qa/runtime/rsa_key.rb @@ -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) diff --git a/qa/qa/specs/features/project/deploy_key_clone_spec.rb b/qa/qa/specs/features/project/deploy_key_clone_spec.rb new file mode 100644 index 00000000000..19d3c83758a --- /dev/null +++ b/qa/qa/specs/features/project/deploy_key_clone_spec.rb @@ -0,0 +1,81 @@ +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 diff --git a/qa/spec/git/location_spec.rb b/qa/spec/git/location_spec.rb new file mode 100644 index 00000000000..4c68a0cda61 --- /dev/null +++ b/qa/spec/git/location_spec.rb @@ -0,0 +1,55 @@ +describe QA::Git::Location do + describe '.parse' do + context 'when URI starts with ssh://' do + context 'when URI has port' do + it 'parses correctly' do + uri = described_class + .parse('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 + .parse('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 + .parse('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 + .parse('[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 |