gitlab-qa 8.4.2 → 8.6.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.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +0 -12
  3. data/Gemfile.lock +1 -1
  4. data/exe/gitlab-qa +1 -1
  5. data/lib/gitlab/qa/component/base.rb +2 -2
  6. data/lib/gitlab/qa/component/gitlab.rb +1 -1
  7. data/lib/gitlab/qa/component/staging.rb +17 -35
  8. data/lib/gitlab/qa/component/suggested_reviewer.rb +47 -0
  9. data/lib/gitlab/qa/docker/command.rb +3 -14
  10. data/lib/gitlab/qa/docker/engine.rb +1 -1
  11. data/lib/gitlab/qa/release.rb +6 -2
  12. data/lib/gitlab/qa/report/find_set_dri.rb +43 -0
  13. data/lib/gitlab/qa/report/gitlab_issue_client.rb +7 -0
  14. data/lib/gitlab/qa/report/relate_failure_issue.rb +16 -0
  15. data/lib/gitlab/qa/report/results_reporter_shared.rb +1 -1
  16. data/lib/gitlab/qa/report/test_result.rb +8 -0
  17. data/lib/gitlab/qa/runtime/env.rb +5 -14
  18. data/lib/gitlab/qa/scenario/test/integration/suggested_reviewer.rb +62 -0
  19. data/lib/gitlab/qa/scenario/test/omnibus/update_from_previous.rb +1 -1
  20. data/lib/gitlab/qa/service/cluster_provider/base.rb +33 -0
  21. data/lib/gitlab/qa/service/cluster_provider/k3d.rb +141 -0
  22. data/lib/gitlab/qa/service/kubernetes_cluster.rb +62 -0
  23. data/lib/gitlab/qa/support/shell_command.rb +98 -0
  24. data/lib/gitlab/qa/support/shellout.rb +16 -0
  25. data/lib/gitlab/qa/version.rb +1 -1
  26. data/lib/gitlab/qa.rb +0 -1
  27. data/support/manifests/suggested_reviewer/authenticator.yaml +41 -0
  28. data/support/manifests/suggested_reviewer/postgres.yaml +84 -0
  29. data/support/manifests/suggested_reviewer/pubsub.yaml +41 -0
  30. data/support/manifests/suggested_reviewer/recommender-bot.yaml +242 -0
  31. data/support/manifests/suggested_reviewer/recommender.yaml +52 -0
  32. metadata +15 -7
  33. data/lib/gitlab/qa/component/internet_tunnel.rb +0 -76
  34. data/lib/gitlab/qa/docker/shellout.rb +0 -77
  35. data/lib/gitlab/qa/scenario/test/integration/kubernetes.rb +0 -56
  36. data/lib/gitlab/qa/scenario/test/integration/ssh_tunnel.rb +0 -56
  37. data/lib/gitlab/qa/support/dev_ee_qa_image.rb +0 -54
