Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-01-05 21:11:38 +00:00
parent 19a051ca1e
commit a981098583
17 changed files with 239 additions and 67 deletions

View file

@ -18,8 +18,10 @@ module Types
description: 'ID of the runner.' description: 'ID of the runner.'
field :description, GraphQL::Types::String, null: true, field :description, GraphQL::Types::String, null: true,
description: 'Description of the runner.' description: 'Description of the runner.'
field :created_at, Types::TimeType, null: true,
description: 'Timestamp of creation of this runner.'
field :contacted_at, Types::TimeType, null: true, field :contacted_at, Types::TimeType, null: true,
description: 'Last contact from the runner.', description: 'Timestamp of last contact from this runner.',
method: :contacted_at method: :contacted_at
field :maximum_timeout, GraphQL::Types::Int, null: true, field :maximum_timeout, GraphQL::Types::Int, null: true,
description: 'Maximum timeout (in seconds) for jobs processed by the runner.' description: 'Maximum timeout (in seconds) for jobs processed by the runner.'

View file

@ -4,8 +4,8 @@
module PreferencesHelper module PreferencesHelper
def layout_choices def layout_choices
[ [
['Fixed', :fixed], [s_('Layout|Fixed'), :fixed],
['Fluid', :fluid] [s_('Layout|Fluid'), :fluid]
] ]
end end
@ -40,9 +40,9 @@ module PreferencesHelper
def project_view_choices def project_view_choices
[ [
['Files and Readme (default)', :files], [s_('ProjectView|Files and Readme (default)'), :files],
['Activity', :activity], [s_('ProjectView|Activity'), :activity],
['Readme', :readme] [s_('ProjectView|Readme'), :readme]
] ]
end end

View file

@ -2,7 +2,7 @@
- @content_class = "limit-container-width" unless fluid_layout - @content_class = "limit-container-width" unless fluid_layout
- user_theme_id = Gitlab::Themes.for_user(@user).id - user_theme_id = Gitlab::Themes.for_user(@user).id
- user_fields = { theme: user_theme_id, gitpod_enabled: @user.gitpod_enabled, sourcegraph_enabled: @user.sourcegraph_enabled }.to_json - user_fields = { theme: user_theme_id, gitpod_enabled: @user.gitpod_enabled, sourcegraph_enabled: @user.sourcegraph_enabled }.to_json
- @themes = Gitlab::Themes::THEMES.to_json - @themes = Gitlab::Themes::available_themes.to_json
- data_attributes = { themes: @themes, integration_views: integration_views.to_json, user_fields: user_fields, body_classes: Gitlab::Themes.body_classes, profile_preferences_path: profile_preferences_path } - data_attributes = { themes: @themes, integration_views: integration_views.to_json, user_fields: user_fields, body_classes: Gitlab::Themes.body_classes, profile_preferences_path: profile_preferences_path }
- Gitlab::Themes.each do |theme| - Gitlab::Themes.each do |theme|

View file

