gitlab-qa 6.8.0 → 6.12.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: daf050b7d871f8eefdc1fa68b052608c11ee186b927fe89accfceca15291ed45
4
- data.tar.gz: 4510e98db8e41c11a1585070a39cd19769384917cff551195942955974dcd78d
3
+ metadata.gz: a7db5ca406c7143f6b4b8ac2d5061080f52157dbe77f23459fdf15919cc24209
4
+ data.tar.gz: b0dca304397f7c373ca94b41936f8d04db818b797dc9a09e05e31accfd8a9cfd
5
5
  SHA512:
6
- metadata.gz: 3a3a6dc22aac1a77fe46f1379a43b489d08cc771b38ea629f9ff3a8f24fd9886f767ed3b3ca8aa18bfeabadc9019aefe2933261c969167e6c8e95f7f75e2c6a1
7
- data.tar.gz: c612e3b42691a28864bcf703fdf89cbbf57f75817341f867d1e8486a25adcbfcf262f3506157841d734813e699e628620dd524af22b4f8da17c689a96c6116cf
6
+ metadata.gz: 25678e888d7a338ef9f54269927e16ab6d5f60bc4b37175185bda64174689d9aecf40ac35c7d31be15e6fb1305527604f4667f09aa6c89f42ba4e02c7187a68d
7
+ data.tar.gz: ff1c2808b0030677ba8420444e4cb303b0d58d6751511bef90a8bcbea98df6a98e1efea83945d7b6488f076eb8f978519198b4938dc9b99503bd97c0d2b9ea57
@@ -49,9 +49,9 @@ variables:
49
49
  QA_CAN_TEST_GIT_PROTOCOL_V2: "true"
50
50
  QA_CAN_TEST_PRAEFECT: "false"
51
51
  QA_TESTCASES_REPORTING_PROJECT: "gitlab-org/quality/testcases"
52
- QA_FAILURES_REPORTING_PROJECT: "gitlab-org/gitlab"
52
+ QA_FAILURES_REPORTING_PROJECT: "rymai/gitlab-qa-issues"
53
53
  # The --dry-run or --max-diff-ratio option can be set to modify the behavior of `exe/gitlab-qa-report --relate-failure-issue` without releasing a new gem version.
54
- QA_FAILURES_REPORTER_OPTIONS: "--dry-run"
54
+ QA_FAILURES_REPORTER_OPTIONS: ""
55
55
  QA_TESTCASE_SESSIONS_PROJECT: "gitlab-org/quality/testcase-sessions"
56
56
 
57
57
  .check-base:
@@ -95,8 +95,8 @@ release:
95
95
  reports:
96
96
  junit: gitlab-qa-run-*/**/rspec-*.xml
97
97
  script:
98
- - 'echo "Running: exe/gitlab-qa ${QA_SCENARIO:=Test::Instance::Image} ${RELEASE:=$DEFAULT_RELEASE} -- $QA_TESTS $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS"'
99
- - exe/gitlab-qa ${QA_SCENARIO:=Test::Instance::Image} ${RELEASE:=$DEFAULT_RELEASE} -- $QA_TESTS $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS || test_run_exit_code=$?
98
+ - 'echo "Running: exe/gitlab-qa ${QA_SCENARIO:=Test::Instance::Image} ${RELEASE:=$DEFAULT_RELEASE} $GITLAB_QA_OPTS -- $QA_TESTS $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS"'
99
+ - exe/gitlab-qa ${QA_SCENARIO:=Test::Instance::Image} ${RELEASE:=$DEFAULT_RELEASE} $GITLAB_QA_OPTS -- $QA_TESTS $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS || test_run_exit_code=$?
100
100
  - exe/gitlab-qa-report --update-screenshot-path "gitlab-qa-run-*/**/rspec-*.xml"
101
101
  - export GITLAB_QA_ACCESS_TOKEN="$GITLAB_QA_PRODUCTION_ACCESS_TOKEN"