@@ -0,0 +1,141 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module Service
6
+ module ClusterProvider
7
+ class K3d < Base
8
+ def create_registry_mirror
9
+ return if registry_mirror_exists?('registry-gitlab')
10
+
11
+ Runtime::Env.require_qa_container_registry_access_token!
12
+
13
+ shell <<~CMD
14
+ k3d registry create registry-gitlab \
15
+ -p 5000 \
16
+ --proxy-remote-url https://#{GITLAB_REGISTRY} \
17
+ --proxy-password #{Runtime::Env.gitlab_username} \
18
+ --proxy-username #{Runtime::Env.qa_container_registry_access_token} \
19
+ -v tmp/registry-gitlab:/var/lib/registry
20
+ CMD
21
+
22
+ File.write('tmp/registry-mirror.yml', registry_mirror)
23
+
24
+ create_args << %w[--registry-use k3d-registry-gitlab:5000 --registry-config tmp/registry-mirror.yml]
25
+ end
26
+
27
+ def validate_dependencies
28
+ find_executable('k3d') || raise("You must first install `k3d` executable to run these tests.")
29
+ end
30
+
31
+ def setup
32
+ shell "k3d cluster create #{cluster_name} #{create_args&.join(' ')}"
33
+
34
+ install_local_storage
35
+ end
36
+
37
+ def teardown
38
+ shell "k3d cluster delete #{cluster_name}"
39
+ end
40
+
41
+ private
42
+
43
+ def registry_mirror_exists?(name)
44
+ shell('k3d registry list').include?("k3d-#{name}")
45
+ end
46
+
47
+ def retry_until(max_attempts: 10, wait: 1)
48
+ max_attempts.times do
49
+ result = yield
50
+ return result if result
51
+
52
+ sleep wait
53
+ end
54
+
55
+ raise "Retried #{max_attempts} times. Aborting"
56
+ end
57
+
58
+ def install_local_storage
59
+ shell('kubectl apply -f -', stdin_data: local_storage_config)
60
+ end
61
+
62
+ # See https://github.com/rancher/k3d/issues/67
63
+ def local_storage_config
64
+ <<~YAML
65
+ ---
66
+ apiVersion: v1
67
+ kind: ServiceAccount
68
+ metadata:
69
+ name: storage-provisioner
70
+ namespace: kube-system
71
+ ---
72
+ apiVersion: rbac.authorization.k8s.io/v1
73
+ kind: ClusterRoleBinding
74
+ metadata:
75
+ name: storage-provisioner
76
+ roleRef:
77
+ apiGroup: rbac.authorization.k8s.io
78
+ kind: ClusterRole
79
+ name: system:persistent-volume-provisioner
80
+ subjects:
81
+ - kind: ServiceAccount
82
+ name: storage-provisioner
83
+ namespace: kube-system
84
+ ---
85
+ apiVersion: v1
86
+ kind: Pod
87
+ metadata:
88
+ name: storage-provisioner
89
+ namespace: kube-system
90
+ spec:
91
+ serviceAccountName: storage-provisioner
92
+ tolerations:
93
+ - effect: NoExecute
94
+ key: node.kubernetes.io/not-ready
95
+ operator: Exists
96
+ tolerationSeconds: 300
97
+ - effect: NoExecute
98
+ key: node.kubernetes.io/unreachable
99
+ operator: Exists
100
+ tolerationSeconds: 300
101
+ hostNetwork: true
102
+ containers:
103
+ - name: storage-provisioner
104
+ image: gcr.io/k8s-minikube/storage-provisioner:v1.8.1
105
+ command: ["/storage-provisioner"]
106
+ imagePullPolicy: IfNotPresent
107
+ volumeMounts:
108
+ - mountPath: /tmp
109
+ name: tmp
110
+ volumes:
111
+ - name: tmp
112
+ hostPath:
113
+ path: /tmp
114
+ type: Directory
115
+ ---
116
+ kind: StorageClass
117
+ apiVersion: storage.k8s.io/v1
118
+ metadata:
119
+ name: standard
120
+ namespace: kube-system
121
+ annotations:
122
+ storageclass.kubernetes.io/is-default-class: "true"
123
+ labels:
124
+ addonmanager.kubernetes.io/mode: EnsureExists
125
+ provisioner: k8s.io/minikube-hostpath
126
+ YAML
127
+ end
128
+
129
+ def registry_mirror
130
+ <<~YAML
131
+ mirrors:
132
+ "registry.gitlab.com":
133
+ endpoint:
134
+ - http://k3d-registry-gitlab:5000
135
+ YAML
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mkmf'
4
+
5
+ module Gitlab
6
+ module QA
7
+ module Service
8
+ class KubernetesCluster
9
+ include Support::Shellout
10
+
11
+ attr_reader :provider
12
+
13
+ def initialize(provider_class: QA::Service::ClusterProvider::K3d)
14
+ @provider = provider_class.new
15
+ end
16
+
17
+ def create!
18
+ validate_dependencies
19
+
20
+ @provider.validate_dependencies
21
+ @provider.setup
22
+
23
+ self
24
+ end
25
+
26
+ def remove!
27
+ @provider.teardown
28
+ end
29
+
30
+ def cluster_name
31
+ @provider.cluster_name
32
+ end
33
+
34
+ def to_s
35
+ cluster_name
36
+ end
37
+
38
+ def create_registry_mirror
39
+ @provider.create_registry_mirror
40
+ end
41
+
42
+ def create_secret(secret, secret_name)
43
+ shell("kubectl create secret generic #{secret_name} --from-literal=token='#{secret}'", mask_secrets: [secret])
44
+ end
45
+
46
+ def apply_manifest(manifest)
47
+ shell('kubectl apply -f -', stdin_data: manifest)
48
+ end
49
+
50
+ private
51
+
52
+ def admin_user
53
+ @admin_user ||= "#{@provider.cluster_name}-admin"
54
+ end
55
+
56
+ def validate_dependencies
57
+ find_executable('kubectl') || raise("You must first install `kubectl` executable to run these tests.")
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'open3'
4
+ require 'active_support/core_ext/string/filters'
5
+
6
+ module Gitlab
7
+ module QA
8
+ module Support
9
+ class ShellCommand
10
+ using Rainbow
11
+
12
+ StatusError = Class.new(StandardError)
13
+
14
+ # Shell command
15
+ #
16
+ # @param [<String, Array>] command
17
+ # @param [<String, Array>] mask_secrets
18
+ # @param [Boolean] stream_output stream command output to stdout directly instead of logger
19
+ def initialize(command = nil, stdin_data: nil, mask_secrets: nil, stream_output: false)
20
+ @command = command
21
+ @mask_secrets = Array(mask_secrets)
22
+ @stream_output = stream_output
23
+ @output = []
24
+ @logger = Runtime::Logger.logger
25
+ @stdin_data = stdin_data
26
+ end
27
+
28
+ attr_reader :command, :output, :stream_output
29
+
30
+ def execute! # rubocop:disable Metrics/AbcSize
31
+ raise StatusError, 'Command already executed' if output.any?
32
+
33
+ logger.info("Shell command: `#{mask_secrets(command).cyan}`")
34
+
35
+ Open3.popen2e(@command.to_s) do |stdin, out, wait|
36
+ if @stdin_data
37
+ stdin.puts(@stdin_data)
38
+ stdin.close
39
+ end
40
+
41
+ out.each do |line|
42
+ output.push(line)
43
+
44
+ if stream_progress
45
+ print "."
46
+ elsif stream_output
47
+ puts line
48
+ end
49
+
50
+ yield line, wait if block_given?
51
+ end
52
+ puts if stream_progress && !output.empty?
53
+
54
+ fail! if wait.value.exited? && wait.value.exitstatus.nonzero?
55
+
56
+ logger.debug("Shell command output:\n#{string_output}") unless stream_output || output.empty?
57
+ end
58
+
59
+ string_output
60
+ end
61
+
62
+ private
63
+
64
+ attr_reader :logger
65
+
66
+ # Raise error and print output to error log level
67
+ #
68
+ # @return [void]
69
+ def fail!
70
+ logger.error("Shell command output:\n#{string_output}") unless stream_output
71
+ raise StatusError, "Command `#{mask_secrets(command).truncate(100)}` failed! " + "✘".red
72
+ end
73
+
74
+ # Stream only command execution progress and log output when command finished
75
+ #
76
+ # @return [Boolean]
77
+ def stream_progress
78
+ !(Runtime::Env.ci || stream_output)
79
+ end
80
+
81
+ # Stringified command output
82
+ #
83
+ # @return [String]
84
+ def string_output
85
+ mask_secrets(output.join.chomp)
86
+ end
87
+
88
+ # Returns a masked string
89
+ #
90
+ # @param [String] input the string to mask
91
+ # @return [String] The masked string
92
+ def mask_secrets(input)
93
+ @mask_secrets.each_with_object(+input) { |secret, s| s.gsub!(secret, '*****') }.to_s
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Gitlab
4
+ module QA
5
+ module Support
6
+ module Shellout
7
+ module_function
8
+
9
+ def shell(command = nil, stdin_data: nil, mask_secrets: nil, stream_output: false, &block)
10
+ Support::ShellCommand.new(
11
+ command, stdin_data: stdin_data, mask_secrets: mask_secrets, stream_output: stream_output).execute!(&block)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Gitlab
4
4
  module QA