@ -8911,7 +8911,8 @@ Represents the total number of issues and their weights for a particular day.
| <a id="cirunneraccesslevel"></a>`accessLevel` | [`CiRunnerAccessLevel!`](#cirunneraccesslevel) | Access level of the runner. | | <a id="cirunneraccesslevel"></a>`accessLevel` | [`CiRunnerAccessLevel!`](#cirunneraccesslevel) | Access level of the runner. |
| <a id="cirunneractive"></a>`active` | [`Boolean!`](#boolean) | Indicates the runner is allowed to receive jobs. | | <a id="cirunneractive"></a>`active` | [`Boolean!`](#boolean) | Indicates the runner is allowed to receive jobs. |
| <a id="cirunneradminurl"></a>`adminUrl` | [`String`](#string) | Admin URL of the runner. Only available for administrators. | | <a id="cirunneradminurl"></a>`adminUrl` | [`String`](#string) | Admin URL of the runner. Only available for administrators. |
| <a id="cirunnercontactedat"></a>`contactedAt` | [`Time`](#time) | Last contact from the runner. | | <a id="cirunnercontactedat"></a>`contactedAt` | [`Time`](#time) | Timestamp of last contact from this runner. |
| <a id="cirunnercreatedat"></a>`createdAt` | [`Time`](#time) | Timestamp of creation of this runner. |
| <a id="cirunnerdescription"></a>`description` | [`String`](#string) | Description of the runner. | | <a id="cirunnerdescription"></a>`description` | [`String`](#string) | Description of the runner. |
| <a id="cirunnerexecutorname"></a>`executorName` | [`String`](#string) | Executor last advertised by the runner. Available only when feature flag `graphql_ci_runner_executor` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice. | | <a id="cirunnerexecutorname"></a>`executorName` | [`String`](#string) | Executor last advertised by the runner. Available only when feature flag `graphql_ci_runner_executor` is enabled. This flag is disabled by default, because the feature is experimental and is subject to change without notice. |
| <a id="cirunnerid"></a>`id` | [`CiRunnerID!`](#cirunnerid) | ID of the runner. | | <a id="cirunnerid"></a>`id` | [`CiRunnerID!`](#cirunnerid) | ID of the runner. |

View file

@ -4,7 +4,7 @@ group: Authentication & Authorization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
--- ---
# GitLab permissions guide # Implementing permissions
There are multiple types of permissions across GitLab, and when implementing There are multiple types of permissions across GitLab, and when implementing
anything that deals with permissions, all of them should be considered. anything that deals with permissions, all of them should be considered.

View file

@ -7,21 +7,23 @@ module Gitlab
# Struct class representing a single Scheme # Struct class representing a single Scheme
Scheme = Struct.new(:id, :name, :css_class) Scheme = Struct.new(:id, :name, :css_class)
SCHEMES = [ def self.available_schemes
Scheme.new(1, 'White', 'white'), [
Scheme.new(2, 'Dark', 'dark'), Scheme.new(1, s_('SynthaxHighlightingTheme|Light'), 'white'),
Scheme.new(3, 'Solarized Light', 'solarized-light'), Scheme.new(2, s_('SynthaxHighlightingTheme|Dark'), 'dark'),
Scheme.new(4, 'Solarized Dark', 'solarized-dark'), Scheme.new(3, s_('SynthaxHighlightingTheme|Solarized Light'), 'solarized-light'),
Scheme.new(5, 'Monokai', 'monokai'), Scheme.new(4, s_('SynthaxHighlightingTheme|Solarized Dark'), 'solarized-dark'),
Scheme.new(6, 'None', 'none') Scheme.new(5, s_('SynthaxHighlightingTheme|Monokai'), 'monokai'),
].freeze Scheme.new(6, s_('SynthaxHighlightingTheme|None'), 'none')
]
end
# Convenience method to get a space-separated String of all the color scheme # Convenience method to get a space-separated String of all the color scheme
# classes that might be applied to a code block. # classes that might be applied to a code block.
# #
# Returns a String # Returns a String
def self.body_classes def self.body_classes
SCHEMES.collect(&:css_class).uniq.join(' ') available_schemes.collect(&:css_class).uniq.join(' ')
end end
# Get a Scheme by its ID # Get a Scheme by its ID
@ -32,12 +34,12 @@ module Gitlab
# #
# Returns a Scheme # Returns a Scheme
def self.by_id(id) def self.by_id(id)
SCHEMES.detect { |s| s.id == id } || default available_schemes.detect { |s| s.id == id } || default
end end
# Returns the number of defined Schemes # Returns the number of defined Schemes
def self.count def self.count
SCHEMES.size available_schemes.size
end end
# Get the default Scheme # Get the default Scheme
@ -51,7 +53,7 @@ module Gitlab
# #
# Yields the Scheme object # Yields the Scheme object
def self.each(&block) def self.each(&block)
SCHEMES.each(&block) available_schemes.each(&block)
end end
# Get the Scheme for the specified user, or the default # Get the Scheme for the specified user, or the default
@ -68,7 +70,7 @@ module Gitlab
end end
def self.valid_ids def self.valid_ids
SCHEMES.map(&:id) available_schemes.map(&:id)
end end
end end
end end

View file

@ -53,17 +53,11 @@ module Gitlab
params = { params = {
body_stream: file, body_stream: file,
headers: { headers: upload_headers(object, upload_action)
'Content-Length' => object.size.to_s,
'Content-Type' => 'application/octet-stream',
'User-Agent' => GIT_LFS_USER_AGENT
}.merge(upload_action['header'] || {})
} }
authenticated = true if params[:headers].key?('Authorization') url = set_basic_auth_and_extract_lfs_url!(params, upload_action['href'])
params[:basic_auth] = basic_auth unless authenticated rsp = Gitlab::HTTP.put(url, params)
rsp = Gitlab::HTTP.put(upload_action['href'], params)
raise ObjectUploadError.new(http_response: rsp) unless rsp.success? raise ObjectUploadError.new(http_response: rsp) unless rsp.success?
ensure ensure
@ -76,20 +70,51 @@ module Gitlab
headers: build_request_headers(verify_action['header']) headers: build_request_headers(verify_action['header'])
} }
authenticated = true if params[:headers].key?('Authorization') url = set_basic_auth_and_extract_lfs_url!(params, verify_action['href'])
params[:basic_auth] = basic_auth unless authenticated rsp = Gitlab::HTTP.post(url, params)
rsp = Gitlab::HTTP.post(verify_action['href'], params)
raise ObjectVerifyError.new(http_response: rsp) unless rsp.success? raise ObjectVerifyError.new(http_response: rsp) unless rsp.success?
end end
private private
def set_basic_auth_and_extract_lfs_url!(params, raw_url)
authenticated = true if params[:headers].key?('Authorization')
params[:basic_auth] = basic_auth unless authenticated
strip_userinfo = authenticated || params[:basic_auth].present?
lfs_url(raw_url, strip_userinfo)
end
def build_request_headers(extra_headers = nil) def build_request_headers(extra_headers = nil)
DEFAULT_HEADERS.merge(extra_headers || {}) DEFAULT_HEADERS.merge(extra_headers || {})
end end
def upload_headers(object, upload_action)
# This uses the httprb library to handle case-insensitive HTTP headers
headers = ::HTTP::Headers.new
headers.merge!(upload_action['header'])
transfer_encodings = Array(headers['Transfer-Encoding']&.split(',')).map(&:strip)
headers['Content-Length'] = object.size.to_s unless transfer_encodings.include?('chunked')
headers['Content-Type'] = 'application/octet-stream'
headers['User-Agent'] = GIT_LFS_USER_AGENT
headers.to_h
end
def lfs_url(raw_url, strip_userinfo)
# HTTParty will give precedence to the username/password
# specified in the URL. This causes problems with Azure DevOps,
# which includes a username in the URL. Stripping the userinfo
# from the URL allows the provided HTTP Basic Authentication
# credentials to be used.
if strip_userinfo
Gitlab::UrlSanitizer.new(raw_url).sanitized_url
else
raw_url
end
end
attr_reader :credentials attr_reader :credentials
def batch_url def batch_url

View file

@ -13,26 +13,28 @@ module Gitlab
Theme = Struct.new(:id, :name, :css_class, :css_filename, :primary_color) Theme = Struct.new(:id, :name, :css_class, :css_filename, :primary_color)
# All available Themes # All available Themes
THEMES = [ def available_themes
Theme.new(1, 'Indigo', 'ui-indigo', 'theme_indigo', '#292961'), [
Theme.new(6, 'Light Indigo', 'ui-light-indigo', 'theme_light_indigo', '#4b4ba3'), Theme.new(1, s_('NavigationTheme|Indigo'), 'ui-indigo', 'theme_indigo', '#292961'),
Theme.new(4, 'Blue', 'ui-blue', 'theme_blue', '#1a3652'), Theme.new(6, s_('NavigationTheme|Light Indigo'), 'ui-light-indigo', 'theme_light_indigo', '#4b4ba3'),
Theme.new(7, 'Light Blue', 'ui-light-blue', 'theme_light_blue', '#2261a1'), Theme.new(4, s_('NavigationTheme|Blue'), 'ui-blue', 'theme_blue', '#1a3652'),
Theme.new(5, 'Green', 'ui-green', 'theme_green', '#0d4524'), Theme.new(7, s_('NavigationTheme|Light Blue'), 'ui-light-blue', 'theme_light_blue', '#2261a1'),
Theme.new(8, 'Light Green', 'ui-light-green', 'theme_light_green', '#156b39'), Theme.new(5, s_('NavigationTheme|Green'), 'ui-green', 'theme_green', '#0d4524'),
Theme.new(9, 'Red', 'ui-red', 'theme_red', '#691a16'), Theme.new(8, s_('NavigationTheme|Light Green'), 'ui-light-green', 'theme_light_green', '#156b39'),
Theme.new(10, 'Light Red', 'ui-light-red', 'theme_light_red', '#a62e21'), Theme.new(9, s_('NavigationTheme|Red'), 'ui-red', 'theme_red', '#691a16'),
Theme.new(2, 'Dark', 'ui-dark', 'theme_dark', '#303030'), Theme.new(10, s_('NavigationTheme|Light Red'), 'ui-light-red', 'theme_light_red', '#a62e21'),
Theme.new(3, 'Light', 'ui-light', 'theme_light', '#666'), Theme.new(2, s_('NavigationTheme|Dark'), 'ui-dark', 'theme_dark', '#303030'),
Theme.new(11, 'Dark Mode (alpha)', 'gl-dark', nil, '#303030') Theme.new(3, s_('NavigationTheme|Light'), 'ui-light', 'theme_light', '#666'),
].freeze Theme.new(11, s_('NavigationTheme|Dark Mode (alpha)'), 'gl-dark', nil, '#303030')
]
end
# Convenience method to get a space-separated String of all the theme # Convenience method to get a space-separated String of all the theme
# classes that might be applied to the `body` element # classes that might be applied to the `body` element
# #
# Returns a String # Returns a String
def body_classes def body_classes
THEMES.collect(&:css_class).uniq.join(' ') available_themes.collect(&:css_class).uniq.join(' ')
end end
# Get a Theme by its ID # Get a Theme by its ID
@ -43,12 +45,12 @@ module Gitlab
# #
# Returns a Theme # Returns a Theme
def by_id(id) def by_id(id)
THEMES.detect { |t| t.id == id } || default available_themes.detect { |t| t.id == id } || default
end end
# Returns the number of defined Themes # Returns the number of defined Themes
def count def count
THEMES.size available_themes.size
end end
# Get the default Theme # Get the default Theme
@ -62,7 +64,7 @@ module Gitlab
# #
# Yields the Theme object # Yields the Theme object
def each(&block) def each(&block)
THEMES.each(&block) available_themes.each(&block)
end end
# Get the Theme for the specified user, or the default # Get the Theme for the specified user, or the default
@ -79,7 +81,7 @@ module Gitlab
end end
def self.valid_ids def self.valid_ids
THEMES.map(&:id) available_themes.map(&:id)
end end
private private
@ -87,7 +89,7 @@ module Gitlab
def default_id def default_id
@default_id ||= begin @default_id ||= begin
id = Gitlab.config.gitlab.default_theme.to_i id = Gitlab.config.gitlab.default_theme.to_i
theme_ids = THEMES.map(&:id) theme_ids = available_themes.map(&:id)
theme_ids.include?(id) ? id : APPLICATION_DEFAULT theme_ids.include?(id) ? id : APPLICATION_DEFAULT
end end

View file

@ -20827,6 +20827,12 @@ msgstr ""
msgid "Launch a ready-to-code development environment for your project." msgid "Launch a ready-to-code development environment for your project."
msgstr "" msgstr ""
msgid "Layout|Fixed"
msgstr ""
msgid "Layout|Fluid"
msgstr ""
msgid "Lead Time" msgid "Lead Time"
msgstr "" msgstr ""
@ -23274,6 +23280,39 @@ msgstr ""
msgid "Navigation bar" msgid "Navigation bar"
msgstr "" msgstr ""
msgid "NavigationTheme|Blue"
msgstr ""
msgid "NavigationTheme|Dark"
msgstr ""
msgid "NavigationTheme|Dark Mode (alpha)"
msgstr ""
msgid "NavigationTheme|Green"
msgstr ""
msgid "NavigationTheme|Indigo"
msgstr ""
msgid "NavigationTheme|Light"
msgstr ""
msgid "NavigationTheme|Light Blue"
msgstr ""
msgid "NavigationTheme|Light Green"
msgstr ""
msgid "NavigationTheme|Light Indigo"
msgstr ""
msgid "NavigationTheme|Light Red"
msgstr ""
msgid "NavigationTheme|Red"
msgstr ""
msgid "Nav|Help" msgid "Nav|Help"
msgstr "" msgstr ""
@ -28117,6 +28156,15 @@ msgstr ""
msgid "ProjectTemplates|iOS (Swift)" msgid "ProjectTemplates|iOS (Swift)"
msgstr "" msgstr ""
msgid "ProjectView|Activity"
msgstr ""
msgid "ProjectView|Files and Readme (default)"
msgstr ""
msgid "ProjectView|Readme"
msgstr ""
msgid "Projects" msgid "Projects"
msgstr "" msgstr ""
@ -34495,6 +34543,24 @@ msgstr ""
msgid "Syntax is incorrect." msgid "Syntax is incorrect."
msgstr "" msgstr ""
msgid "SynthaxHighlightingTheme|Dark"
msgstr ""
msgid "SynthaxHighlightingTheme|Light"
msgstr ""
msgid "SynthaxHighlightingTheme|Monokai"
msgstr ""
msgid "SynthaxHighlightingTheme|None"
msgstr ""
msgid "SynthaxHighlightingTheme|Solarized Dark"
msgstr ""
msgid "SynthaxHighlightingTheme|Solarized Light"
msgstr ""
msgid "System" msgid "System"
msgstr "" msgstr ""

View file

@ -6,8 +6,6 @@ module QA
module_function module_function
def while_signed_in(as: nil, address: :gitlab, admin: false) def while_signed_in(as: nil, address: :gitlab, admin: false)
Page::Main::Menu.perform(&:sign_out_if_signed_in)
sign_in(as: as, address: address, admin: admin) sign_in(as: as, address: address, admin: admin)
result = yield result = yield
@ -23,9 +21,10 @@ module QA
end end
def sign_in(as: nil, address: :gitlab, skip_page_validation: false, admin: false) def sign_in(as: nil, address: :gitlab, skip_page_validation: false, admin: false)
Page::Main::Login.perform { |p| p.redirect_to_login_page(address) }
unless Page::Main::Login.perform(&:on_login_page?) unless Page::Main::Login.perform(&:on_login_page?)
Page::Main::Menu.perform(&:sign_out) if Page::Main::Menu.perform(&:signed_in?) Page::Main::Menu.perform(&:sign_out) if Page::Main::Menu.perform(&:signed_in?)
Runtime::Browser.visit(address, Page::Main::Login)
end end
Page::Main::Login.perform do |login| Page::Main::Login.perform do |login|

View file

@ -386,6 +386,10 @@ module QA
end end
end end
def current_host
URI(page.current_url).host
end
def self.path def self.path
raise NotImplementedError raise NotImplementedError
end end

View file

@ -156,6 +156,11 @@ module QA
sign_in_using_credentials(user: user) sign_in_using_credentials(user: user)
end end
def redirect_to_login_page(address)
desired_host = URI(Runtime::Scenario.send("#{address}_address")).host
Runtime::Browser.visit(address, Page::Main::Login) if desired_host != current_host
end
private private
def sign_in_using_gitlab_credentials(user:, skip_page_validation: false) def sign_in_using_gitlab_credentials(user:, skip_page_validation: false)

View file

@ -9,7 +9,7 @@ RSpec.describe GitlabSchema.types['CiRunner'] do
it 'contains attributes related to a runner' do it 'contains attributes related to a runner' do
expected_fields = %w[ expected_fields = %w[
id description contacted_at maximum_timeout access_level active status id description created_at contacted_at maximum_timeout access_level active status
version short_sha revision locked run_untagged ip_address runner_type tag_list version short_sha revision locked run_untagged ip_address runner_type tag_list
project_count job_count admin_url user_permissions executor_name project_count job_count admin_url user_permissions executor_name
] ]

View file

@ -15,7 +15,7 @@ RSpec.describe Gitlab::ColorSchemes do
describe '.by_id' do describe '.by_id' do
it 'returns a scheme by its ID' do it 'returns a scheme by its ID' do
expect(described_class.by_id(1).name).to eq 'White' expect(described_class.by_id(1).name).to eq 'Light'
expect(described_class.by_id(4).name).to eq 'Solarized Dark' expect(described_class.by_id(4).name).to eq 'Solarized Dark'
end end
end end

View file

@ -114,6 +114,52 @@ RSpec.describe Gitlab::Lfs::Client do
end end
end end
context 'server returns 200 OK with a chunked transfer request' do
before do
upload_action['header']['Transfer-Encoding'] = 'gzip, chunked'
end
it "makes an HTTP PUT with expected parameters" do
stub_upload(object: object, headers: upload_action['header'], chunked_transfer: true).to_return(status: 200)
lfs_client.upload!(object, upload_action, authenticated: true)
end
end
context 'server returns 200 OK with a username and password in the URL' do
let(:base_url) { "https://someuser:testpass@example.com" }
it "makes an HTTP PUT with expected parameters" do
stub_upload(
object: object,
headers: basic_auth_headers.merge(upload_action['header']),
url: "https://example.com/some/file"
).to_return(status: 200)
lfs_client.upload!(object, upload_action, authenticated: true)
end
end
context 'no credentials in client' do
subject(:lfs_client) { described_class.new(base_url, credentials: {}) }
context 'server returns 200 OK with credentials in URL' do
let(:creds) { 'someuser:testpass' }
let(:base_url) { "https://#{creds}@example.com" }
let(:auth_headers) { { 'Authorization' => "Basic #{Base64.strict_encode64(creds)}" } }
it "makes an HTTP PUT with expected parameters" do
stub_upload(
object: object,
headers: auth_headers.merge(upload_action['header']),
url: "https://example.com/some/file"
).to_return(status: 200)
lfs_client.upload!(object, upload_action, authenticated: true)
end
end
end
context 'server returns 200 OK to an unauthenticated request' do context 'server returns 200 OK to an unauthenticated request' do
it "makes an HTTP PUT with expected parameters" do it "makes an HTTP PUT with expected parameters" do
stub = stub_upload( stub = stub_upload(
@ -171,16 +217,21 @@ RSpec.describe Gitlab::Lfs::Client do
end end
end end
def stub_upload(object:, headers:) def stub_upload(object:, headers:, url: upload_action['href'], chunked_transfer: false)
headers = { headers = {
'Content-Type' => 'application/octet-stream', 'Content-Type' => 'application/octet-stream',
'Content-Length' => object.size.to_s,
'User-Agent' => git_lfs_user_agent 'User-Agent' => git_lfs_user_agent
}.merge(headers) }.merge(headers)
stub_request(:put, upload_action['href']).with( if chunked_transfer
headers['Transfer-Encoding'] = 'gzip, chunked'
else
headers['Content-Length'] = object.size.to_s
end
stub_request(:put, url).with(
body: object.file.read, body: object.file.read,
headers: headers.merge('Content-Length' => object.size.to_s) headers: headers
) )
end end
end end
@ -196,11 +247,25 @@ RSpec.describe Gitlab::Lfs::Client do
end end
end end
context 'server returns 200 OK with a username and password in the URL' do
let(:base_url) { "https://someuser:testpass@example.com" }
it "makes an HTTP PUT with expected parameters" do
stub_verify(
object: object,
headers: basic_auth_headers.merge(verify_action['header']),
url: "https://example.com/some/file/verify"
).to_return(status: 200)
lfs_client.verify!(object, verify_action, authenticated: true)
end
end
context 'server returns 200 OK to an unauthenticated request' do context 'server returns 200 OK to an unauthenticated request' do
it "makes an HTTP POST with expected parameters" do it "makes an HTTP POST with expected parameters" do
stub = stub_verify( stub = stub_verify(
object: object, object: object,
headers: basic_auth_headers.merge(upload_action['header']) headers: basic_auth_headers.merge(verify_action['header'])
).to_return(status: 200) ).to_return(status: 200)
lfs_client.verify!(object, verify_action, authenticated: false) lfs_client.verify!(object, verify_action, authenticated: false)
@ -238,14 +303,14 @@ RSpec.describe Gitlab::Lfs::Client do
end end
end end
def stub_verify(object:, headers:) def stub_verify(object:, headers:, url: verify_action['href'])
headers = { headers = {
'Accept' => git_lfs_content_type, 'Accept' => git_lfs_content_type,
'Content-Type' => git_lfs_content_type, 'Content-Type' => git_lfs_content_type,
'User-Agent' => git_lfs_user_agent 'User-Agent' => git_lfs_user_agent
}.merge(headers) }.merge(headers)
stub_request(:post, verify_action['href']).with( stub_request(:post, url).with(
body: object.to_json(only: [:oid, :size]), body: object.to_json(only: [:oid, :size]),
headers: headers headers: headers
) )

View file

@ -28,7 +28,7 @@ RSpec.describe Gitlab::Themes, lib: true do
it 'prevents an infinite loop when configuration default is invalid' do it 'prevents an infinite loop when configuration default is invalid' do
default = described_class::APPLICATION_DEFAULT default = described_class::APPLICATION_DEFAULT
themes = described_class::THEMES themes = described_class.available_themes
config = double(default_theme: 0).as_null_object config = double(default_theme: 0).as_null_object
allow(Gitlab).to receive(:config).and_return(config) allow(Gitlab).to receive(:config).and_return(config)

View file

@ -57,6 +57,7 @@ RSpec.describe 'Query.runner(id)' do
expect(runner_data).to match a_hash_including( expect(runner_data).to match a_hash_including(
'id' => "gid://gitlab/Ci::Runner/#{runner.id}", 'id' => "gid://gitlab/Ci::Runner/#{runner.id}",
'description' => runner.description, 'description' => runner.description,
'createdAt' => runner.created_at&.iso8601,
'contactedAt' => runner.contacted_at&.iso8601, 'contactedAt' => runner.contacted_at&.iso8601,
'version' => runner.version, 'version' => runner.version,
'shortSha' => runner.short_sha, 'shortSha' => runner.short_sha,