gitlab-qa 8.4.2 → 8.6.0

Sign up to get free protection for your applications and to get access to all the features.
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