5
- VERSION = '8.4.2'
5
+ VERSION = '8.6.0'
6
6
  end
7
7
  end
data/lib/gitlab/qa.rb CHANGED
@@ -10,7 +10,6 @@ module Gitlab
10
10
  loader.ignore("#{__dir__}/qa/version.rb")
11
11
 
12
12
  loader.inflector.inflect(
13
- 'dev_ee_qa_image' => 'DevEEQAImage',
14
13
  'results_in_testcases' => 'ResultsInTestCases',
15
14
  'postgresql' => 'PostgreSQL',
16
15
  'registry_with_cdn' => 'RegistryWithCDN',
@@ -0,0 +1,41 @@
1
+ ---
2
+ apiVersion: apps/v1
3
+ kind: Deployment
4
+ metadata:
5
+ name: authenticator-deployment
6
+ labels:
7
+ app: authenticator
8
+ spec:
9
+ replicas: 1
10
+ selector:
11
+ matchLabels:
12
+ app: authenticator
13
+ template:
14
+ metadata:
15
+ labels:
16
+ app: authenticator
17
+ spec:
18
+ imagePullSecrets:
19
+ - name: gitlab-registry
20
+ containers:
21
+ - name: authenticator
22
+ image: registry.gitlab.com/gitlab-org/modelops/applied-ml/review-recommender/authenticator:0.1.0
23
+ imagePullPolicy: Always
24
+ ports:
25
+ - containerPort: 8080
26
+ args: []
27
+ env:
28
+ - name: AUTHENTICATOR_SERVICE_PORT
29
+ value: "8080"
30
+ ---
31
+ apiVersion: v1
32
+ kind: Service
33
+ metadata:
34
+ name: authenticator-service
35
+ spec:
36
+ type: NodePort
37
+ ports:
38
+ - port: 8080
39
+ targetPort: 8080
40
+ selector:
41
+ app: authenticator
@@ -0,0 +1,84 @@
1
+ ---
2
+ apiVersion: v1
3
+ kind: Secret
4
+ metadata:
5
+ name: postgres-secret
6
+ type: kubernetes.io/basic-auth
7
+ stringData:
8
+ username: reviewer-recommender
9
+ password: ml4dawin
10
+
11
+ ---
12
+ apiVersion: v1
13
+ kind: PersistentVolumeClaim
14
+ metadata:
15
+ name: postgres-pvc
16
+ spec:
17
+ storageClassName: local-path
18
+ accessModes:
19
+ - ReadWriteOnce
20
+ resources:
21
+ requests:
22
+ storage: 1Gi
23
+
24
+ ---
25
+ apiVersion: apps/v1
26
+ kind: Deployment
27
+ metadata:
28
+ name: postgres-deployment
29
+ spec:
30
+ replicas: 1
31
+ selector:
32
+ matchLabels:
33
+ app: postgres
34
+ template:
35
+ metadata:
36
+ labels:
37
+ app: postgres
38
+ spec:
39
+ containers:
40
+ - name: postgres
41
+ image: postgres:13-alpine
42
+ imagePullPolicy: IfNotPresent
43
+ ports:
44
+ - containerPort: 5432
45
+ volumeMounts:
46
+ - name: postgres-pv
47
+ mountPath: /var/lib/postgresql/data
48
+ subPath: postgres
49
+ resources:
50
+ limits:
51
+ memory: 256Mi
52
+ cpu: 250m
53
+ env:
54
+ - name: POSTGRES_DB
55
+ value: reviewer-recommender
56
+ - name: POSTGRES_USER
57
+ valueFrom:
58
+ secretKeyRef:
59
+ name: postgres-secret
60
+ key: username
61
+ - name: POSTGRES_PASSWORD
62
+ valueFrom:
63
+ secretKeyRef:
64
+ name: postgres-secret
65
+ key: password
66
+ volumes:
67
+ - name: postgres-pv
68
+ persistentVolumeClaim:
69
+ claimName: postgres-pvc
70
+
71
+ ---
72
+ apiVersion: v1
73
+ kind: Service
74
+ metadata:
75
+ name: postgres
76
+ labels:
77
+ app: postgres
78
+ spec:
79
+ type: ClusterIP
80
+ selector:
81
+ app: postgres
82
+ ports:
83
+ - port: 5432
84
+ targetPort: 5432
@@ -0,0 +1,41 @@
1
+ ---
2
+ apiVersion: apps/v1
3
+ kind: Deployment
4
+ metadata:
5
+ name: pubsub-deployment
6
+ labels:
7
+ app: pubsub
8
+ spec:
9
+ replicas: 1
10
+ selector:
11
+ matchLabels:
12
+ app: pubsub
13
+ template:
14
+ metadata:
15
+ labels:
16
+ app: pubsub
17
+ spec:
18
+ containers:
19
+ - name: pubsub
20
+ image: singularities/pubsub-emulator:latest
21
+ imagePullPolicy: IfNotPresent
22
+ env:
23
+ - name: PUBSUB_PROJECT_ID
24
+ value: project-test
25
+ - name: PUBSUB_LISTEN_ADDRESS
26
+ value: 0.0.0.0:8432
27
+
28
+ ---
29
+ apiVersion: v1
30
+ kind: Service
31
+ metadata:
32
+ name: pubsub
33
+ labels:
34
+ app: pubsub
35
+ spec:
36
+ type: ClusterIP
37
+ selector:
38
+ app: pubsub
39
+ ports:
40
+ - port: 8432
41
+ targetPort: 8432