102
102
  - if [ "$TOP_UPSTREAM_SOURCE_REF" == "master" ] || [[ "$TOP_UPSTREAM_SOURCE_JOB" == https://ops.gitlab.net* ]]; then exe/gitlab-qa-report --report-in-issues "gitlab-qa-run-*/**/rspec-*.json" --project "$QA_TESTCASES_REPORTING_PROJECT" || true; fi
@@ -175,8 +175,8 @@ ee:sanity-framework:
175
175
  # The custom jobs are for manually running specific/alternative tests in MRs, so we don't report them in issues
176
176
  ce:custom-parallel:
177
177
  script:
178
- - 'echo "Running: exe/gitlab-qa ${QA_SCENARIO:=Test::Instance::Image} ${RELEASE:=$DEFAULT_RELEASE} -- $QA_TESTS $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS"'
179
- - exe/gitlab-qa ${QA_SCENARIO:=Test::Instance::Image} ${RELEASE:=$DEFAULT_RELEASE} -- $QA_TESTS $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS
178
+ - 'echo "Running: exe/gitlab-qa ${QA_SCENARIO:=Test::Instance::Image} ${RELEASE:=$DEFAULT_RELEASE} $GITLAB_QA_OPTS -- $QA_TESTS $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS"'
179
+ - exe/gitlab-qa ${QA_SCENARIO:=Test::Instance::Image} ${RELEASE:=$DEFAULT_RELEASE} $GITLAB_QA_OPTS -- $QA_TESTS $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS
180
180
  extends:
181
181
  - .test
182
182
  - .high-capacity
@@ -187,8 +187,8 @@ ce:custom-parallel:
187
187
 
188
188
  ee:custom-parallel:
189
189
  script:
190
- - 'echo "Running: exe/gitlab-qa ${QA_SCENARIO:=Test::Instance::Image} ${RELEASE:=$DEFAULT_RELEASE} -- $QA_TESTS $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS"'
191
- - exe/gitlab-qa ${QA_SCENARIO:=Test::Instance::Image} ${RELEASE:=$DEFAULT_RELEASE} -- $QA_TESTS $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS
190
+ - 'echo "Running: exe/gitlab-qa ${QA_SCENARIO:=Test::Instance::Image} ${RELEASE:=$DEFAULT_RELEASE} $GITLAB_QA_OPTS -- $QA_TESTS $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS"'
191
+ - exe/gitlab-qa ${QA_SCENARIO:=Test::Instance::Image} ${RELEASE:=$DEFAULT_RELEASE} $GITLAB_QA_OPTS -- $QA_TESTS $QA_RSPEC_TAGS $RSPEC_REPORT_OPTS
192
192
  extends:
193
193
  - .test
194
194
  - .high-capacity
@@ -4,7 +4,7 @@
4
4
 
5
5
  The [maven repository spec](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/qa/specs/features/ee/browser_ui/5_package/maven_repository_spec.rb) creates a Maven artifact and links it to a GitLab project. The artifact is created within a [Maven docker image](https://gitlab.com/gitlab-org/gitlab/-/blob/master/qa/qa/service/docker_run/maven.rb#L8).
6
6
 
7
- Using `gitlab-qa` to run these tests reduces the liklihood of network errors between the maven container and GitLab instance.
7
+ Using `gitlab-qa` to run these tests reduces the likelihood of network errors between the maven container and GitLab instance.
8
8
 
9
9
  To run this with `gitlab-qa` you can use the `Test::Instance::Image` that is needed for your test. For example:
10
10
 
@@ -84,6 +84,7 @@ All environment variables used by GitLab QA should be defined in [`lib/gitlab/qa
84
84
  | `JIRA_ADMIN_PASSWORD` |- | Password for authenticating with Jira server as admin. | No|
85
85
  | `CACHE_NAMESPACE_NAME` | `true` | Cache namespace name for groups. | No|
86
86
  | `DEPLOY_VERSION` |- | The version of GitLab being tested against. | No|
87
+ | `GITLAB_QA_USER_AGENT` |- | The browser user-agent to use instead of the default Chrome user-agent. | No|
87
88
 
88
89
  ## [Supported Remote Grid environment variables](./running_against_remote_grid.md)
89
90
 
@@ -27,8 +27,8 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency 'rubocop', '~> 0.82.0'
28
28
  spec.add_development_dependency 'rubocop-rspec', '~> 1.36'
29
29
  spec.add_development_dependency 'webmock', '3.7.0'
30
- spec.add_runtime_dependency 'activesupport', '~> 6.0.2'
31
- spec.add_runtime_dependency 'gitlab', '~> 4.11.0'
30
+ spec.add_runtime_dependency 'activesupport', '~> 6.0.2'
31
+ spec.add_runtime_dependency 'gitlab', '~> 4.16.1'
32
32
  spec.add_runtime_dependency 'http', '4.3.0'
33
33
  spec.add_runtime_dependency 'nokogiri', '~> 1.10'
34
34
  spec.add_runtime_dependency 'table_print', '1.5.6'
@@ -53,6 +53,7 @@ module Gitlab
53
53
 
54
54
  def prepare
55
55
  prepare_docker_image
56
+ prepare_docker_container
56
57
  prepare_network
57
58
  end
58
59
 
@@ -70,6 +71,12 @@ module Gitlab
70
71
  docker.network_create(network)
71
72
  end
72
73
 
74
+ def prepare_docker_container
75
+ return unless docker.container_exists?(name)
76
+
77
+ docker.remove(name)
78
+ end
79
+
73
80
  def start # rubocop:disable Metrics/AbcSize
74
81
  docker.run(image, tag) do |command|
75
82
  command << "-d"
@@ -63,6 +63,14 @@ module Gitlab
63
63
  Docker::Command.execute("rm -f #{name}")
64
64
  end
65
65
 
66
+ def container_exists?(name)
67
+ Docker::Command.execute("container inspect #{name}")
68
+ rescue Docker::Shellout::StatusError
69
+ false
70
+ else
71
+ true
72
+ end
73
+
66
74
  def network_exists?(name)
67
75
  Docker::Command.execute("network inspect #{name}")
68
76
  rescue Docker::Shellout::StatusError
@@ -161,11 +161,11 @@ module Gitlab
161
161
  end
162
162
 
163
163
  def generate_test_job(tests_with_same_testcase)
164
- tests_with_same_testcase.map(&:ci_job_url).uniq.map do |ci_job_url|
165
- ci_job_id = ci_job_url[/\d+\z/]
164
+ tests_with_same_testcase.map do |test|
165
+ ci_job_id = test.ci_job_url[/\d+\z/]
166
166
 
167
- "[#{ci_job_id}](#{ci_job_url})"
168
- end.join(', ')
167
+ "[#{ci_job_id}](#{test.ci_job_url})#{' ~"quarantine"' if test.quarantine?}"
168
+ end.uniq.join(', ')
169
169
  end
170
170
 
171
171
  def generate_test_status(tests_with_same_testcase)
@@ -59,7 +59,7 @@ module Gitlab
59
59
 
60
60
  def find_issue_discussions(iid:)
61
61
  handle_gitlab_client_exceptions do
62
- Gitlab.issue_discussions(project, iid, order_by: 'created_at', sort: 'asc')
62
+ Gitlab.issue_discussions(project, iid, order_by: 'created_at', sort: 'asc').auto_paginate
63
63
  end
64
64
  end
65
65
 
@@ -109,6 +109,9 @@ module Gitlab
109
109
  pipeline = QA::Runtime::Env.pipeline_from_project_name
110
110
  channel = pipeline == "canary" ? "qa-production" : "qa-#{pipeline}"
111
111
  error_msg = warn_exception(e)
112
+
113
+ return unless QA::Runtime::Env.ci_commit_ref_name == 'master'
114
+
112
115
  slack_options = {
113
116
  channel: channel,
114
117
  icon_emoji: ':ci_failing:',
@@ -10,7 +10,7 @@ module Gitlab
10
10
  # Uses the API to create or update GitLab issues with the results of tests from RSpec report files.
11
11
  class RelateFailureIssue < ReportAsIssue
12
12
  DEFAULT_MAX_DIFF_RATIO_FOR_DETECTION = 0.05
13
- STACKTRACE_REGEX = %r{### Stack trace\s*(```)\s*.*(Failure/Error: .+)(\1)}m.freeze
13
+ STACKTRACE_REGEX = %r{### Stack trace\s*(```)\s*.*(Failure/Error:.+)(\1)}m.freeze
14
14
  NEW_ISSUE_LABELS = Set.new(%w[QA Quality test failure::investigating priority::2]).freeze
15
15
 
16
16
  MultipleIssuesFound = Class.new(StandardError)
@@ -47,6 +47,7 @@ module Gitlab
47
47
  issue = find_or_create_issue(test)
48
48
  return unless issue
49
49
 
50
+ update_labels(issue, test)
50
51
  post_failed_job_note(issue, test)
51
52
  puts " => Marked #{issue.web_url} as related to #{test.testcase}."
52
53
  rescue MultipleIssuesFound => e
@@ -81,17 +82,15 @@ module Gitlab
81
82
  # Search with the `search` param returns 500 errors, so we filter by ~QA and then filter further in Ruby
82
83
  failure_issues(test).each_with_object({}) do |issue, memo|
83
84
  relevant_issue_stacktrace = find_issue_stacktrace(issue)
84
- unless relevant_issue_stacktrace
85
- puts " => [DEBUG] Found issue #{issue.web_url} but stacktrace doesn't match."
86
- next
87
- end
85
+ next unless relevant_issue_stacktrace
88
86
 
89
87
  distance = ld.call(first_test_failure_stacktrace, relevant_issue_stacktrace)
90
88
  diff_ratio = (distance.to_f / first_test_failure_stacktrace.size).round(3)
91
89
  if diff_ratio <= max_diff_ratio
90
+ puts " => [DEBUG] Issue #{issue} has an acceptable diff ratio of #{(diff_ratio * 100).round(2)}%."
92
91
  memo[issue] = diff_ratio
93
92
  else
94
- puts " => [DEBUG] Found issue #{issue.web_url} but stacktrace is too different (#{(diff_ratio * 100).round(2)}%)."
93
+ puts " => [DEBUG] Found issue #{issue.web_url} but stacktraces are too different (#{(diff_ratio * 100).round(2)}%)."
95
94
  end
96
95
  end
97
96
  end
@@ -102,7 +101,7 @@ module Gitlab
102
101
  if issue_stacktrace_match
103
102
  issue_stacktrace_match[2].gsub(/^#.*$/, '').strip
104
103
  else
105
- puts "\n => Stacktrace couldn't be found for #{issue.web_url}:\n\n#{issue.description}\n\n----------------------------------\n"
104
+ puts " => [DEBUG] Stacktrace couldn't be found for #{issue.web_url}:\n\n#{issue.description}\n\n----------------------------------\n"
106
105
  end
107
106
  end
108
107
 
@@ -123,16 +122,45 @@ module Gitlab
123
122
  end
124
123
 
125
124
  def new_issue_description(test)
126
- super + "\n\n### Stack trace\n\n```\n#{test.failures.first['message_lines'].join("\n")}\n```"
125
+ super + [
126
+ "\n\n### Stack trace",
127
+ "```\n#{test.failures.first['message_lines'].join("\n")}\n```",
128
+ "First happened in #{test.ci_job_url}."
129
+ ].join("\n\n")
130
+ end
131
+
132
+ def deploy_environment_label
133
+ environment = Runtime::Env.deploy_environment
134
+
135
+ case environment
136
+ when 'production'
137
+ 'found:gitlab.com'
138
+ when 'canary', 'staging'
139
+ "found:#{environment}.gitlab.com"
140
+ when 'preprod'
141
+ 'found:pre.gitlab.com'
142
+ when 'staging-orchestrated', 'nightly', 'master'
143
+ "found:#{environment}"
144
+ else
145
+ raise "No `found:*` label for the `#{environment}` environment!"
146
+ end
127
147
  end
128
148
 
129
149
  def new_issue_labels(test)
130
150
  NEW_ISSUE_LABELS + up_to_date_labels(test: test)
131
151
  end
132
152
 
153
+ def up_to_date_labels(test:, issue: nil)
154
+ super << deploy_environment_label
155
+ end
156
+
133
157
  def post_failed_job_note(issue, test)
134
158
  gitlab.create_issue_note(iid: issue.iid, note: "/relate #{test.testcase}")
135
159
  end
160
+
161
+ def new_issue_title(test)
162
+ "Failure in #{super}"
163
+ end
136
164
  end
137
165
  end
138
166
  end
@@ -28,6 +28,10 @@ module Gitlab
28
28
  raise NotImplementedError
29
29
  end
30
30
 
31
+ def new_issue_title(test)
32
+ "#{partial_file_path(test.file)} | #{search_safe(test.name)}".strip
33
+ end
34
+
31
35
  def new_issue_description(test)
32
36
  "### Full description\n\n#{search_safe(test.name)}\n\n### File path\n\n#{test.file}"
33
37
  end
@@ -76,7 +80,7 @@ module Gitlab
76
80
  gitlab.create_issue(
77
81
  title: title_from_test(test),
78
82
  description: new_issue_description(test),
79
- labels: new_issue_labels(test)
83
+ labels: new_issue_labels(test).to_a
80
84
  )
81
85
  end
82
86
 
@@ -113,7 +117,7 @@ module Gitlab
113
117
  end
114
118
 
115
119
  def title_from_test(test)
116
- title = "#{partial_file_path(test.file)} | #{search_safe(test.name)}".strip
120
+ title = new_issue_title(test)
117
121
 
118
122
  return title unless title.length > MAX_TITLE_LENGTH
119
123
 
@@ -25,8 +25,6 @@ module Gitlab
25
25
  end
26
26
 
27
27
  def report_test(test)
28
- return if test.skipped
29
-
30
28
  puts "Reporting test: #{test.file} | #{test.name}"
31
29
 
32
30
  issue = find_issue(test)
@@ -34,16 +32,23 @@ module Gitlab
34
32
  if issue
35
33
  puts "Found existing issue: #{issue.web_url}"
36
34
  else
35
+ # Don't create new issues for skipped tests
36
+ return if test.skipped
37
+
37
38
  issue = create_issue(test)
38
39
  puts "Created new issue: #{issue.web_url}"
39
40
  end
40
41
 
41
42
  test.testcase ||= issue.web_url
42
43
 
43
- update_labels(issue, test)
44
- note_status(issue, test)
44
+ labels_updated = update_labels(issue, test)
45
+ note_posted = note_status(issue, test)
45
46
 
46
- puts "Issue updated"
47
+ if labels_updated || note_posted
48
+ puts "Issue updated."
49
+ else
50
+ puts "Test passed, no update needed."
51
+ end
47
52
  end
48
53
 
49
54
  def find_issue(test)
@@ -79,7 +84,8 @@ module Gitlab
79
84
  end
80
85
 
81
86
  def note_status(issue, test)
82
- return if test.failures.empty?
87
+ return false if test.skipped
88
+ return false if test.failures.empty?
83
89
 
84
90
  note = note_content(test)
85
91
 
@@ -88,6 +94,8 @@ module Gitlab
88
94
  end
89
95
 
90
96
  gitlab.create_issue_note(iid: issue.iid, note: note)
97
+
98
+ true
91
99
  end
92
100
 
93
101
  def note_content(test)
@@ -125,11 +133,7 @@ module Gitlab
125
133
  end
126
134
 
127
135
  def error_and_stack_trace(text)
128
- result = text.strip[/Error:(.*)/m, 1].to_s
129
-
130
- warn "Could not find `Error:` in text: #{text}" if result.empty?
131
-
132
- result
136
+ text.strip[/Error:(.*)/m, 1].to_s
133
137
  end
134
138
  end
135
139
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_support/core_ext/object/blank'
4
+
3
5
  module Gitlab
4
6
  module QA
5
7
  module Report
@@ -78,6 +80,13 @@ module Gitlab
78
80
  report['failure_issue'] = new_failure_issue
79
81
  end
80
82
 
83
+ def quarantine?
84
+ # The value for 'quarantine' could be nil, a hash, a string,
85
+ # or true (if the test just has the :quarantine tag)
86
+ # But any non-nil or false value should means the test is in quarantine
87
+ report['quarantine'].present?
88
+ end
89
+
81
90
  private
82
91
 
83
92
  # rubocop:disable Metrics/AbcSize
@@ -8,6 +8,7 @@ module Gitlab
8
8
 
9
9
  # Variables that are used in tests and are passed through to the docker container that executes the tests.
10
10
  # These variables should be listed in /docs/what_tests_can_be_run.md#supported-gitlab-environment-variables
11
+ # unless they're defined elsewhere (e.g.: https://docs.gitlab.com/ee/ci/variables/predefined_variables.html)
11
12
  ENV_VARIABLES = {
12
13
  'QA_REMOTE_GRID' => :remote_grid,
13
14
  'QA_REMOTE_GRID_USERNAME' => :remote_grid_username,
@@ -68,6 +69,7 @@ module Gitlab
68
69
  'CI_SERVER_PERSONAL_ACCESS_TOKEN' => :ci_server_personal_access_token,
69
70
  'CI_NODE_INDEX' => :ci_node_index,
70
71
  'CI_NODE_TOTAL' => :ci_node_total,
72
+ 'CI_PROJECT_NAME' => :ci_project_name,
71
73
  'GITLAB_CI' => :gitlab_ci,
72
74
  'QA_SKIP_PULL' => :qa_skip_pull,
73
75
  'ELASTIC_URL' => :elastic_url,
@@ -83,7 +85,8 @@ module Gitlab
83
85
  'JIRA_ADMIN_USERNAME' => :jira_admin_username,
84
86
  'JIRA_ADMIN_PASSWORD' => :jira_admin_password,
85
87
  'CACHE_NAMESPACE_NAME' => :cache_namespace_name,
86
- 'DEPLOY_VERSION' => :deploy_version
88
+ 'DEPLOY_VERSION' => :deploy_version,
89
+ 'GITLAB_QA_USER_AGENT' => :gitlab_qa_user_agent
87
90
  }.freeze
88
91
 
89
92
  ENV_VARIABLES.each do |env_name, method_name|
@@ -137,6 +140,10 @@ module Gitlab
137
140
  ENV['CI_PROJECT_NAME']
138
141
  end
139
142
 
143
+ def ci_commit_ref_name
144
+ ENV['CI_COMMIT_REF_NAME']
145
+ end
146
+
140
147
  def pipeline_from_project_name
141
148
  if ci_project_name.to_s.start_with?('gitlab-qa')
142
149
  if ENV['TOP_UPSTREAM_SOURCE_JOB'].to_s.start_with?('https://ops.gitlab.net')
@@ -1,5 +1,5 @@
1
1
  module Gitlab
2
2
  module QA
3
- VERSION = '6.8.0'.freeze
3
+ VERSION = '6.12.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gitlab-qa
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.8.0
4
+ version: 6.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Grzegorz Bizon
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-11-10 00:00:00.000000000 Z
11
+ date: 2020-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: climate_control
@@ -142,14 +142,14 @@ dependencies:
142
142
  requirements:
143
143
  - - "~>"
144
144
  - !ruby/object:Gem::Version
145
- version: 4.11.0
145
+ version: 4.16.1
146
146
  type: :runtime
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
150
  - - "~>"
151
151
  - !ruby/object:Gem::Version
152
- version: 4.11.0
152
+ version: 4.16.1
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: http
155
155
  requirement: !ruby/object:Gem::Requirement