summaryrefslogtreecommitdiff
path: root/qa
diff options
context:
space:
mode:
authorMark Lapierre <mlapierre@gmail.com>2018-06-11 18:58:06 -0400
committerMark Lapierre <mlapierre@gitlab.com>2018-09-15 11:09:34 -0400
commit6cf55e51292852975e8cc5df4bb54ca39e5dc727 (patch)
tree97891f89e8d7688b927238d3a6b58ca4f2e0581e /qa
parent265b49135436af9b8938c4b21b13462f0cfffdcb (diff)
downloadgitlab-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.rb2
-rw-r--r--qa/qa/factory/repository/project_push.rb18
-rw-r--r--qa/qa/factory/repository/push.rb18
-rw-r--r--qa/qa/factory/repository/wiki_push.rb4
-rw-r--r--qa/qa/factory/resource/project.rb7
-rw-r--r--qa/qa/factory/resource/ssh_key.rb40
-rw-r--r--qa/qa/git/repository.rb37
-rw-r--r--qa/qa/page/menu/profile.rb7
-rw-r--r--qa/qa/page/menu/side.rb3
-rw-r--r--qa/qa/page/profile/ssh_keys.rb34
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/add_ssh_key_spec.rb31
-rw-r--r--qa/qa/specs/features/browser_ui/3_create/repository/use_ssh_key_spec.rb40
12 files changed, 228 insertions, 13 deletions
diff --git a/qa/qa.rb b/qa/qa.rb
index 830a6aa17de..3c74dc0b096 100644
--- a/qa/qa.rb
+++ b/qa/qa.rb
@@ -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