Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-06-25 12:09:00 +00:00
parent e2dcb7987a
commit 08d789003a
38 changed files with 340 additions and 6867 deletions

File diff suppressed because it is too large Load Diff

View File

@ -7,12 +7,14 @@ import eventHub from '../eventhub';
import DeployKeysService from '../service'; import DeployKeysService from '../service';
import DeployKeysStore from '../store'; import DeployKeysStore from '../store';
import KeysPanel from './keys_panel.vue'; import KeysPanel from './keys_panel.vue';
import Icon from '~/vue_shared/components/icon.vue';
export default { export default {
components: { components: {
KeysPanel, KeysPanel,
NavigationTabs, NavigationTabs,
GlLoadingIcon, GlLoadingIcon,
Icon,
}, },
props: { props: {
endpoint: { endpoint: {
@ -123,8 +125,8 @@ export default {
/> />
<template v-else-if="hasKeys"> <template v-else-if="hasKeys">
<div class="top-area scrolling-tabs-container inner-page-scroll-tabs"> <div class="top-area scrolling-tabs-container inner-page-scroll-tabs">
<div class="fade-left"><i class="fa fa-angle-left" aria-hidden="true"> </i></div> <div class="fade-left"><icon name="chevron-lg-left" :size="12" /></div>
<div class="fade-right"><i class="fa fa-angle-right" aria-hidden="true"> </i></div> <div class="fade-right"><icon name="chevron-lg-right" :size="12" /></div>
<navigation-tabs :tabs="tabs" scope="deployKeys" @onChangeTab="onChangeTab" /> <navigation-tabs :tabs="tabs" scope="deployKeys" @onChangeTab="onChangeTab" />
</div> </div>

View File

@ -9,6 +9,7 @@ import NavigationTabs from '~/vue_shared/components/navigation_tabs.vue';
import NavigationControls from './nav_controls.vue'; import NavigationControls from './nav_controls.vue';
import { getParameterByName } from '~/lib/utils/common_utils'; import { getParameterByName } from '~/lib/utils/common_utils';
import CIPaginationMixin from '~/vue_shared/mixins/ci_pagination_api_mixin'; import CIPaginationMixin from '~/vue_shared/mixins/ci_pagination_api_mixin';
import Icon from '~/vue_shared/components/icon.vue';
import PipelinesFilteredSearch from './pipelines_filtered_search.vue'; import PipelinesFilteredSearch from './pipelines_filtered_search.vue';
import { validateParams } from '../../utils'; import { validateParams } from '../../utils';
import { ANY_TRIGGER_AUTHOR, RAW_TEXT_WARNING, FILTER_TAG_IDENTIFIER } from '../../constants'; import { ANY_TRIGGER_AUTHOR, RAW_TEXT_WARNING, FILTER_TAG_IDENTIFIER } from '../../constants';
@ -20,6 +21,7 @@ export default {
NavigationTabs, NavigationTabs,
NavigationControls, NavigationControls,
PipelinesFilteredSearch, PipelinesFilteredSearch,
Icon,
}, },
mixins: [pipelinesMixin, CIPaginationMixin, glFeatureFlagsMixin()], mixins: [pipelinesMixin, CIPaginationMixin, glFeatureFlagsMixin()],
props: { props: {
@ -298,8 +300,8 @@ export default {
v-if="shouldRenderTabs || shouldRenderButtons" v-if="shouldRenderTabs || shouldRenderButtons"
class="top-area scrolling-tabs-container inner-page-scroll-tabs" class="top-area scrolling-tabs-container inner-page-scroll-tabs"
> >
<div class="fade-left"><i class="fa fa-angle-left" aria-hidden="true"> </i></div> <div class="fade-left"><icon name="chevron-lg-left" :size="12" /></div>
<div class="fade-right"><i class="fa fa-angle-right" aria-hidden="true"> </i></div> <div class="fade-right"><icon name="chevron-lg-right" :size="12" /></div>
<navigation-tabs <navigation-tabs
v-if="shouldRenderTabs" v-if="shouldRenderTabs"

View File

@ -137,7 +137,8 @@
transition-duration: 0.3s; transition-duration: 0.3s;
} }
.fa { .fa,
svg {
position: relative; position: relative;
top: 5px; top: 5px;
font-size: 18px; font-size: 18px;

View File

@ -313,7 +313,7 @@
right: 0; right: 0;
text-align: right; text-align: right;
.fa { svg {
right: 5px; right: 5px;
} }
} }
@ -323,7 +323,7 @@
left: 0; left: 0;
text-align: left; text-align: left;
.fa { svg {
left: 5px; left: 5px;
} }
} }

View File

@ -1,38 +0,0 @@
# frozen_string_literal: true
module BuildsHelper
def build_summary(build, skip: false)
if build.has_trace?
if skip
link_to _("View job log"), pipeline_job_url(build.pipeline, build)
else
build.trace.html(last_lines: 10).html_safe
end
else
_("No job log")
end
end
def sidebar_build_class(build, current_build)
build_class = []
build_class << 'active' if build.id === current_build.id
build_class << 'retried' if build.retried?
build_class.join(' ')
end
def javascript_build_options
{
page_path: project_job_path(@project, @build),
build_status: @build.status,
build_stage: @build.stage,
log_state: ''
}
end
def build_failed_issue_options
{
title: _("Job Failed #%{build_id}") % { build_id: @build.id },
description: project_job_url(@project, @build)
}
end
end

View File

@ -0,0 +1,40 @@
# frozen_string_literal: true
module Ci
module BuildsHelper
def build_summary(build, skip: false)
if build.has_trace?
if skip
link_to _('View job log'), pipeline_job_url(build.pipeline, build)
else
build.trace.html(last_lines: 10).html_safe
end
else
_('No job log')
end
end
def sidebar_build_class(build, current_build)
build_class = []
build_class << 'active' if build.id === current_build.id
build_class << 'retried' if build.retried?
build_class.join(' ')
end
def javascript_build_options
{
page_path: project_job_path(@project, @build),
build_status: @build.status,
build_stage: @build.stage,
log_state: ''
}
end
def build_failed_issue_options
{
title: _("Job Failed #%{build_id}") % { build_id: @build.id },
description: project_job_url(@project, @build)
}
end
end
end

View File

@ -0,0 +1,54 @@
# frozen_string_literal: true
module Ci
module VariablesHelper
def ci_variable_protected_by_default?
Gitlab::CurrentSettings.current_application_settings.protected_ci_variables
end
def create_deploy_token_path(entity, opts = {})
if entity.is_a?(::Group)
create_deploy_token_group_settings_repository_path(entity, opts)
else
# TODO: change this path to 'create_deploy_token_project_settings_ci_cd_path'
# See MR comment for more detail: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27059#note_311585356
create_deploy_token_project_settings_repository_path(entity, opts)
end
end
def revoke_deploy_token_path(entity, token)
if entity.is_a?(::Group)
revoke_group_deploy_token_path(entity, token)
else
revoke_project_deploy_token_path(entity, token)
end
end
def ci_variable_protected?(variable, only_key_value)
if variable && !only_key_value
variable.protected
else
ci_variable_protected_by_default?
end
end
def ci_variable_masked?(variable, only_key_value)
if variable && !only_key_value
variable.masked
else
false
end
end
def ci_variable_type_options
[
%w(Variable env_var),
%w(File file)
]
end
def ci_variable_maskable_regex
Ci::Maskable::REGEX.inspect.sub('\\A', '^').sub('\\z', '$').sub(/^\//, '').sub(/\/[a-z]*$/, '').gsub('\/', '/')
end
end
end

View File

@ -1,52 +0,0 @@
# frozen_string_literal: true
module CiVariablesHelper
def ci_variable_protected_by_default?
Gitlab::CurrentSettings.current_application_settings.protected_ci_variables
end
def create_deploy_token_path(entity, opts = {})
if entity.is_a?(Group)
create_deploy_token_group_settings_repository_path(entity, opts)
else
# TODO: change this path to 'create_deploy_token_project_settings_ci_cd_path'
# See MR comment for more detail: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27059#note_311585356
create_deploy_token_project_settings_repository_path(entity, opts)
end
end
def revoke_deploy_token_path(entity, token)
if entity.is_a?(Group)
revoke_group_deploy_token_path(entity, token)
else
revoke_project_deploy_token_path(entity, token)
end
end
def ci_variable_protected?(variable, only_key_value)
if variable && !only_key_value
variable.protected
else
ci_variable_protected_by_default?
end
end
def ci_variable_masked?(variable, only_key_value)
if variable && !only_key_value
variable.masked
else
false
end
end
def ci_variable_type_options
[
%w(Variable env_var),
%w(File file)
]
end
def ci_variable_maskable_regex
Ci::Maskable::REGEX.inspect.sub('\\A', '^').sub('\\z', '$').sub(/^\//, '').sub(/\/[a-z]*$/, '').gsub('\/', '/')
end
end

View File

@ -8,20 +8,19 @@ class Repositories::BaseService < BaseService
attr_reader :repository attr_reader :repository
delegate :container, :disk_path, :full_path, to: :repository delegate :container, :disk_path, :full_path, to: :repository
delegate :repository_storage, to: :container
def initialize(repository) def initialize(repository)
@repository = repository @repository = repository
end end
def repo_exists?(path) def repo_exists?(path)
gitlab_shell.repository_exists?(repository_storage, path + '.git') gitlab_shell.repository_exists?(repository.shard, path + '.git')
end end
def mv_repository(from_path, to_path) def mv_repository(from_path, to_path)
return true unless repo_exists?(from_path) return true unless repo_exists?(from_path)
gitlab_shell.mv_repository(repository_storage, from_path, to_path) gitlab_shell.mv_repository(repository.shard, from_path, to_path)
end end
# Build a path for removing repositories # Build a path for removing repositories

View File

@ -9,7 +9,7 @@ class Repositories::ShellDestroyService < Repositories::BaseService
GitlabShellWorker.perform_in(delay, GitlabShellWorker.perform_in(delay,
:remove_repository, :remove_repository,
repository_storage, repository.shard,
removal_path) removal_path)
end end
end end

View File

@ -2,9 +2,9 @@
.top-area.scrolling-tabs-container.inner-page-scroll-tabs .top-area.scrolling-tabs-container.inner-page-scroll-tabs
.fade-left .fade-left
= icon('angle-left') = sprite_icon('chevron-lg-left', size: 12)
.fade-right .fade-right
= icon('angle-right') = sprite_icon('chevron-lg-right', size: 12)
%ul.nav-links.nav.nav-tabs.scrolling-tabs %ul.nav-links.nav.nav-tabs.scrolling-tabs
= nav_link(html_options: { class: active_when(params[:filter].nil?) }) do = nav_link(html_options: { class: active_when(params[:filter].nil?) }) do
= link_to admin_users_path do = link_to admin_users_path do

View File

@ -12,8 +12,8 @@
= link_to _("New project"), new_project_path, class: "btn btn-success" = link_to _("New project"), new_project_path, class: "btn btn-success"
.top-area.scrolling-tabs-container.inner-page-scroll-tabs .top-area.scrolling-tabs-container.inner-page-scroll-tabs
.fade-left= icon('angle-left') .fade-left= sprite_icon('chevron-lg-left', size: 12)
.fade-right= icon('angle-right') .fade-right= sprite_icon('chevron-lg-right', size: 12)
%ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs{ class: ('border-0' if feature_project_list_filter_bar) } %ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs{ class: ('border-0' if feature_project_list_filter_bar) }
= nav_link(page: [dashboard_projects_path, root_path]) do = nav_link(page: [dashboard_projects_path, root_path]) do
= link_to dashboard_projects_path, class: 'shortcuts-activity', data: {placement: 'right'} do = link_to dashboard_projects_path, class: 'shortcuts-activity', data: {placement: 'right'} do

View File

@ -19,8 +19,8 @@
.groups-listing{ data: { endpoints: { default: group_children_path(@group, format: :json), shared: group_shared_projects_path(@group, format: :json) } } } .groups-listing{ data: { endpoints: { default: group_children_path(@group, format: :json), shared: group_shared_projects_path(@group, format: :json) } } }
.top-area.group-nav-container.justify-content-between .top-area.group-nav-container.justify-content-between
.scrolling-tabs-container.inner-page-scroll-tabs .scrolling-tabs-container.inner-page-scroll-tabs
.fade-left= icon('angle-left') .fade-left= sprite_icon('chevron-lg-left', size: 12)
.fade-right= icon('angle-right') .fade-right= sprite_icon('chevron-lg-right', size: 12)
%ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs %ul.nav-links.scrolling-tabs.mobile-separator.nav.nav-tabs
%li.js-subgroups_and_projects-tab %li.js-subgroups_and_projects-tab
= link_to group_path, data: { target: 'div#subgroups_and_projects', action: 'subgroups_and_projects', toggle: 'tab'} do = link_to group_path, data: { target: 'div#subgroups_and_projects', action: 'subgroups_and_projects', toggle: 'tab'} do

View File

@ -20,8 +20,8 @@
.merge-request-tabs-holder{ class: ("js-tabs-affix" unless ENV['RAILS_ENV'] == 'test') } .merge-request-tabs-holder{ class: ("js-tabs-affix" unless ENV['RAILS_ENV'] == 'test') }
.merge-request-tabs-container .merge-request-tabs-container
.scrolling-tabs-container.inner-page-scroll-tabs.is-smaller .scrolling-tabs-container.inner-page-scroll-tabs.is-smaller
.fade-left= icon('angle-left') .fade-left= sprite_icon('chevron-lg-left', size: 12)
.fade-right= icon('angle-right') .fade-right= sprite_icon('chevron-lg-right', size: 12)
%ul.merge-request-tabs.nav.nav-tabs.nav-links.no-top.no-bottom.js-tabs-affix %ul.merge-request-tabs.nav.nav-tabs.nav-links.no-top.no-bottom.js-tabs-affix
%li.commits-tab.new-tab %li.commits-tab.new-tab
= link_to url_for(safe_params), data: {target: 'div#commits', action: 'new', toggle: 'tabvue'} do = link_to url_for(safe_params), data: {target: 'div#commits', action: 'new', toggle: 'tabvue'} do

View File

@ -1,5 +1,5 @@
- content_for :create_access_levels do - content_for :create_access_levels do
.create_access_levels-container .create_access_levels-container{ data: { qa_selector: 'access_levels_content' } }
= dropdown_tag('Select', = dropdown_tag('Select',
options: { toggle_class: 'js-allowed-to-create wide', options: { toggle_class: 'js-allowed-to-create wide',
dropdown_class: 'dropdown-menu-selectable capitalize-header', dropdown_class: 'dropdown-menu-selectable capitalize-header',

View File

@ -3,8 +3,8 @@
= search_filter_link 'users', _("Users") = search_filter_link 'users', _("Users")
.scrolling-tabs-container.inner-page-scroll-tabs.is-smaller .scrolling-tabs-container.inner-page-scroll-tabs.is-smaller
.fade-left= icon('angle-left') .fade-left= sprite_icon('chevron-lg-left', size: 12)
.fade-right= icon('angle-right') .fade-right= sprite_icon('chevron-lg-right', size: 12)
%ul.nav-links.search-filter.scrolling-tabs.nav.nav-tabs %ul.nav-links.search-filter.scrolling-tabs.nav.nav-tabs
- if @project - if @project
- if project_search_tabs?(:blobs) - if project_search_tabs?(:blobs)

View File

@ -1,8 +1,8 @@
- show_group_events = local_assigns.fetch(:show_group_events, false) - show_group_events = local_assigns.fetch(:show_group_events, false)
.scrolling-tabs-container.inner-page-scroll-tabs.is-smaller.flex-fill .scrolling-tabs-container.inner-page-scroll-tabs.is-smaller.flex-fill
.fade-left= icon('angle-left') .fade-left= sprite_icon('chevron-lg-left', size: 12)
.fade-right= icon('angle-right') .fade-right= sprite_icon('chevron-lg-right', size: 12)
%ul.nav-links.event-filter.scrolling-tabs.nav.nav-tabs %ul.nav-links.event-filter.scrolling-tabs.nav.nav-tabs
= event_filter_link EventFilter::ALL, _('All'), s_('EventFilterBy|Filter by all') = event_filter_link EventFilter::ALL, _('All'), s_('EventFilterBy|Filter by all')
- if event_filter_visible(:repository) - if event_filter_visible(:repository)

View File

@ -1,6 +1,6 @@
.scrolling-tabs-container.inner-page-scroll-tabs.is-smaller .scrolling-tabs-container.inner-page-scroll-tabs.is-smaller
.fade-left= icon('angle-left') .fade-left= sprite_icon('chevron-lg-left', size: 12)
.fade-right= icon('angle-right') .fade-right= sprite_icon('chevron-lg-right', size: 12)
%ul.nav-links.scrolling-tabs.js-milestone-tabs.nav.nav-tabs %ul.nav-links.scrolling-tabs.js-milestone-tabs.nav.nav-tabs
%li.nav-item %li.nav-item
= link_to '#tab-issues', class: 'nav-link active', data: { toggle: 'tab', show: '.tab-issues-buttons' } do = link_to '#tab-issues', class: 'nav-link active', data: { toggle: 'tab', show: '.tab-issues-buttons' } do

View File

@ -89,8 +89,8 @@
- unless profile_tabs.empty? - unless profile_tabs.empty?
.scrolling-tabs-container .scrolling-tabs-container
.fade-left= icon('angle-left') .fade-left= sprite_icon('chevron-lg-left', size: 12)
.fade-right= icon('angle-right') .fade-right= sprite_icon('chevron-lg-right', size: 12)
%ul.nav-links.user-profile-nav.scrolling-tabs.nav.nav-tabs %ul.nav-links.user-profile-nav.scrolling-tabs.nav.nav-tabs
- if profile_tab?(:overview) - if profile_tab?(:overview)
%li.js-overview-tab %li.js-overview-tab

View File

@ -0,0 +1,5 @@
---
title: Expand healtchecks `500`s when DB is not available
merge_request: 34844
author:
type: fixed

View File

@ -375,6 +375,8 @@ otherwise the external file won't be included.
| [`remote`](#includeremote) | Include a file from a remote URL. Must be publicly accessible. | | [`remote`](#includeremote) | Include a file from a remote URL. Must be publicly accessible. |
| [`template`](#includetemplate) | Include templates which are provided by GitLab. | | [`template`](#includetemplate) | Include templates which are provided by GitLab. |
The `include` methods do not support [variable expansion](../variables/where_variables_can_be_used.md#variables-usage).
NOTE: **Note:** NOTE: **Note:**
`.gitlab-ci.yml` configuration included by all methods is evaluated at pipeline creation. `.gitlab-ci.yml` configuration included by all methods is evaluated at pipeline creation.
The configuration is a snapshot in time and persisted in the database. Any changes to The configuration is a snapshot in time and persisted in the database. Any changes to

View File

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference type: reference
--- ---
# GitLab CI/CD YAML includes # GitLab CI/CD include examples
In addition to the [`includes` examples](README.md#include) listed in the In addition to the [`includes` examples](README.md#include) listed in the
[GitLab CI YAML reference](README.md), this page lists more variations of `include` [GitLab CI YAML reference](README.md), this page lists more variations of `include`

View File

@ -111,11 +111,7 @@ Patterns:
- `'"((?:\\"|[^"]|\\")*)"'`: captures terms inside quotes, removing the quotes - `'"((?:\\"|[^"]|\\")*)"'`: captures terms inside quotes, removing the quotes
- `"'((?:\\'|[^']|\\')*)'"`: same as above, for single-quotes - `"'((?:\\'|[^']|\\')*)'"`: same as above, for single-quotes
- `'\.([^.]+)(?=\.|\s|\Z)'`: separate terms with periods in-between - `'\.([^.]+)(?=\.|\s|\Z)'`: separate terms with periods in-between
- `'\/?([^\/]+)(?=\/|\b)'`: separate path terms `like/this/one` - `'([\p{L}_.-]+)'` : some common chars in file names to keep the whole filename intact (eg. `my_file-ñame.txt`)
#### `edgeNGram_filter`
Uses an [Edge NGram token filter](https://www.elastic.co/guide/en/elasticsearch/reference/5.5/analysis-edgengram-tokenfilter.html) to allow inputs with only parts of a token to find the token. For example it would turn `glasses` into permutations starting with `gl` and ending with `glasses`, which would allow a search for "`glass`" to find the original token `glasses`
## Gotchas ## Gotchas

View File

@ -178,6 +178,10 @@ For example, to add support for files referenced by a `Widget` model with a
mount_uploader :file, WidgetUploader mount_uploader :file, WidgetUploader
def self.replicables_for_geo_node
# Should be implemented. The idea of the method is to restrict
# the set of synced items depending on synchronization settings
end
... ...
end end
``` ```
@ -257,19 +261,30 @@ For example, to add support for files referenced by a `Widget` model with a
class Geo::WidgetRegistry < Geo::BaseRegistry class Geo::WidgetRegistry < Geo::BaseRegistry
include Geo::StateMachineRegistry include Geo::StateMachineRegistry
MODEL_CLASS = ::Widget
MODEL_FOREIGN_KEY = :widget_id MODEL_FOREIGN_KEY = :widget_id
belongs_to :widget, class_name: 'Widget' belongs_to :widget, class_name: 'Widget'
def self.has_create_events?
true
end
end end
``` ```
The method `has_create_events?` should return `true` in most of the cases.
However, if the entity you add doesn't have the create event, don't add the
method at all.
1. Update `REGISTRY_CLASSES` in `ee/app/workers/geo/secondary/registry_consistency_worker.rb`.
1. Create `ee/spec/factories/geo/widget_registry.rb`: 1. Create `ee/spec/factories/geo/widget_registry.rb`:
```ruby ```ruby
# frozen_string_literal: true # frozen_string_literal: true
FactoryBot.define do FactoryBot.define do
factory :widget_registry, class: 'Geo::WidgetRegistry' do factory :geo_widget_registry, class: 'Geo::WidgetRegistry' do
widget widget
state { Geo::WidgetRegistry.state_value(:pending) } state { Geo::WidgetRegistry.state_value(:pending) }
@ -302,13 +317,17 @@ For example, to add support for files referenced by a `Widget` model with a
require 'spec_helper' require 'spec_helper'
RSpec.describe Geo::WidgetRegistry, :geo, type: :model do RSpec.describe Geo::WidgetRegistry, :geo, type: :model do
let_it_be(:registry) { create(:widget_registry) } let_it_be(:registry) { create(:geo_widget_registry) }
specify 'factory is valid' do specify 'factory is valid' do
expect(registry).to be_valid expect(registry).to be_valid
end end
include_examples 'a Geo framework registry' include_examples 'a Geo framework registry'
describe '.find_registry_differences' do
... # To be implemented
end
end end
``` ```
@ -429,7 +448,7 @@ Widgets should now be verified by Geo!
require 'spec_helper' require 'spec_helper'
RSpec.describe Resolvers::Geo::WidgetRegistriesResolver do RSpec.describe Resolvers::Geo::WidgetRegistriesResolver do
it_behaves_like 'a Geo registries resolver', :widget_registry it_behaves_like 'a Geo registries resolver', :geo_widget_registry
end end
``` ```
@ -453,7 +472,7 @@ Widgets should now be verified by Geo!
require 'spec_helper' require 'spec_helper'
RSpec.describe Geo::WidgetRegistryFinder do RSpec.describe Geo::WidgetRegistryFinder do
it_behaves_like 'a framework registry finder', :widget_registry it_behaves_like 'a framework registry finder', :geo_widget_registry
end end
``` ```
@ -503,7 +522,7 @@ Widgets should now be verified by Geo!
it_behaves_like 'gets registries for', { it_behaves_like 'gets registries for', {
field_name: 'widgetRegistries', field_name: 'widgetRegistries',
registry_class_name: 'WidgetRegistry', registry_class_name: 'WidgetRegistry',
registry_factory: :widget_registry, registry_factory: :geo_widget_registry,
registry_foreign_key_field_name: 'widgetId' registry_foreign_key_field_name: 'widgetId'
} }
``` ```

View File

@ -137,8 +137,8 @@ This check is being exempt from Rack Attack.
## Access token (Deprecated) ## Access token (Deprecated)
> NOTE: **Note:** NOTE: **Note:**
> Access token has been deprecated in GitLab 9.4 in favor of [IP whitelist](#ip-whitelist). Access token has been deprecated in GitLab 9.4 in favor of [IP whitelist](#ip-whitelist).
An access token needs to be provided while accessing the probe endpoints. The current An access token needs to be provided while accessing the probe endpoints. The current
accepted token can be found under the **Admin Area > Monitoring > Health check** accepted token can be found under the **Admin Area > Monitoring > Health check**
@ -152,6 +152,10 @@ The access token can be passed as a URL parameter:
https://gitlab.example.com/-/readiness?token=ACCESS_TOKEN https://gitlab.example.com/-/readiness?token=ACCESS_TOKEN
``` ```
NOTE: **Note:**
In case the database or Redis service are unaccessible, the probe endpoints response is not guaranteed to be correct.
You should switch to [IP whitelist](#ip-whitelist) from deprecated access token to avoid it.
<!-- ## Troubleshooting <!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues Include any troubleshooting steps that you can foresee. If you know beforehand what issues

View File

@ -118,8 +118,8 @@ module API
{ {
repository: repository.gitaly_repository, repository: repository.gitaly_repository,
address: Gitlab::GitalyClient.address(container.repository_storage), address: Gitlab::GitalyClient.address(repository.shard),
token: Gitlab::GitalyClient.token(container.repository_storage), token: Gitlab::GitalyClient.token(repository.shard),
features: Feature::Gitaly.server_feature_flags features: Feature::Gitaly.server_feature_flags
} }
end end

View File

@ -20,6 +20,12 @@ module Gitlab
success ? 200 : 503, success ? 200 : 503,
status(success).merge(payload(readiness)) status(success).merge(payload(readiness))
) )
rescue => e
exception_payload = { message: "#{e.class} : #{e.message}" }
Probes::Status.new(
500,
status(false).merge(exception_payload))
end end
private private

View File

@ -72,7 +72,7 @@ module Gitlab
end end
def redis_cluster_validate!(command) def redis_cluster_validate!(command)
RedisClusterValidator.validate!(command) if @redis_cluster_validation ::Gitlab::Instrumentation::RedisClusterValidator.validate!(command) if @redis_cluster_validation
end end
def enable_redis_cluster_validation def enable_redis_cluster_validation

View File

@ -216,8 +216,8 @@ module Gitlab
def gitaly_server_hash(repository) def gitaly_server_hash(repository)
{ {
address: Gitlab::GitalyClient.address(repository.container.repository_storage), address: Gitlab::GitalyClient.address(repository.shard),
token: Gitlab::GitalyClient.token(repository.container.repository_storage), token: Gitlab::GitalyClient.token(repository.shard),
features: Feature::Gitaly.server_feature_flags features: Feature::Gitaly.server_feature_flags
} }
end end

View File

@ -183,7 +183,6 @@ module QA
autoload :OAuth, 'qa/page/main/oauth' autoload :OAuth, 'qa/page/main/oauth'
autoload :SignUp, 'qa/page/main/sign_up' autoload :SignUp, 'qa/page/main/sign_up'
autoload :Terms, 'qa/page/main/terms' autoload :Terms, 'qa/page/main/terms'
autoload :Onboarding, 'qa/page/main/onboarding'
end end
module Settings module Settings

View File

@ -165,10 +165,6 @@ module QA
terms.accept_terms if terms.visible? terms.accept_terms if terms.visible?
end end
QA::Page::Main::Onboarding.perform do |onboarding|
onboarding.skip_for_now if onboarding.respond_to?(:skip_for_now) && onboarding.visible?
end
Page::Main::Menu.validate_elements_present! unless skip_page_validation Page::Main::Menu.validate_elements_present! unless skip_page_validation
end end

View File

@ -1,12 +0,0 @@
# frozen_string_literal: true
module QA
module Page
module Main
class Onboarding < Page::Base
end
end
end
end
QA::Page::Main::Onboarding.prepend_if_ee('QA::EE::Page::Main::Onboarding')

View File

@ -15,7 +15,7 @@ module QA
end end
def accept_terms def accept_terms
click_element :accept_terms_button click_element :accept_terms_button, Page::Main::Menu
end end
end end
end end

View File

@ -12,6 +12,7 @@ module QA
end end
view 'app/views/projects/protected_tags/_create_protected_tag.html.haml' do view 'app/views/projects/protected_tags/_create_protected_tag.html.haml' do
element :access_levels_content
element :access_levels_dropdown element :access_levels_dropdown
end end
@ -26,8 +27,10 @@ module QA
def choose_access_level_role(role) def choose_access_level_role(role)
click_element :access_levels_dropdown click_element :access_levels_dropdown
within_element(:access_levels_content) do
click_on role click_on role
end end
end
def click_protect_tag_button def click_protect_tag_button
click_element :protect_tag_button click_element :protect_tag_button

View File

@ -0,0 +1,111 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Ci::BuildsHelper do
describe '#build_summary' do
subject { helper.build_summary(build, skip: skip) }
context 'when build has no trace' do
let(:build) { instance_double(Ci::Build, has_trace?: false) }
context 'when skip is false' do
let(:skip) { false }
it 'returns no job log' do
expect(subject).to eq('No job log')
end
end
context 'when skip is true' do
let(:skip) { true }
it 'returns no job log' do
expect(subject).to eq('No job log')
end
end
end
context 'when build has trace' do
let(:build) { create(:ci_build, :trace_live) }
context 'when skip is true' do
let(:skip) { true }
it 'returns link to logs' do
expect(subject).to include('View job log')
expect(subject).to include(pipeline_job_url(build.pipeline, build))
end
end
context 'when skip is false' do
let(:skip) { false }
it 'returns log lines' do
expect(subject).to include(build.trace.html(last_lines: 10).html_safe)
end
end
end
end
describe '#sidebar_build_class' do
using RSpec::Parameterized::TableSyntax
where(:build_id, :current_build_id, :retried, :expected_result) do
1 | 1 | true | 'active retried'
1 | 1 | false | 'active'
1 | 2 | false | ''
1 | 2 | true | 'retried'
end
let(:build) { instance_double(Ci::Build, retried?: retried, id: build_id) }
let(:current_build) { instance_double(Ci::Build, retried?: true, id: current_build_id ) }
subject { helper.sidebar_build_class(build, current_build) }
with_them do
it 'builds sidebar html class' do
expect(subject).to eq(expected_result)
end
end
end
describe '#javascript_build_options' do
subject { helper.javascript_build_options }
it 'returns build options' do
project = assign_project
ci_build = assign_build
expect(subject).to eq({
page_path: project_job_path(project, ci_build),
build_status: ci_build.status,
build_stage: ci_build.stage,
log_state: ''
})
end
end
describe '#build_failed_issue_options' do
subject { helper.build_failed_issue_options }
it 'returns failed title and description' do
project = assign_project
ci_build = assign_build
expect(subject).to eq(title: "Job Failed \##{ci_build.id}", description: project_job_url(project, ci_build))
end
end
def assign_project
build(:project).tap do |project|
assign(:project, project)
end
end
def assign_build
create(:ci_build).tap do |ci_build|
assign(:build, ci_build)
end
end
end

View File

@ -47,6 +47,20 @@ RSpec.describe Gitlab::HealthChecks::Probes::Collection do
status: 'failed', message: 'check error') status: 'failed', message: 'check error')
end end
end end
context 'when check raises exception not handled inside the check' do
before do
expect(Gitlab::HealthChecks::Redis::RedisCheck).to receive(:readiness).and_raise(
::Redis::CannotConnectError, 'Redis down')
end
it 'responds with failure including the exception info' do
expect(subject.http_status).to eq(500)
expect(subject.json[:status]).to eq('failed')
expect(subject.json[:message]).to eq('Redis::CannotConnectError : Redis down')
end
end
end end
context 'without checks' do context 'without checks' do

View File

@ -129,6 +129,40 @@ RSpec.describe HealthController do
expect(response).to have_gitlab_http_status(:service_unavailable) expect(response).to have_gitlab_http_status(:service_unavailable)
expect(response.headers['X-GitLab-Custom-Error']).to eq(1) expect(response.headers['X-GitLab-Custom-Error']).to eq(1)
end end
context 'when DB is not accessible and connection raises an exception' do
before do
expect(Gitlab::HealthChecks::DbCheck)
.to receive(:readiness)
.and_raise(PG::ConnectionBad, 'could not connect to server')
end
it 'responds with 500 including the exception info' do
subject
expect(response).to have_gitlab_http_status(:internal_server_error)
expect(response.headers['X-GitLab-Custom-Error']).to eq(1)
expect(json_response).to eq(
{ 'status' => 'failed', 'message' => 'PG::ConnectionBad : could not connect to server' })
end
end
context 'when any exception happens during the probing' do
before do
expect(Gitlab::HealthChecks::Redis::RedisCheck)
.to receive(:readiness)
.and_raise(::Redis::CannotConnectError, 'Redis down')
end
it 'responds with 500 including the exception info' do
subject
expect(response).to have_gitlab_http_status(:internal_server_error)
expect(response.headers['X-GitLab-Custom-Error']).to eq(1)
expect(json_response).to eq(
{ 'status' => 'failed', 'message' => 'Redis::CannotConnectError : Redis down' })
end
end
end end
end end