diff options
author | Mark Lapierre <mlapierre@gmail.com> | 2018-06-11 18:58:06 -0400 |
---|---|---|
committer | Mark Lapierre <mlapierre@gitlab.com> | 2018-09-15 11:09:34 -0400 |
commit | 6cf55e51292852975e8cc5df4bb54ca39e5dc727 (patch) | |
tree | 97891f89e8d7688b927238d3a6b58ca4f2e0581e /qa | |
parent | 265b49135436af9b8938c4b21b13462f0cfffdcb (diff) | |
download | gitlab-ce-6cf55e51292852975e8cc5df4bb54ca39e5dc727.tar.gz |
Add an SSH key and use it to clone and push
Adds 2 end-to-end tests:
1. Add and remove an SSH key
2. Add an SSH key and use it to clone and push
Includes changes to factories to allow Git actions via SSH
Diffstat (limited to 'qa')
-rw-r--r-- | qa/qa.rb | 2 | ||||
-rw-r--r-- | qa/qa/factory/repository/project_push.rb | 18 | ||||
-rw-r--r-- | qa/qa/factory/repository/push.rb | 18 | ||||
-rw-r--r-- | qa/qa/factory/repository/wiki_push.rb | 4 | ||||
-rw-r--r-- | qa/qa/factory/resource/project.rb | 7 | ||||
-rw-r--r-- | qa/qa/factory/resource/ssh_key.rb | 40 | ||||
-rw-r--r-- | qa/qa/git/repository.rb | 37 | ||||
-rw-r--r-- | qa/qa/page/menu/profile.rb | 7 | ||||
-rw-r--r-- | qa/qa/page/menu/side.rb | 3 | ||||
-rw-r--r-- | qa/qa/page/profile/ssh_keys.rb | 34 | ||||
-rw-r--r-- | qa/qa/specs/features/browser_ui/3_create/repository/add_ssh_key_spec.rb | 31 | ||||
-rw-r--r-- | qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb | 40 |
12 files changed, 228 insertions, 13 deletions
@@ -57,6 +57,7 @@ module QA autoload :Wiki, 'qa/factory/resource/wiki' autoload :File, 'qa/factory/resource/file' autoload :Fork, 'qa/factory/resource/fork' + autoload :SSHKey, 'qa/factory/resource/ssh_key' end module Repository @@ -217,6 +218,7 @@ module QA module Profile autoload :PersonalAccessTokens, 'qa/page/profile/personal_access_tokens' + autoload :SSHKeys, 'qa/page/profile/ssh_keys' end module Issuable diff --git a/qa/qa/factory/repository/project_push.rb b/qa/qa/factory/repository/project_push.rb index 4f78098d348..167f47c9141 100644 --- a/qa/qa/factory/repository/project_push.rb +++ b/qa/qa/factory/repository/project_push.rb @@ -11,7 +11,9 @@ module QA factory.output end - product(:project) { |factory| factory.project } + product :project do |factory| + factory.project + end def initialize @file_name = 'file.txt' @@ -21,8 +23,8 @@ module QA @new_branch = true end - def repository_uri - @repository_uri ||= begin + def repository_http_uri + @repository_http_uri ||= begin project.visit! Page::Project::Show.act do choose_repository_clone_http @@ -30,6 +32,16 @@ module QA end end end + + def repository_ssh_uri + @repository_ssh_uri ||= begin + project.visit! + Page::Project::Show.act do + choose_repository_clone_ssh + repository_location.uri + end + end + end end end end diff --git a/qa/qa/factory/repository/push.rb b/qa/qa/factory/repository/push.rb index 5b7ebf6c41f..6c5088f1da5 100644 --- a/qa/qa/factory/repository/push.rb +++ b/qa/qa/factory/repository/push.rb @@ -5,8 +5,8 @@ module QA module Repository class Push < Factory::Base attr_accessor :file_name, :file_content, :commit_message, - :branch_name, :new_branch, :output, :repository_uri, - :user + :branch_name, :new_branch, :output, :repository_http_uri, + :repository_ssh_uri, :ssh_key, :user attr_writer :remote_branch @@ -16,7 +16,8 @@ module QA @commit_message = "This is a test commit" @branch_name = 'master' @new_branch = true - @repository_uri = "" + @repository_http_uri = "" + @ssh_key = nil end def remote_branch @@ -31,9 +32,14 @@ module QA def fabricate! Git::Repository.perform do |repository| - repository.uri = repository_uri + if ssh_key + repository.uri = repository_ssh_uri + repository.use_ssh_key(ssh_key) + else + repository.uri = repository_http_uri + repository.use_default_credentials + end - repository.use_default_credentials username = 'GitLab QA' email = 'root@gitlab.com' @@ -63,6 +69,8 @@ module QA repository.commit(commit_message) @output = repository.push_changes("#{branch_name}:#{remote_branch}") + + repository.delete_ssh_key end end end diff --git a/qa/qa/factory/repository/wiki_push.rb b/qa/qa/factory/repository/wiki_push.rb index fb7c2bb660d..ecc6cc18c88 100644 --- a/qa/qa/factory/repository/wiki_push.rb +++ b/qa/qa/factory/repository/wiki_push.rb @@ -16,8 +16,8 @@ module QA @new_branch = false end - def repository_uri - @repository_uri ||= begin + def repository_http_uri + @repository_http_uri ||= begin wiki.visit! Page::Project::Wiki::Show.act do go_to_clone_repository diff --git a/qa/qa/factory/resource/project.rb b/qa/qa/factory/resource/project.rb index 7fff22b5468..90db26ab3ab 100644 --- a/qa/qa/factory/resource/project.rb +++ b/qa/qa/factory/resource/project.rb @@ -20,6 +20,13 @@ module QA end end + product :repository_http_location do + Page::Project::Show.act do + choose_repository_clone_http + repository_location + end + end + def initialize @description = 'My awesome project' end diff --git a/qa/qa/factory/resource/ssh_key.rb b/qa/qa/factory/resource/ssh_key.rb new file mode 100644 index 00000000000..6c872f32d16 --- /dev/null +++ b/qa/qa/factory/resource/ssh_key.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +module QA + module Factory + module Resource + class SSHKey < Factory::Base + extend Forwardable + + attr_accessor :title + attr_reader :private_key, :public_key, :fingerprint + def_delegators :key, :private_key, :public_key, :fingerprint + + product :private_key do |factory| + factory.private_key + end + + product :title do |factory| + factory.title + end + + product :fingerprint do |factory| + factory.fingerprint + end + + def key + @key ||= Runtime::Key::RSA.new + end + + def fabricate! + Page::Menu::Main.act { go_to_profile_settings } + Page::Menu::Profile.act { click_ssh_keys } + + Page::Profile::SSHKeys.perform do |page| + page.add_key(public_key, title) + end + end + end + end + end +end diff --git a/qa/qa/git/repository.rb b/qa/qa/git/repository.rb index bdbb18b5045..a2a1d61152f 100644 --- a/qa/qa/git/repository.rb +++ b/qa/qa/git/repository.rb @@ -7,6 +7,10 @@ module QA class Repository include Scenario::Actable + def initialize + @ssh_cmd = "" + end + def self.perform(*args) Dir.mktmpdir do |dir| Dir.chdir(dir) { super } @@ -33,7 +37,7 @@ module QA end def clone(opts = '') - run_and_redact_credentials("git clone #{opts} #{@uri} ./") + run_and_redact_credentials(build_git_command("git clone #{opts} #{@uri} ./")) end def checkout(branch_name) @@ -53,6 +57,10 @@ module QA `git config user.email #{email}` end + def configure_ssh_command(command) + @ssh_cmd = "GIT_SSH_COMMAND='#{command}'" + end + def commit_file(name, contents, message) add_file(name, contents) commit(message) @@ -69,7 +77,7 @@ module QA end def push_changes(branch = 'master') - output, _ = run_and_redact_credentials("git push #{@uri} #{branch}") + output, _ = run_and_redact_credentials(build_git_command("git push #{@uri} #{branch}")) output end @@ -78,6 +86,31 @@ module QA `git log --oneline`.split("\n") end + def use_ssh_key(key) + @private_key_file = Tempfile.new("id_#{SecureRandom.hex(8)}") + File.binwrite(@private_key_file, key.private_key) + File.chmod(0700, @private_key_file) + + @known_hosts_file = Tempfile.new("known_hosts_#{SecureRandom.hex(8)}") + keyscan_params = ['-H'] + keyscan_params << "-p #{@uri.port}" if @uri.port + keyscan_params << @uri.host + run_and_redact_credentials("ssh-keyscan #{keyscan_params.join(' ')} >> #{@known_hosts_file.path}") + + configure_ssh_command("ssh -i #{@private_key_file.path} -o UserKnownHostsFile=#{@known_hosts_file.path}") + end + + def delete_ssh_key + return unless @private_key_file + + @private_key_file.close(true) + @known_hosts_file.close(true) + end + + def build_git_command(command_str) + [@ssh_cmd, command_str].compact.join(' ') + end + private # Since the remote URL contains the credentials, and git occasionally diff --git a/qa/qa/page/menu/profile.rb b/qa/qa/page/menu/profile.rb index 95e88d863e4..7e24fa85c33 100644 --- a/qa/qa/page/menu/profile.rb +++ b/qa/qa/page/menu/profile.rb @@ -6,6 +6,7 @@ module QA element :access_token_link, 'link_to profile_personal_access_tokens_path' element :access_token_title, 'Access Tokens' element :top_level_items, '.sidebar-top-level-items' + element :ssh_keys, 'SSH Keys' end def click_access_tokens @@ -14,6 +15,12 @@ module QA end end + def click_ssh_keys + within_sidebar do + click_link('SSH Keys') + end + end + private def within_sidebar diff --git a/qa/qa/page/menu/side.rb b/qa/qa/page/menu/side.rb index 354ccec2a5a..a1eedfea42e 100644 --- a/qa/qa/page/menu/side.rb +++ b/qa/qa/page/menu/side.rb @@ -6,6 +6,7 @@ module QA element :settings_item element :settings_link, 'link_to edit_project_path' element :repository_link, "title: _('Repository')" + element :link_pipelines element :pipelines_settings_link, "title: _('CI / CD')" element :operations_kubernetes_link, "title: _('Kubernetes')" element :issues_link, /link_to.*shortcuts-issues/ @@ -49,7 +50,7 @@ module QA def click_ci_cd_pipelines within_sidebar do - click_link('CI / CD') + click_element :link_pipelines end end diff --git a/qa/qa/page/profile/ssh_keys.rb b/qa/qa/page/profile/ssh_keys.rb new file mode 100644 index 00000000000..ce1813b14d0 --- /dev/null +++ b/qa/qa/page/profile/ssh_keys.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +module QA + module Page + module Profile + class SSHKeys < Page::Base + view 'app/views/profiles/keys/_form.html.haml' do + element :key_title_field + element :key_public_key_field + element :add_key_button + end + + view 'app/views/profiles/keys/_key_details.html.haml' do + element :delete_key_button + end + + def add_key(public_key, title) + fill_element :key_public_key_field, public_key + fill_element :key_title_field, title + + click_element :add_key_button + end + + def remove_key(title) + click_link(title) + + accept_alert do + click_element :delete_key_button + end + end + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/add_ssh_key_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/add_ssh_key_spec.rb new file mode 100644 index 00000000000..84f663c4866 --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/repository/add_ssh_key_spec.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +module QA + context :create do + describe 'SSH keys support' do + let(:key_title) { "key for ssh tests #{Time.now.to_f}" } + + it 'user adds and then removes an SSH key' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + key = Factory::Resource::SSHKey.fabricate! do |resource| + resource.title = key_title + end + + expect(page).to have_content("Title: #{key_title}") + expect(page).to have_content(key.fingerprint) + + Page::Menu::Main.act { go_to_profile_settings } + Page::Menu::Profile.act { click_ssh_keys } + + Page::Profile::SSHKeys.perform do |ssh_keys| + ssh_keys.remove_key(key_title) + end + + expect(page).not_to have_content("Title: #{key_title}") + expect(page).not_to have_content(key.fingerprint) + end + end + end +end diff --git a/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb b/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb new file mode 100644 index 00000000000..7c989bfd8cc --- /dev/null +++ b/qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +module QA + context :create do + describe 'SSH key support' do + # Note: If you run this test against GDK make sure you've enabled sshd + # See: https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/run_qa_against_gdk.md + + let(:key_title) { "key for ssh tests #{Time.now.to_f}" } + + it 'user adds an ssh key and pushes code to the repository' do + Runtime::Browser.visit(:gitlab, Page::Main::Login) + Page::Main::Login.act { sign_in_using_credentials } + + key = Factory::Resource::SSHKey.fabricate! do |resource| + resource.title = key_title + end + + Factory::Repository::ProjectPush.fabricate! do |push| + push.ssh_key = key + push.file_name = 'README.md' + push.file_content = '# Test Use SSH Key' + push.commit_message = 'Add README.md' + end + + Page::Project::Show.act { wait_for_push } + + expect(page).to have_content('README.md') + expect(page).to have_content('Test Use SSH Key') + + Page::Menu::Main.act { go_to_profile_settings } + Page::Menu::Profile.act { click_ssh_keys } + + Page::Profile::SSHKeys.perform do |ssh_keys| + ssh_keys.remove_key(key_title) + end + end + end + end +end |