gitlab-qa 0.2.2 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitlab-ci.yml +9 -1
- data/CONTRIBUTING.md +19 -620
- data/README.md +20 -3
- data/lib/gitlab/qa.rb +10 -2
- data/lib/gitlab/qa/{docker → component}/gitlab.rb +55 -21
- data/lib/gitlab/qa/component/specs.rb +59 -0
- data/lib/gitlab/qa/docker/command.rb +17 -22
- data/lib/gitlab/qa/docker/engine.rb +1 -1
- data/lib/gitlab/qa/docker/shellout.rb +27 -0
- data/lib/gitlab/qa/release.rb +37 -15
- data/lib/gitlab/qa/runtime/env.rb +6 -1
- data/lib/gitlab/qa/scenario/test/instance/any.rb +7 -3
- data/lib/gitlab/qa/scenario/test/instance/image.rb +4 -9
- data/lib/gitlab/qa/scenario/test/integration/mattermost.rb +35 -0
- data/lib/gitlab/qa/scenario/test/omnibus/image.rb +4 -8
- data/lib/gitlab/qa/scenario/test/omnibus/upgrade.rb +6 -4
- data/lib/gitlab/qa/version.rb +1 -1
- metadata +6 -4
- data/lib/gitlab/qa/docker/specs.rb +0 -40
data/README.md
CHANGED
@@ -25,6 +25,10 @@ command in your system.
|
|
25
25
|
|
26
26
|
`gitlab-qa Test::Instance::Image CE|EE|<full image address>`
|
27
27
|
|
28
|
+
1. Run tests against a Docker image with GitLab and Mattermost:
|
29
|
+
|
30
|
+
`gitlab-qa Test::Integration::Mattermost CE|EE|<full image address>`
|
31
|
+
|
28
32
|
1. Test upgrade process:
|
29
33
|
|
30
34
|
`gitlab-qa Test::Omnibus::Upgrade CE|EE|<full image address>`
|
@@ -61,16 +65,29 @@ This scenario tests that the GitLab Docker container works as expected by
|
|
61
65
|
running tests against it.
|
62
66
|
|
63
67
|
To run tests against the GitLab containers, a GitLab QA (`gitlab/gitlab-qa`)
|
64
|
-
container is
|
68
|
+
container is spun up and tests are run from it by running the `Test::Instance`
|
65
69
|
scenario (located under `qa/scenario/test/instance` in the GitLab codebase).
|
66
70
|
|
71
|
+
### `Test::Integration::Mattermost CE|EE|<full image address>`
|
72
|
+
|
73
|
+
This scenario tests that GitLab instance works as expected when
|
74
|
+
enabling the embedded Mattermost server (see `Test::Instance::Image`
|
75
|
+
above).
|
76
|
+
|
67
77
|
### `Test::Instance::Any CE|EE|<full image address>`
|
68
78
|
|
69
79
|
This scenario tests that the any GitLab instance works as expected by running
|
70
|
-
tests against it (see `Test::Instance::Image`
|
80
|
+
tests against it (see `Test::Instance::Image` above).
|
71
81
|
|
72
82
|
## Supported environment variables
|
73
83
|
|
74
84
|
* `GITLAB_USERNAME` - username to use when signing in to GitLab
|
75
|
-
* `GITLAB_PASSWORD`
|
85
|
+
* `GITLAB_PASSWORD` - password to use when signing in to GitLab
|
76
86
|
* `EE_LICENSE` - Enterprise Edition license
|
87
|
+
* `QA_SCREENSHOTS_DIR` - Path to a directory where screenshots for failing tests
|
88
|
+
will be saved (default: `/tmp/gitlab-qa-screenshots`)
|
89
|
+
* `DOCKER_HOST` - Docker host to run tests against (default: `http://localhost`)
|
90
|
+
|
91
|
+
## Contributing
|
92
|
+
|
93
|
+
Please see the [contribution guidelines](CONTRIBUTING.md)
|
data/lib/gitlab/qa.rb
CHANGED
@@ -22,14 +22,22 @@ module Gitlab
|
|
22
22
|
autoload :Image, 'qa/scenario/test/omnibus/image'
|
23
23
|
autoload :Upgrade, 'qa/scenario/test/omnibus/upgrade'
|
24
24
|
end
|
25
|
+
|
26
|
+
module Integration
|
27
|
+
autoload :Mattermost, 'qa/scenario/test/integration/mattermost'
|
28
|
+
end
|
25
29
|
end
|
26
30
|
end
|
27
31
|
|
32
|
+
module Component
|
33
|
+
autoload :Gitlab, 'qa/component/gitlab'
|
34
|
+
autoload :Specs, 'qa/component/specs'
|
35
|
+
end
|
36
|
+
|
28
37
|
module Docker
|
29
38
|
autoload :Engine, 'qa/docker/engine'
|
30
39
|
autoload :Command, 'qa/docker/command'
|
31
|
-
autoload :
|
32
|
-
autoload :Specs, 'qa/docker/specs'
|
40
|
+
autoload :Shellout, 'qa/docker/shellout'
|
33
41
|
end
|
34
42
|
end
|
35
43
|
end
|
@@ -1,28 +1,42 @@
|
|
1
1
|
require 'securerandom'
|
2
2
|
require 'net/http'
|
3
3
|
require 'uri'
|
4
|
+
require 'forwardable'
|
5
|
+
require 'shellwords'
|
4
6
|
|
5
7
|
module Gitlab
|
6
8
|
module QA
|
7
|
-
module
|
9
|
+
module Component
|
8
10
|
class Gitlab
|
11
|
+
extend Forwardable
|
9
12
|
include Scenario::Actable
|
10
13
|
|
11
14
|
# rubocop:disable Style/Semicolon
|
12
15
|
|
13
|
-
|
14
|
-
|
16
|
+
attr_reader :release, :docker
|
17
|
+
attr_accessor :volumes, :network, :environment, :network_aliases
|
18
|
+
|
19
|
+
def_delegators :release, :tag, :image, :edition
|
15
20
|
|
16
21
|
def initialize
|
17
22
|
@docker = Docker::Engine.new
|
23
|
+
@environment = {}
|
24
|
+
@volumes = {}
|
25
|
+
@network_aliases = []
|
26
|
+
|
27
|
+
self.release = 'CE'
|
18
28
|
end
|
19
29
|
|
20
|
-
def
|
21
|
-
@
|
30
|
+
def omnibus_config=(config)
|
31
|
+
@environment['GITLAB_OMNIBUS_CONFIG'] = config
|
22
32
|
end
|
23
33
|
|
24
34
|
def release=(release)
|
25
|
-
@release
|
35
|
+
@release = Release.new(release)
|
36
|
+
end
|
37
|
+
|
38
|
+
def name
|
39
|
+
@name ||= "gitlab-qa-#{edition}-#{SecureRandom.hex(4)}"
|
26
40
|
end
|
27
41
|
|
28
42
|
def address
|
@@ -30,7 +44,7 @@ module Gitlab
|
|
30
44
|
end
|
31
45
|
|
32
46
|
def hostname
|
33
|
-
"#{
|
47
|
+
"#{name}.#{network}"
|
34
48
|
end
|
35
49
|
|
36
50
|
def instance
|
@@ -44,29 +58,40 @@ module Gitlab
|
|
44
58
|
end
|
45
59
|
|
46
60
|
def prepare
|
47
|
-
@docker.pull(
|
61
|
+
@docker.pull(image, tag)
|
48
62
|
|
49
|
-
return if @docker.network_exists?(
|
50
|
-
@docker.network_create(
|
63
|
+
return if @docker.network_exists?(network)
|
64
|
+
@docker.network_create(network)
|
51
65
|
end
|
52
66
|
|
67
|
+
# rubocop:disable Metrics/MethodLength
|
68
|
+
# rubocop:disable Metrics/AbcSize
|
53
69
|
def start
|
54
|
-
|
55
|
-
raise 'Please configure an instance first!'
|
56
|
-
end
|
70
|
+
ensure_configured!
|
57
71
|
|
58
|
-
|
59
|
-
command <<
|
60
|
-
command << "--
|
72
|
+
docker.run(image, tag) do |command|
|
73
|
+
command << '-d -p 80:80'
|
74
|
+
command << "--name #{name}"
|
75
|
+
command << "--net #{network}"
|
76
|
+
command << "--hostname #{hostname}"
|
61
77
|
|
62
78
|
@volumes.to_h.each do |to, from|
|
63
79
|
command << "--volume #{to}:#{from}:Z"
|
64
80
|
end
|
81
|
+
|
82
|
+
@environment.to_h.each do |key, value|
|
83
|
+
escaped_value = Shellwords.escape(value)
|
84
|
+
command << "--env #{key}=#{escaped_value}"
|
85
|
+
end
|
86
|
+
|
87
|
+
@network_aliases.to_a.each do |network_alias|
|
88
|
+
command << "--network-alias #{network_alias}"
|
89
|
+
end
|
65
90
|
end
|
66
91
|
end
|
67
92
|
|
68
93
|
def reconfigure
|
69
|
-
@docker.attach(
|
94
|
+
@docker.attach(name) do |line, wait|
|
70
95
|
# TODO, workaround which allows to detach from the container
|
71
96
|
#
|
72
97
|
Process.kill('INT', wait.pid) if line =~ /gitlab Reconfigured!/
|
@@ -74,14 +99,14 @@ module Gitlab
|
|
74
99
|
end
|
75
100
|
|
76
101
|
def restart
|
77
|
-
@docker.restart(
|
102
|
+
@docker.restart(name)
|
78
103
|
end
|
79
104
|
|
80
105
|
def teardown
|
81
|
-
raise 'Invalid instance name!' unless
|
106
|
+
raise 'Invalid instance name!' unless name
|
82
107
|
|
83
|
-
@docker.stop(
|
84
|
-
@docker.remove(
|
108
|
+
@docker.stop(name)
|
109
|
+
@docker.remove(name)
|
85
110
|
end
|
86
111
|
|
87
112
|
def wait
|
@@ -96,6 +121,15 @@ module Gitlab
|
|
96
121
|
end
|
97
122
|
end
|
98
123
|
|
124
|
+
private
|
125
|
+
|
126
|
+
# rubocop:disable Style/GuardClause
|
127
|
+
def ensure_configured!
|
128
|
+
unless [name, release, network].all?
|
129
|
+
raise 'Please configure an instance first!'
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
99
133
|
class Availability
|
100
134
|
def initialize(address)
|
101
135
|
@uri = URI.join(address, '/help')
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Gitlab
|
2
|
+
module QA
|
3
|
+
module Component
|
4
|
+
##
|
5
|
+
# This class represents GitLab QA specs image that is implemented in
|
6
|
+
# the `qa/` directory located in GitLab CE / EE repositories.
|
7
|
+
#
|
8
|
+
# TODO, it needs some refactoring.
|
9
|
+
#
|
10
|
+
class Specs
|
11
|
+
include Scenario::Actable
|
12
|
+
|
13
|
+
IMAGE_NAME = 'gitlab/gitlab-qa'.freeze
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@docker = Docker::Engine.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def test(gitlab:, suite: 'Test::Instance', extra_args: [])
|
20
|
+
test_address(
|
21
|
+
release: gitlab.release,
|
22
|
+
address: gitlab.address,
|
23
|
+
name: "#{gitlab.name}-specs",
|
24
|
+
network: gitlab.network,
|
25
|
+
suite: suite,
|
26
|
+
extra_args: extra_args
|
27
|
+
)
|
28
|
+
end
|
29
|
+
|
30
|
+
# rubocop:disable Metrics/ParameterLists
|
31
|
+
def test_address(release:, address:, name: nil, network: nil,
|
32
|
+
suite: 'Test::Instance', extra_args: [])
|
33
|
+
puts "Running instance suite #{suite} for Gitlab " \
|
34
|
+
"#{release.edition.upcase} at #{address}"
|
35
|
+
|
36
|
+
args = [suite, address] + extra_args
|
37
|
+
|
38
|
+
@docker.run(IMAGE_NAME, release.edition_tag, *args) do |command|
|
39
|
+
build_command(command, name, network)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def build_command(command, name, network)
|
46
|
+
command << "-t --rm --net=#{network || 'bridge'}"
|
47
|
+
|
48
|
+
Runtime::Env.delegated.each do |env|
|
49
|
+
command.env(env, "$#{env}")
|
50
|
+
end
|
51
|
+
|
52
|
+
command.volume('/var/run/docker.sock', '/var/run/docker.sock')
|
53
|
+
command.volume(Runtime::Env.screenshots_dir, '/home/qa/tmp')
|
54
|
+
command.name(name || "gitlab-specs-#{Time.now.to_i}")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -1,17 +1,9 @@
|
|
1
|
-
require 'open3'
|
2
|
-
|
3
1
|
module Gitlab
|
4
2
|
module QA
|
5
3
|
module Docker
|
6
4
|
class Command
|
7
|
-
class StatusError < StandardError; end
|
8
|
-
|
9
5
|
attr_reader :args
|
10
6
|
|
11
|
-
def self.execute(cmd, &block)
|
12
|
-
new(cmd).execute!(&block)
|
13
|
-
end
|
14
|
-
|
15
7
|
def initialize(cmd = nil)
|
16
8
|
@args = Array(cmd)
|
17
9
|
end
|
@@ -20,25 +12,28 @@ module Gitlab
|
|
20
12
|
tap { @args.concat(args) }
|
21
13
|
end
|
22
14
|
|
23
|
-
def
|
24
|
-
|
15
|
+
def volume(from, to)
|
16
|
+
tap { @args << "-v #{from}:#{to}" }
|
25
17
|
end
|
26
18
|
|
27
|
-
|
19
|
+
def name(identity)
|
20
|
+
tap { @args << "--name #{identity}" }
|
21
|
+
end
|
28
22
|
|
29
|
-
def
|
30
|
-
|
23
|
+
def env(name, value)
|
24
|
+
tap { @args << %(-e #{name}="#{value}") }
|
25
|
+
end
|
31
26
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
yield line, wait if block_given?
|
36
|
-
end
|
27
|
+
def to_s
|
28
|
+
"docker #{@args.join(' ')}"
|
29
|
+
end
|
37
30
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
31
|
+
def execute!(&block)
|
32
|
+
Docker::Shellout.execute!(self, &block)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.execute(cmd, &block)
|
36
|
+
new(cmd).execute!(&block)
|
42
37
|
end
|
43
38
|
end
|
44
39
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
3
|
+
module Gitlab
|
4
|
+
module QA
|
5
|
+
module Docker
|
6
|
+
class Shellout
|
7
|
+
class StatusError < StandardError; end
|
8
|
+
|
9
|
+
def self.execute!(command)
|
10
|
+
puts "Running shell command: `#{command}`"
|
11
|
+
|
12
|
+
Open3.popen2e(command.to_s) do |_in, out, wait|
|
13
|
+
out.each do |line|
|
14
|
+
puts line
|
15
|
+
|
16
|
+
yield line, wait if block_given?
|
17
|
+
end
|
18
|
+
|
19
|
+
if wait.value.exited? && wait.value.exitstatus.nonzero?
|
20
|
+
raise StatusError, "Docker command `#{command}` failed!"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/gitlab/qa/release.rb
CHANGED
@@ -5,33 +5,55 @@ module Gitlab
|
|
5
5
|
DEFAULT_TAG = 'nightly'.freeze
|
6
6
|
|
7
7
|
attr_reader :release
|
8
|
+
attr_writer :tag
|
8
9
|
|
9
10
|
def initialize(release)
|
10
11
|
@release = release.to_s
|
11
12
|
end
|
12
13
|
|
14
|
+
def to_s
|
15
|
+
"#{image}:#{tag}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def previous_stable
|
19
|
+
# The previous stable is always gitlab/gitlab-ce:latest or
|
20
|
+
# gitlab/gitlab-ee:latest
|
21
|
+
self.class.new("#{canonical_image}:latest")
|
22
|
+
end
|
23
|
+
|
13
24
|
def edition
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
25
|
+
@edition ||=
|
26
|
+
if canonical?
|
27
|
+
release.downcase.to_sym
|
28
|
+
else
|
29
|
+
release.match(CUSTOM_GITLAB_IMAGE_REGEX)[1].to_sym
|
30
|
+
end
|
19
31
|
end
|
20
32
|
|
21
33
|
def image
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
34
|
+
@image ||=
|
35
|
+
if canonical?
|
36
|
+
"gitlab/gitlab-#{edition}"
|
37
|
+
else
|
38
|
+
release.sub(/:.+\z/, '')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def canonical_image
|
43
|
+
@canonical_image ||= "gitlab/gitlab-#{edition}"
|
27
44
|
end
|
28
45
|
|
29
46
|
def tag
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
47
|
+
@tag ||=
|
48
|
+
if canonical?
|
49
|
+
DEFAULT_TAG
|
50
|
+
else
|
51
|
+
release.match(CUSTOM_GITLAB_IMAGE_REGEX)[2]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def edition_tag
|
56
|
+
@edition_tag ||= "#{edition}-#{tag}"
|
35
57
|
end
|
36
58
|
|
37
59
|
private
|
@@ -4,12 +4,17 @@ module Gitlab
|
|
4
4
|
module Env
|
5
5
|
extend self
|
6
6
|
|
7
|
+
VARIABLES = %w(GITLAB_USERNAME
|
8
|
+
GITLAB_PASSWORD
|
9
|
+
GITLAB_URL
|
10
|
+
EE_LICENSE).freeze
|
11
|
+
|
7
12
|
def screenshots_dir
|
8
13
|
ENV['QA_SCREENSHOTS_DIR'] || '/tmp/gitlab-qa-screenshots'
|
9
14
|
end
|
10
15
|
|
11
16
|
def delegated
|
12
|
-
|
17
|
+
VARIABLES.select { |name| ENV[name] }
|
13
18
|
end
|
14
19
|
end
|
15
20
|
end
|