Commit cf9c3f71 authored by Sean McGivern's avatar Sean McGivern

Merge branch 'ce-to-ee-2018-11-20' into 'master'

CE upstream - 2018-11-20 13:22 UTC

Closes gitlab-ce#54189, #8488, and gitlab-ce#54236

See merge request gitlab-org/gitlab-ee!8533
parents ed4707a2 2eaaca51
......@@ -2,10 +2,6 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 11.4.7 (2018-11-20)
- No changes.
## 11.4.6 (2018-11-18)
### Security (1 change)
......@@ -15,9 +11,8 @@ entry.
## 11.4.5 (2018-11-04)
### Fixed (5 changes, 1 of them is from the community)
### Fixed (4 changes, 1 of them is from the community)
- Fix stuck job warning message. !8060
- fix link to enable usage ping from convdev index. !22545 (Anand Capur)
- Update gitlab-ui dependency to 1.8.0-hotfix.1 to fix IE11 bug.
- Remove duplicate escape in job sidebar.
......@@ -324,7 +319,6 @@ entry.
- Fix loading issue on some merge request discussion. !21982
- Fix project deletion when there is a export available. !22276
- No changes.
## 11.3.3 (2018-10-04)
......
......@@ -103,6 +103,12 @@ picked into the stable branches) up to the 19th of the month. Such merge
requests should have the ~"feature flag" label assigned, and don't require a
corresponding exception request to be created.
In order to build the final package and present the feature for self-hosted
customers, the feature flag should be removed. This should happen before the
22nd, ideally _at least_ 2 days before. That means MRs with feature
flags being picked at the 19th would have a quite tight schedule, so picking
these _earlier_ is preferable.
While rare, release managers may decide to reject picking a change into a stable
branch, even when feature flags are used. This might be necessary if the changes
are deemed problematic, too invasive, or there simply isn't enough time to
......
......@@ -158,10 +158,16 @@ class GfmAutoComplete {
// Team Members
$input.atwho({
at: '@',
alias: 'users',
displayTpl(value) {
let tmpl = GfmAutoComplete.Loading.template;
if (value.username != null) {
tmpl = GfmAutoComplete.Members.template;
const { avatarTag, username, title } = value;
if (username != null) {
tmpl = GfmAutoComplete.Members.templateFunction({
avatarTag,
username,
title,
});
}
return tmpl;
},
......@@ -572,8 +578,9 @@ GfmAutoComplete.Emoji = {
};
// Team Members
GfmAutoComplete.Members = {
// eslint-disable-next-line no-template-curly-in-string
template: '<li>${avatarTag} ${username} <small>${title}</small></li>',
templateFunction({ avatarTag, username, title }) {
return `<li>${avatarTag} ${username} <small>${_.escape(title)}</small></li>`;
},
};
GfmAutoComplete.Labels = {
template:
......
......@@ -10,6 +10,7 @@ export default class UserOverviewBlock {
limit: DEFAULT_LIMIT,
...options.requestParams,
};
this.postRenderCallback = options.postRenderCallback;
this.loadData();
}
......@@ -43,5 +44,9 @@ export default class UserOverviewBlock {
}
loadingEl.classList.add('hide');
if (this.postRenderCallback) {
this.postRenderCallback.call(this);
}
}
}
......@@ -2,7 +2,8 @@ import $ from 'jquery';
import axios from '~/lib/utils/axios_utils';
import Activities from '~/activities';
import { localTimeAgo } from '~/lib/utils/datetime_utility';
import { __, sprintf } from '~/locale';
import AjaxCache from '~/lib/utils/ajax_cache';
import { __ } from '~/locale';
import flash from '~/flash';
import ActivityCalendar from './activity_calendar';
import UserOverviewBlock from './user_overview_block';
......@@ -62,23 +63,20 @@ import UserOverviewBlock from './user_overview_block';
* </div>
*/
const CALENDAR_TEMPLATES = {
activity: `
<div class="clearfix calendar">
<div class="js-contrib-calendar"></div>
<div class="calendar-hint bottom-right"></div>
</div>
`,
overview: `
<div class="clearfix calendar">
<div class="calendar-hint"></div>
<div class="js-contrib-calendar prepend-top-20"></div>
</div>
`,
};
const CALENDAR_TEMPLATE = `
<div class="clearfix calendar">
<div class="js-contrib-calendar"></div>
<div class="calendar-hint bottom-right"></div>
</div>
`;
const CALENDAR_PERIOD_6_MONTHS = 6;
const CALENDAR_PERIOD_12_MONTHS = 12;
/* computation based on
* width = (group + 1) * this.daySizeWithSpace + this.getExtraWidthPadding(group);
* (see activity_calendar.js)
*/
const OVERVIEW_CALENDAR_BREAKPOINT = 918;
export default class UserTabs {
constructor({ defaultAction, action, parentEl }) {
......@@ -105,6 +103,12 @@ export default class UserTabs {
.off('shown.bs.tab', '.nav-links a[data-toggle="tab"]')
.on('shown.bs.tab', '.nav-links a[data-toggle="tab"]', event => this.tabShown(event))
.on('click', '.gl-pagination a', event => this.changeProjectsPage(event));
window.addEventListener('resize', () => this.onResize());
}
onResize() {
this.loadActivityCalendar();
}
changeProjectsPage(e) {
......@@ -167,8 +171,6 @@ export default class UserTabs {
return;
}
this.loadActivityCalendar('activity');
// eslint-disable-next-line no-new
new Activities('#activity');
......@@ -180,10 +182,10 @@ export default class UserTabs {
return;
}
this.loadActivityCalendar('overview');
this.loadActivityCalendar();
UserTabs.renderMostRecentBlocks('#js-overview .activities-block', {
requestParams: { limit: 5 },
requestParams: { limit: 10 },
});
UserTabs.renderMostRecentBlocks('#js-overview .projects-block', {
requestParams: { limit: 10, skip_pagination: true },
......@@ -198,52 +200,39 @@ export default class UserTabs {
container,
url: $(`${container} .overview-content-list`).data('href'),
...options,
postRenderCallback: () => localTimeAgo($('.js-timeago', container)),
});
}
loadActivityCalendar(action) {
const monthsAgo = action === 'overview' ? CALENDAR_PERIOD_6_MONTHS : CALENDAR_PERIOD_12_MONTHS;
loadActivityCalendar() {
const $calendarWrap = this.$parentEl.find('.tab-pane.active .user-calendar');
const calendarPath = $calendarWrap.data('calendarPath');
AjaxCache.retrieve(calendarPath)
.then(data => UserTabs.renderActivityCalendar(data, $calendarWrap))
.catch(() => flash(__('There was an error loading users activity calendar.')));
}
static renderActivityCalendar(data, $calendarWrap) {
const monthsAgo = UserTabs.getVisibleCalendarPeriod($calendarWrap);
const calendarActivitiesPath = $calendarWrap.data('calendarActivitiesPath');
const utcOffset = $calendarWrap.data('utcOffset');
let utcFormatted = 'UTC';
if (utcOffset !== 0) {
utcFormatted = `UTC${utcOffset > 0 ? '+' : ''}${utcOffset / 3600}`;
}
const calendarHint = __('Issues, merge requests, pushes and comments.');
axios
.get(calendarPath)
.then(({ data }) => {
$calendarWrap.html(CALENDAR_TEMPLATES[action]);
let calendarHint = '';
if (action === 'activity') {
calendarHint = sprintf(
__(
'Summary of issues, merge requests, push events, and comments (Timezone: %{utcFormatted})',
),
{ utcFormatted },
);
} else if (action === 'overview') {
calendarHint = __('Issues, merge requests, pushes and comments.');
}
$calendarWrap.find('.calendar-hint').text(calendarHint);
// eslint-disable-next-line no-new
new ActivityCalendar(
'.tab-pane.active .js-contrib-calendar',
'.tab-pane.active .user-calendar-activities',
data,
calendarActivitiesPath,
utcOffset,
0,
monthsAgo,
);
})
.catch(() => flash(__('There was an error loading users activity calendar.')));
$calendarWrap.html(CALENDAR_TEMPLATE);
$calendarWrap.find('.calendar-hint').text(calendarHint);
// eslint-disable-next-line no-new
new ActivityCalendar(
'.tab-pane.active .js-contrib-calendar',
'.tab-pane.active .user-calendar-activities',
data,
calendarActivitiesPath,
utcOffset,
0,
monthsAgo,
);
}
toggleLoading(status) {
......@@ -267,4 +256,11 @@ export default class UserTabs {
getCurrentAction() {
return this.$parentEl.find('.nav-links a.active').data('action');
}
static getVisibleCalendarPeriod($calendarWrap) {
const width = $calendarWrap.width();
return width < OVERVIEW_CALENDAR_BREAKPOINT
? CALENDAR_PERIOD_6_MONTHS
: CALENDAR_PERIOD_12_MONTHS;
}
}
......@@ -34,14 +34,7 @@ export default {
fileSizeReadable() {
return numberToHumanSize(this.fileSize);
},
dimensionStyles() {
if (!this.isLoaded) return {};
return {
width: `${this.width}px`,
height: `${this.height}px`,
};
},
hasFileSize() {
return this.fileSize > 0;
},
......@@ -89,7 +82,6 @@ export default {
<div>
<div
:class="innerCssClasses"
:style="dimensionStyles"
class="position-relative"
>
<img
......
......@@ -25,7 +25,7 @@ export default {
swipeMaxWidth: undefined,
swipeMaxHeight: undefined,
swipeBarPos: 1,
swipeWrapWidth: undefined,
swipeWrapWidth: 0,
};
},
computed: {
......@@ -63,7 +63,7 @@ export default {
leftValue = clientWidth - spaceLeft;
}
this.swipeWrapWidth = this.swipeMaxWidth - leftValue;
this.swipeWrapWidth = (leftValue / clientWidth) * 100;
this.swipeBarPos = leftValue;
},
startDrag() {
......@@ -81,7 +81,6 @@ export default {
// Add 2 for border width
this.swipeMaxWidth =
Math.max(this.swipeOldImgInfo.renderedWidth, this.swipeNewImgInfo.renderedWidth) + 2;
this.swipeWrapWidth = this.swipeMaxWidth;
this.swipeMaxHeight =
Math.max(this.swipeOldImgInfo.renderedHeight, this.swipeNewImgInfo.renderedHeight) + 2;
......@@ -107,10 +106,6 @@ export default {
<div class="swipe view">
<div
ref="swipeFrame"
:style="{
'width': swipeMaxPixelWidth,
'height': swipeMaxPixelHeight,
}"
class="swipe-frame">
<image-viewer
key="swipeOldImg"
......@@ -123,14 +118,17 @@ export default {
<div
ref="swipeWrap"
:style="{
'width': swipeWrapPixelWidth,
'height': swipeMaxPixelHeight,
width: `${swipeWrapWidth}%`
}"
class="swipe-wrap">
class="swipe-wrap"
>
<image-viewer
key="swipeNewImg"
:render-info="false"
:path="newPath"
:style="{
width: swipeMaxPixelWidth
}"
class="frame added"
@imgLoaded="swipeNewImgLoaded"
>
......
......@@ -19,18 +19,18 @@ export default {
</script>
<template>
<div class="two-up view">
<div class="two-up view d-flex">
<image-viewer
:path="oldPath"
:render-info="true"
inner-css-classes="frame deleted"
class="wrap"
class="wrap w-50"
/>
<image-viewer
:path="newPath"
:render-info="true"
:inner-css-classes="['frame', 'added']"
class="wrap"
class="wrap w-50"
>
<slot
slot="image-overlay"
......
......@@ -253,19 +253,6 @@
right: 7px;
}
.frame {
top: 0;
right: 0;
position: absolute;
&.deleted {
margin: 0;
display: block;
top: 13px;
right: 7px;
}
}
.swipe-bar {
display: block;
height: 100%;
......@@ -435,7 +422,7 @@
.onion-skin.view {
.swipe-wrap {
top: 0;
right: 0;
left: 0;
}
.frame.deleted {
......
......@@ -178,7 +178,7 @@ class GroupDescendantsFinder
end
def sort
params.fetch(:sort, 'id_asc')
params.fetch(:sort, 'created_desc')
end
# rubocop: disable CodeReuse/ActiveRecord
......
......@@ -1053,11 +1053,19 @@ class Repository
end
def cache
@cache ||= Gitlab::RepositoryCache.new(self)
@cache ||= if is_wiki
Gitlab::RepositoryCache.new(self, extra_namespace: 'wiki')
else
Gitlab::RepositoryCache.new(self)
end
end
def request_store_cache
@request_store_cache ||= Gitlab::RepositoryCache.new(self, backend: Gitlab::SafeRequestStore)
@request_store_cache ||= if is_wiki
Gitlab::RepositoryCache.new(self, extra_namespace: 'wiki', backend: Gitlab::SafeRequestStore)
else
Gitlab::RepositoryCache.new(self, backend: Gitlab::SafeRequestStore)
end
end
def tags_sorted_by_committed_date
......
......@@ -5,7 +5,7 @@
.project-header.d-flex.flex-row.flex-wrap.align-items-center.append-bottom-8
.project-title-row.d-flex.align-items-center
.avatar-container.project-avatar.float-none
= project_icon(@project, alt: @project.name, class: 'avatar avatar-tile')
= project_icon(@project, alt: @project.name, class: 'avatar avatar-tile s24', width: 24, height: 24)
%h1.project-title.d-flex.align-items-baseline.qa-project-name
= @project.name
.project-metadata.d-flex.flex-row.flex-wrap.align-items-baseline
......
- diff_file = viewer.diff_file
- url = url_for(safe_params.merge(action: :diff_for_path, old_path: diff_file.old_path, new_path: diff_file.new_path, file_identifier: diff_file.file_identifier))
.nothing-here-block.diff-collapsed{ data: { diff_for_path: url } }
This diff is collapsed.
%button.click-to-expand.btn.btn-link Click to expand it.
= _("This diff is collapsed.")
%button.click-to-expand.btn.btn-link= _("Click to expand it.")
......@@ -8,7 +8,7 @@
.files-changed-inner
.inline-parallel-buttons.d-none.d-sm-none.d-md-block
- if !diffs_expanded? && diff_files.any? { |diff_file| diff_file.collapsed? }
= link_to 'Expand all', url_for(safe_params.merge(expanded: 1, format: nil)), class: 'btn btn-default'
= link_to _('Expand all'), url_for(safe_params.merge(expanded: 1, format: nil)), class: 'btn btn-default'
- if show_whitespace_toggle
- if current_controller?(:commit)
= commit_diff_whitespace_link(diffs.project, @commit, class: 'd-none d-sm-inline-block')
......
......@@ -12,7 +12,7 @@
- blob = diff_file.blob
.file-actions.d-none.d-sm-block
- if blob&.readable_text?
= link_to '#', class: 'js-toggle-diff-comments btn active has-tooltip', title: "Toggle comments for this file", disabled: @diff_notes_disabled do
= link_to '#', class: 'js-toggle-diff-comments btn active has-tooltip', title: _("Toggle comments for this file"), disabled: @diff_notes_disabled do
= icon('comment')
\
- if editable_diff?(diff_file)
......
......@@ -28,7 +28,7 @@
= diff_file.file_path
- if diff_file.deleted_file?
deleted
= _("deleted")
= copy_file_path_button(diff_file.file_path)
......
.nothing-here-block
This #{viewer.switcher_title} could not be displayed because #{diff_render_error_reason(viewer)}.
= _("This %{viewer} could not be displayed because %{reason}.") % { viewer: viewer.switcher_title, reason: diff_render_error_reason(viewer) }
You can
= diff_render_error_options(viewer).to_sentence(two_words_connector: ' or ', last_word_connector: ', or ').html_safe
......
......@@ -38,4 +38,4 @@
\-#{diff_file.removed_lines}
%li.dropdown-menu-empty-item.hidden
%a
No files found.
= _("No files found.")
- too_big = diff_file.diff_lines.count > Commit::DIFF_SAFE_LINES
- if too_big
.suppressed-container
%a.show-suppressed-diff.js-show-suppressed-diff Changes suppressed. Click to show.
%a.show-suppressed-diff.js-show-suppressed-diff= _("Changes suppressed. Click to show.")
%table.text-file.diff-wrap-lines.code.js-syntax-highlight.commit-diff{ data: diff_view_data, class: too_big ? 'hide' : '' }
= render partial: "projects/diffs/line",
......
.alert.alert-warning
%h4
Too many changes to show.
= _("Too many changes to show.")
.float-right
- if current_controller?(:commit)
= link_to "Plain diff", project_commit_path(@project, @commit, format: :diff), class: "btn btn-sm"
= link_to "Email patch", project_commit_path(@project, @commit, format: :patch), class: "btn btn-sm"
= link_to _("Plain diff"), project_commit_path(@project, @commit, format: :diff), class: "btn btn-sm"
= link_to _("Email patch"), project_commit_path(@project, @commit, format: :patch), class: "btn btn-sm"
- elsif current_controller?('projects/merge_requests/diffs') && @merge_request&.persisted?
= link_to "Plain diff", merge_request_path(@merge_request, format: :diff), class: "btn btn-sm"
= link_to "Email patch", merge_request_path(@merge_request, format: :patch), class: "btn btn-sm"
= link_to _("Plain diff"), merge_request_path(@merge_request, format: :diff), class: "btn btn-sm"
= link_to _("Email patch"), merge_request_path(@merge_request, format: :patch), class: "btn btn-sm"
%p
To preserve performance only
%strong #{diff_files.size} of #{diff_files.real_size}
files are displayed.
= _("To preserve performance only <strong>%{display_size} of ${real_size}</strong> files are displayed.").html_safe % { display_size: diff_files.size, real_size: diff_files.real_size }
.nothing-here-block
File added
= _("File added")
.nothing-here-block
File deleted
= _("File deleted")
- diff_file = viewer.diff_file
.nothing-here-block
File mode changed from #{diff_file.a_mode} to #{diff_file.b_mode}
= _("File mode changed from %{a_mode} to %{b_mode}") % { a_mode: diff_file.a_mode, b_mode: diff_file.b_mode }
.nothing-here-block
No preview for this file type
= _("No preview for this file type")
.nothing-here-block
This diff was suppressed by a .gitattributes entry.
= _("This diff was suppressed by a .gitattributes entry.")
- if environment.external_url && can?(current_user, :read_environment, environment)
= link_to environment.external_url, target: '_blank', rel: 'noopener noreferrer', class: 'btn external-url has-tooltip qa-view-deployment', title: s_('Environments|Open live environment') do
= sprite_icon('external-link')
View deployment
= _("View deployment")
.row.prepend-top-default.append-bottom-default
.col-lg-3
%h4.prepend-top-0
Environments
= _("Environments")
%p
Environments allow you to track deployments of your application
= succeed "." do
= link_to "Read more about environments", help_page_path("ci/environments")
- link_to_read_more = link_to(_("Read more about environments"), help_page_path("ci/environments"))
= _("Environments allow you to track deployments of your application %{link_to_read_more}.").html_safe % { link_to_read_more: link_to_read_more }
= form_for [@project.namespace.becomes(Namespace), @project, @environment], html: { class: 'col-lg-9' } do |f|
= form_errors(@environment)
.form-group
= f.label :name, 'Name', class: 'label-bold'
= f.label :name, _('Name'), class: 'label-bold'
= f.text_field :name, required: true, class: 'form-control'
.form-group
= f.label :external_url, 'External URL', class: 'label-bold'
= f.label :external_url, _('External URL'), class: 'label-bold'
= f.url_field :external_url, class: 'form-control'
.form-actions
= f.submit 'Save', class: 'btn btn-success'
= link_to 'Cancel', project_environments_path(@project), class: 'btn btn-cancel'
= f.submit _('Save'), class: 'btn btn-save'
= link_to _('Cancel'), project_environments_path(@project), class: 'btn btn-cancel'
......@@ -2,6 +2,6 @@
- return unless can?(current_user, :read_environment, environment)
= link_to environment_metrics_path(environment), title: 'See metrics', class: 'btn metrics-button' do
= link_to environment_metrics_path(environment), title: _('See metrics'), class: 'btn metrics-button' do
= sprite_icon('chart')
Monitoring
= _("Monitoring")
- @no_container = true
- page_title "Edit", @environment.name, "Environments"
- page_title _("Edit"), @environment.name, _("Environments")
%div{ class: container_class }
%h3.page-title
Edit environment
= _('Edit environment')
%hr
= render 'form'
- @no_container = true
- page_title "Environments"
- page_title _("Environments")
#environments-folder-list-view{ data: { endpoint: folder_project_environments_path(@project, @folder, format: :json),
"folder-name" => @folder,
......
- @no_container = true
- page_title "Environments"
- add_to_breadcrumbs("Pipelines", project_pipelines_path(@project))
- page_title _("Environments")
- add_to_breadcrumbs(_("Pipelines"), project_pipelines_path(@project))
#environments-list-view{ data: { environments_data: environments_list_data,
"can-create-deployment" => can?(current_user, :create_deployment, @project).to_s,
......
- @no_container = true
- page_title "Metrics for environment", @environment.name
- page_title _("Metrics for environment"), @environment.name
.prometheus-container{ class: container_class }
#prometheus-graphs{ data: metrics_data(@project, @environment) }
- @no_container = true
- breadcrumb_title "Environments"
- page_title 'New Environment'
- breadcrumb_title _("Environments")
- page_title _("New Environment")
%div{ class: container_class }
%h3.page-title
New environment
= _("New environment")
%hr
= render 'form'
- @no_container = true
- add_to_breadcrumbs "Environments", project_environments_path(@project)
- add_to_breadcrumbs _("Environments"), project_environments_path(@project)
- breadcrumb_title @environment.name
- page_title "Environments"
- page_title _("Environments")
%div{ class: container_class }
- if can?(current_user, :stop_environment, @environment)
......@@ -10,7 +10,7 @@
.modal-content
.modal-header
%h4.modal-title.d-flex.mw-100
Stopping
= s_("Environments|Stopping")
%span.has-tooltip.text-truncate.ml-1.mr-1.flex-fill{ title: @environment.name, data: { container: '#stop-environment-modal' } }
= @environment.name
?
......@@ -40,7 +40,7 @@
= render 'projects/environments/external_url', environment: @environment
= render 'projects/environments/metrics_button', environment: @environment
- if can?(current_user, :update_environment, @environment)
= link_to 'Edit', edit_project_environment_path(@project, @environment), class: 'btn'
= link_to _('Edit'), edit_project_environment_path(@project, @environment), class: 'btn'
- if can?(current_user, :stop_environment, @environment)
= button_tag class: 'btn btn-danger', type: 'button', data: { toggle: 'modal',
target: '#stop-environment-modal' } do
......@@ -52,21 +52,19 @@
.empty-state
.text-content
%h4.state-title
You don't have any deployments right now.
= _("You don't have any deployments right now.")
%p.blank-state-text
Define environments in the deploy stage(s) in
%code .gitlab-ci.yml
to track deployments here.
= _("Define environments in the deploy stage(s) in <code>.gitlab-ci.yml</code> to track deployments here.").html_safe
.text-center
= link_to _("Read more"), help_page_path("ci/environments"), class: "btn btn-success"
- else
.table-holder
.ci-table.environments{ role: 'grid' }
.gl-responsive-table-row.table-row-header{ role: 'row' }
.table-section.section-10{ role: 'columnheader' } ID
.table-section.section-30{ role: 'columnheader' } Commit
.table-section.section-25{ role: 'columnheader' } Job
.table-section.section-15{ role: 'columnheader' } Created
.table-section.section-10{ role: 'columnheader' }= _('ID')
.table-section.section-30{ role: 'columnheader' }= _('Commit')
.table-section.section-25{ role: 'columnheader' }= _('Job')
.table-section.section-15{ role: 'columnheader' }= _('Created')
= render @deployments
......
- @no_container = true
- page_title "Terminal for environment", @environment.name
- page_title _("Terminal for environment"), @environment.name
- content_for :page_specific_javascripts do
= stylesheet_link_tag "xterm.css"
......@@ -9,7 +9,7 @@
.row
.col-sm-6
%h3.page-title
Terminal for environment
= _("Terminal for environment")
= @environment.name
.col-sm-6
......
- @no_container = true
- page_title "Charts"
- page_title _("Contribution Charts")
.repo-charts{ class: container_class }
%h4.sub-header
......
- @no_container = true
- breadcrumb_title "CI / CD Charts"
- page_title _("Charts"), _("Pipelines")
- page_title _("CI / CD Charts")
%div{ class: container_class }
.sub-header-block
......
#js-authenticate-u2f
%a.btn.btn-block.btn-info#js-login-2fa-device{ href: '#' } Sign in via 2FA code
%a.btn.btn-block.btn-info#js-login-2fa-device{ href: '#' }= _("Sign in via 2FA code")
-# haml-lint:disable InlineJavaScript
%script#js-authenticate-u2f-in-progress{ type: "text/template" }
%p Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.
%p= _("Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.")
%script#js-authenticate-u2f-error{ type: "text/template" }
%div
%p <%= error_message %> (error code: <%= error_code %>)
%a.btn.btn-block.btn-warning#js-u2f-try-again Try again?
%p <%= error_message %> (#{_("error code:")} <%= error_code %>)
%a.btn.btn-block.btn-warning#js-u2f-try-again= _("Try again?")
%script#js-authenticate-u2f-authenticated{ type: "text/template" }
%div
%p We heard back from your U2F device. You have been authenticated.
%p= _("We heard back from your U2F device. You have been authenticated.")
= form_tag(new_user_session_path, method: :post, id: 'js-login-u2f-form') do |f|
- resource_params = params[resource_name].presence || params
= hidden_field_tag 'user[remember_me]', resource_params.fetch(:remember_me, 0)
......
......@@ -2,39 +2,39 @@
-# haml-lint:disable InlineJavaScript
%script#js-register-u2f-not-supported{ type: "text/template" }
%p Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer).
%p= _("Your browser doesn't support U2F. Please use Google Chrome desktop (version 41 or newer).")
%script#js-register-u2f-setup{ type: "text/template" }
- if current_user.two_factor_otp_enabled?
.row.append-bottom-10
.col-md-4
%button#js-setup-u2f-device.btn.btn-info.btn-block Set up new U2F device
%button#js-setup-u2f-device.btn.btn-info.btn-block= _("Set up new U2F device")
.col-md-8
%p Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left.
%p= _("Your U2F device needs to be set up. Plug it in (if not already) and click the button on the left.")
- else
.row.append-bottom-10
.col-md-4
%button#js-setup-u2f-device.btn.btn-info.btn-block{ disabled: true } Set up new U2F device
%button#js-setup-u2f-device.btn.btn-info.btn-block{ disabled: true }= _("Set up new U2F device")
.col-md-8
%p.text-warning You need to register a two-factor authentication app before you can set up a U2F device.
%p.text-warning= _("You need to register a two-factor authentication app before you can set up a U2F device.")
%script#js-register-u2f-in-progress{ type: "text/template" }
%p Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.
%p= _("Trying to communicate with your device. Plug it in (if you haven't already) and press the button on the device now.")
%script#js-register-u2f-error{ type: "text/template" }
%div
%p
%span <%= error_message %> (error code: <%= error_code %>)
%a.btn.btn-warning#js-u2f-try-again Try again?
%span <%= error_message %> (#{_("error code:")} <%= error_code %>)
%a.btn.btn-warning#js-u2f-try-again= _("Try again?")
%script#js-register-u2f-registered{ type: "text/template" }
.row.append-bottom-10
.col-md-12
%p Your device was successfully set up! Give it a name and register it with the GitLab server.
%p= _("Your device was successfully set up! Give it a name and register it with the GitLab server.")
= form_tag(create_u2f_profile_two_factor_auth_path, method: :post) do
.row.append-bottom-10
.col-md-3
= text_field_tag 'u2f_registration[name]', nil, class: 'form-control', placeholder: "Pick a name"
= text_field_tag 'u2f_registration[name]', nil, class: 'form-control', placeholder: _("Pick a name")
.col-md-3
= hidden_field_tag 'u2f_registration[device_response]', nil, class: 'form-control', required: true, id: "js-device-response"
= submit_tag "Register U2F device", class: "btn btn-success"
= submit_tag _("Register U2F device"), class: "btn btn-success"
.row
.col-12
.calendar-block.prepend-top-default.append-bottom-default
.user-calendar.d-none.d-sm-block{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } }
%h4.center.light
= spinner nil, true
.user-calendar-activities.d-none.d-sm-block
.row
.col-md-12.col-lg-6
.calendar-block
.content-block.hide-bottom-border
%h4
= s_('UserProfile|Activity')
.user-calendar.d-none.d-sm-block.text-left{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } }
%h4.center.light
%i.fa.fa-spinner.fa-spin
.user-calendar-activities.d-none.d-sm-block
- if can?(current_user, :read_cross_project)
.activities-block
.border-bottom.prepend-top-16
%h5
= s_('UserProfile|Recent contributions')
.prepend-top-16
.d-flex.align-items-center.border-bottom
%h4.flex-grow
= s_('UserProfile|Activity')
= link_to s_('UserProfile|View all'), user_activity_path, class: "hide js-view-all"
.overview-content-list{ data: { href: user_path } }
.center.light.loading
%i.fa.fa-spinner.fa-spin
.prepend-top-10
= link_to s_('UserProfile|View all'), user_activity_path, class: "hide js-view-all"
= spinner nil, true
.col-md-12.col-lg-6
.projects-block
.border-bottom.prepend-top-16
%h4
= s_('UserProfile|Personal projects')
.prepend-top-16
.d-flex.align-items-center.border-bottom
%h4.flex-grow
= s_('UserProfile|Personal projects')
= link_to s_('UserProfile|View all'), user_projects_path, class: "hide js-view-all"
.overview-content-list{ data: { href: user_projects_path } }
.center.light.loading
%i.fa.fa-spinner.fa-spin
.prepend-top-10
= link_to s_('UserProfile|View all'), user_projects_path, class: "hide js-view-all"
= spinner nil, true
......@@ -124,12 +124,6 @@
- if profile_tab?(:activity)
#activity.tab-pane
.row-content-block.calendar-block.white.second-block.d-none.d-sm-block
.user-calendar{ data: { calendar_path: user_calendar_path(@user, :json), calendar_activities_path: user_calendar_activities_path, utc_offset: Time.zone.utc_offset } }
%h4.center.light
%i.fa.fa-spinner.fa-spin
.user-calendar-activities
- if can?(current_user, :read_cross_project)
%h4.prepend-top-20
= s_('UserProfile|Most Recent Activity')
......
---
title: UI improvements to user's profile
merge_request: 22977
author:
type: other
---
title: Fix default sorting for subgroups and projects list
merge_request: 23058
author: Jacopo Beschi @jacopo-beschi
type: fixed
---
title: Fixes to AWS documentation spelling and grammar
merge_request: 23198
author: Brendan O'Leary
type: other
---
title: Drop default value on status column in deployments table
merge_request: 22971
author:
type: other
---
title: Enable even more frozen string for lib/gitlab
merge_request:
author: gfyoung
type: performance
---
title: Change breadcrumb title for contribution charts
merge_request: 23071
author: George Tsiolis
type: changed
---
title: Fix project identicon aligning Harry Kiselev
merge_request: 23166
author: Harry Kiselev
type: other
---
title: Escape user fullname while rendering autocomplete template to prevent XSS
merge_request:
author:
type: security
---
title: Prevent templated services from being imported
merge_request:
author:
type: security
......@@ -15,10 +15,10 @@ docs_paths_to_review = docs_paths_requiring_review(helper.all_changed_files)
unless docs_paths_to_review.empty?
message 'This merge request adds or changes files that require a ' \
'review from the docs team.'
'review from the Docs team.'
markdown(<<~MARKDOWN)
## Docs Review
## Docs review
The following files require a review from the Documentation team:
......@@ -32,24 +32,15 @@ the documentation. GitLabbers are also welcome to use the [#docs](https://gitlab
Who to ping [based on DevOps stages](https://about.gitlab.com/handbook/product/categories/#devops-stages):
| Stage | Tech writer |
| ------------- | ----------- |
| ~Create | `@marcia` |
| ~Configure | `@eread` |
| ~Distribution | `@axil` |
| ~Geo | `@eread` |
| ~Gitaly | `@axil` |
| ~Gitter | `@axil` |
| ~Manage | `@eread` |
| ~Monitoring | `@axil` |
| ~Packaging | `@axil` |
| ~Plan | `@mikelewis`|
| ~Release | `marcia` |
| ~Secure | `@axil` |
| ~Verify | `@eread` |
| Tech writer | Stage(s) |
| ------------ | ------------------------------------------------------------ |
| `@marcia` | ~Create ~Release |
| `@axil` | ~Distribution ~Gitaly ~Gitter ~Monitoring ~Packaging ~Secure |
| `@eread` | ~Manage ~Configure ~Geo ~Verify |
| `@mikelewis` | ~Plan |
If you are not sure which category the change falls within, or the change is not
part of one of these categories, you can mention the whole team with `@gl-docsteam`.
part of one of these categories, you can mention one of the usernames above.
MARKDOWN
unless gitlab.mr_labels.include?('Documentation')
......
# frozen_string_literal: true
class DropDefaultValueOnStatusDeployments < ActiveRecord::Migration
DOWNTIME = false
DEPLOYMENT_STATUS_SUCCESS = 2 # Equivalent to Deployment.state_machine.states['success'].value
def up
change_column_default :deployments, :status, nil
end
def down
change_column_default :deployments, :status, DEPLOYMENT_STATUS_SUCCESS
end
end
......@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20181107054254) do
ActiveRecord::Schema.define(version: 20181112103239) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
......@@ -924,7 +924,7 @@ ActiveRecord::Schema.define(version: 20181107054254) do
t.datetime "created_at"
t.datetime "updated_at"
t.string "on_stop"
t.integer "status", limit: 2, default: 2, null: false
t.integer "status", limit: 2, null: false
t.datetime_with_timezone "finished_at"
t.index ["created_at"], name: "index_deployments_on_created_at", using: :btree
t.index ["deployable_type", "deployable_id"], name: "index_deployments_on_deployable_type_and_deployable_id", using: :btree
......
......@@ -134,9 +134,9 @@ should be more than enough.
When removing an index make sure to use the method `remove_concurrent_index` instead
of the regular `remove_index` method. The `remove_concurrent_index` method
automatically drops concurrent indexes when using PostgreSQL, removing the
need for downtime. To use this method you must disable transactions by calling
the method `disable_ddl_transaction!` in the body of your migration class like
so:
need for downtime. To use this method you must disable single-transaction mode
by calling the method `disable_ddl_transaction!` in the body of your migration
class like so:
```ruby
class MyMigration < ActiveRecord::Migration
......
......@@ -9,7 +9,7 @@ in [significantly degraded performance](https://gitlab.com/gitlab-org/gitlab-ee/
GitLab on AWS can leverage many of the services that are already
configurable with High Availability. These services have a lot of
flexibility and are able to adopt to most companies, best of all is the
flexibility and are able to adapt to most companies, best of all is the
ability to automate both vertical and horizontal scaling.
In this article we'll go through a basic HA setup where we'll start by
......@@ -55,9 +55,9 @@ and from the Actions dropdown choose Edit DNS Hostnames and select Yes.
### Subnet
Now let's create some subnets in different Availability Zones. Make sure
that each subnet is associated the the VPC we just created, that it has
that each subnet is associated to the VPC we just created, that it has
a distinct VPC and lastly that CIDR blocks don't overlap. This will also
allow us to enable multi AZ for redundancy.
allow us to enable multi-AZ for redundancy.
We will create private and public subnets to match load balancers and
RDS instances as well.
......@@ -98,7 +98,7 @@ traffic from any destination.
![Subnet Config](img/ig-rt.png)
Before leaving this screen select the next tab to the rgiht which is
Before leaving this screen select the next tab to the right which is
Subnet Associations and add our public subnets. If you followed our
naming convention they should be easy to find.
......@@ -106,8 +106,8 @@ naming convention they should be easy to find.
## Database with RDS
For our database server we will use Amazon RDS which offers Multi AZ
for redundancy. Lets start by creating a subnet group and then we'll
For our database server we will use Amazon RDS which offers Multi-AZ
for redundancy. Let's start by creating a subnet group and then we'll
create the actual RDS instance.
### Subnet Group
......@@ -122,7 +122,7 @@ the VPC ID dropdown and at the bottom we can add our private subnets.
Select the RDS service from the Database section and create a new
PostgreSQL instance. After choosing between a Production or
Development instance we'll start with the actual configuration. On the
image bellow we have the settings for this article but note the
image below we have the settings for this article but note the
following two options which are of particular interest for HA:
1. Multi-AZ-Deployment is recommended as redundancy. Read more at
......@@ -133,7 +133,7 @@ IOPS (SSD) is best suited for HA. Read more about it at
![RDS Instance Specs](img/instance_specs.png)
The rest of the setting on this page request a DB identifier, username
The rest of the setting on this page request a DB identifier, username,
and a master password. We've chosen to use `gitlab-ha`, `gitlab` and a
very secure password respectively. Keep these in hand for later.
......@@ -152,7 +152,7 @@ EC is an in-memory hosted caching solution. Redis maintains its own
persistence and is used for certain types of application.
Let's choose the ElastiCache service in the Database section from our
AWS console. Now lets create a cache subnet group which will be very
AWS console. Now let's create a cache subnet group which will be very
similar to the RDS subnet group. Make sure to select our VPC and its
private subnets.
......@@ -160,7 +160,7 @@ private subnets.
Now press the Launch a Cache Cluster and choose Redis for our
DB engine. You'll be able to configure details such as replication,
Multi AZ and node types. The second section will allow us to choose our
Multi-AZ and node types. The second section will allow us to choose our
subnet and security group and
![Redis Cluster details](img/redis-cluster-det.png)
......@@ -274,7 +274,7 @@ username, and password.
gitlab_rails['db_password'] = "mypassword"
gitlab_rails['db_host'] = "<rds-endpoint>"
Next we only need to configure the Redis section by adding the host and
Next, we only need to configure the Redis section by adding the host and
uncommenting the port.
......@@ -285,7 +285,7 @@ to make the EFS integration easier to manage.
gitlab_rails['redis_host'] = "<redis-endpoint>"
gitlab_rails['redis_port'] = 6379
Finally run reconfigure, you might find it useful to run a check and
Finally, run reconfigure. You might find it useful to run a check and
a service status to make sure everything has been set up correctly.
sudo gitlab-ctl reconfigure
......@@ -321,10 +321,10 @@ The Load Balancer Health will allow us to indicate where to ping and what
makes up a healthy or unhealthy instance.
We won't add the instance on the next session because we'll destroy it
momentarily as we'll be using the image we where creating. We will keep
momentarily as we'll be using the image we were creating. We will keep
the Enable Cross-Zone and Enable Connection Draining active.
After we finish creating the Load Balancer we can re visit our Security
After we finish creating the Load Balancer we can revisit our Security
Groups to improve access only through the ELB and any other requirement
you might have.
......@@ -363,7 +363,7 @@ After this is launched we are able to start creating our Auto Scaling
Group. Start by giving it a name and assigning it our VPC and private
subnets. We also want to always start with two instances and if you
scroll down to Advanced Details we can choose to receive traffic from ELBs.
Lets enable that option and select our ELB. We also want to use the ELB's
Let's enable that option and select our ELB. We also want to use the ELB's
health check.
![Auto scaling](img/auto-scaling-det.png)
......@@ -388,9 +388,9 @@ we where aiming for.
After you're done with the policies section have some fun trying to break
instances. You should be able to see how the Auto Scaling Group and the
EC2 screen start bringing them up again.
EC2 screen starts bringing them up again.
High Availability is a very big area, we went mostly through scaling and
High Availability is a vast area, we went mostly through scaling and
some redundancy options but it might also imply Geographic replication.
There is a lot of ground yet to cover so have a read through these other
resources and feel free to open an issue to request additional material.
......
......@@ -235,7 +235,7 @@ There might be configuration options available for [`gitlab.yml`][yaml]. View th
```sh
cd /home/git/gitlab
git diff origin/11-1-stable:config/gitlab.yml.example origin/11-3-stable:config/gitlab.yml.example
git diff origin/11-2-stable:config/gitlab.yml.example origin/11-3-stable:config/gitlab.yml.example
```
#### Nginx configuration
......@@ -246,10 +246,10 @@ Ensure you're still up-to-date with the latest NGINX configuration changes:
cd /home/git/gitlab
# For HTTPS configurations
git diff origin/11-1-stable:lib/support/nginx/gitlab-ssl origin/11-3-stable:lib/support/nginx/gitlab-ssl
git diff origin/11-2-stable:lib/support/nginx/gitlab-ssl origin/11-3-stable:lib/support/nginx/gitlab-ssl
# For HTTP configurations
git diff origin/11-1-stable:lib/support/nginx/gitlab origin/11-3-stable:lib/support/nginx/gitlab
git diff origin/11-2-stable:lib/support/nginx/gitlab origin/11-3-stable:lib/support/nginx/gitlab
```
If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
......@@ -283,7 +283,7 @@ There might be new configuration options available for [`gitlab.default.example`
```sh
cd /home/git/gitlab
git diff origin/11-1-stable:lib/support/init.d/gitlab.default.example origin/11-3-stable:lib/support/init.d/gitlab.default.example
git diff origin/11-2-stable:lib/support/init.d/gitlab.default.example origin/11-3-stable:lib/support/init.d/gitlab.default.example
```
Ensure you're still up-to-date with the latest init script changes:
......
......@@ -235,7 +235,7 @@ There might be configuration options available for [`gitlab.yml`][yaml]. View th
```sh
cd /home/git/gitlab
git diff origin/11-1-stable:config/gitlab.yml.example origin/11-4-stable:config/gitlab.yml.example
git diff origin/11-3-stable:config/gitlab.yml.example origin/11-4-stable:config/gitlab.yml.example
```
#### Nginx configuration
......@@ -246,10 +246,10 @@ Ensure you're still up-to-date with the latest NGINX configuration changes:
cd /home/git/gitlab
# For HTTPS configurations
git diff origin/11-1-stable:lib/support/nginx/gitlab-ssl origin/11-4-stable:lib/support/nginx/gitlab-ssl
git diff origin/11-3-stable:lib/support/nginx/gitlab-ssl origin/11-4-stable:lib/support/nginx/gitlab-ssl
# For HTTP configurations
git diff origin/11-1-stable:lib/support/nginx/gitlab origin/11-4-stable:lib/support/nginx/gitlab
git diff origin/11-3-stable:lib/support/nginx/gitlab origin/11-4-stable:lib/support/nginx/gitlab
```
If you are using Strict-Transport-Security in your installation to continue using it you must enable it in your Nginx
......@@ -283,7 +283,7 @@ There might be new configuration options available for [`gitlab.default.example`
```sh
cd /home/git/gitlab
git diff origin/11-1-stable:lib/support/init.d/gitlab.default.example origin/11-4-stable:lib/support/init.d/gitlab.default.example
git diff origin/11-3-stable:lib/support/init.d/gitlab.default.example origin/11-4-stable:lib/support/init.d/gitlab.default.example
```
Ensure you're still up-to-date with the latest init script changes:
......
......@@ -28,7 +28,7 @@ module Gitlab
end
def extract_authn_context(document)
REXML::XPath.first(document, "//saml:AuthnStatement/saml:AuthnContext/saml:AuthnContextClassRef/text()").to_s
REXML::XPath.first(document, "//*[name()='saml:AuthnStatement' or name()='saml2:AuthnStatement']/*[name()='saml:AuthnContext' or name()='saml2:AuthnContext']/*[name()='saml:AuthnContextClassRef' or name()='saml2:AuthnContextClassRef']/text()").to_s
end
end
end
......
......@@ -42,7 +42,7 @@ module Gitlab
end
def self.cache_key_for_project(project)
"#{Gitlab::Redis::Cache::CACHE_NAMESPACE}:projects/#{project.id}/pipeline_status/#{project.commit&.sha}"
"#{Gitlab::Redis::Cache::CACHE_NAMESPACE}:project:#{project.id}:pipeline_status:#{project.commit&.sha}"
end
def self.update_for_pipeline(pipeline)
......
# frozen_string_literal: true
module Gitlab
module Ci
class Config
......
......@@ -165,6 +165,8 @@ excluded_attributes:
- :encrypted_token_iv
- :encrypted_url
- :encrypted_url_iv
services:
- :template
methods:
labels:
......
# frozen_string_literal: true
# Inspired by https://github.com/peek/peek-pg/blob/master/lib/peek/views/pg.rb
# PEEK_DB_CLIENT is a constant set in config/initializers/peek.rb
module Gitlab
......
# frozen_string_literal: true
module Gitlab
module Popen
class Runner
......
# frozen_string_literal: true
module Gitlab
module Profiler
class TotalTimeFlatPrinter < RubyProf::FlatPrinter
......
# frozen_string_literal: true
module Gitlab
module ProjectAuthorizations
# Calculating new project authorizations when supporting nested groups.
......
# frozen_string_literal: true
module Gitlab
module ProjectAuthorizations
# Calculating new project authorizations when not supporting nested groups.
......
# frozen_string_literal: true
module Gitlab
module Prometheus
module AdditionalMetricsParser
......
# frozen_string_literal: true
module Gitlab
module Prometheus
class Metric
......
# frozen_string_literal: true
module Gitlab
module Prometheus
class MetricGroup
......
# frozen_string_literal: true
module Gitlab
module Prometheus
ParsingError = Class.new(StandardError)
......
# frozen_string_literal: true
module Gitlab
module Prometheus
module Queries
......
# frozen_string_literal: true
module Gitlab
module Prometheus
module Queries
......
# frozen_string_literal: true
module Gitlab
module Prometheus
module Queries
......
# frozen_string_literal: true
module Gitlab
module Prometheus
module Queries
......
# frozen_string_literal: true
module Gitlab
module Prometheus
module Queries
......
# frozen_string_literal: true
module Gitlab
module Prometheus
module Queries
......
# frozen_string_literal: true
module Gitlab
module Prometheus
module Queries
......
# frozen_string_literal: true
module Gitlab
module QueryLimiting
class ActiveSupportSubscriber < ActiveSupport::Subscriber
......
# frozen_string_literal: true
module Gitlab
module QueryLimiting
class Transaction
......@@ -68,7 +70,7 @@ module Gitlab
def error_message
header = 'Too many SQL queries were executed'
header += " in #{action}" if action
header = "#{header} in #{action}" if action
"#{header}: a maximum of #{THRESHOLD} is allowed but #{count} SQL queries were executed"
end
......
# frozen_string_literal: true
module Gitlab
module QuickActions
class CommandDefinition
......
# frozen_string_literal: true
module Gitlab
module QuickActions
module Dsl
......
# frozen_string_literal: true
module Gitlab
module QuickActions
# This class takes an array of commands that should be extracted from a
......
# frozen_string_literal: true
module Gitlab
module QuickActions
# This class takes spend command argument
......
# frozen_string_literal: true
module Gitlab
module QuickActions
class SubstitutionDefinition < CommandDefinition
......
# frozen_string_literal: true
# please require all dependencies below:
require_relative 'wrapper' unless defined?(::Rails) && ::Rails.root.present?
......
# frozen_string_literal: true
# please require all dependencies below:
require_relative 'wrapper' unless defined?(::Gitlab::Redis::Wrapper)
......
# frozen_string_literal: true
# please require all dependencies below:
require_relative 'wrapper' unless defined?(::Gitlab::Redis::Wrapper)
......
# frozen_string_literal: true
# This file should only be used by sub-classes, not directly by any clients of the sub-classes
# please require all dependencies below:
require 'active_support/core_ext/hash/keys'
......
......@@ -7,13 +7,13 @@ module Gitlab
def initialize(repository, extra_namespace: nil, backend: Rails.cache)
@repository = repository
@namespace = "#{repository.full_path}:#{repository.project.id}"
@namespace = "project:#{repository.project.id}"
@namespace = "#{@namespace}:#{extra_namespace}" if extra_namespace
@backend = backend
end
def cache_key(type)
"#{type}:#{namespace}"
"#{namespace}:#{type}"
end
def expire(key)
......
# frozen_string_literal: true
require 'ruby-prof'
module Gitlab
......
# frozen_string_literal: true
module Gitlab
module RequestProfiler
class Profile
......
# frozen_string_literal: true
module Gitlab
module Sanitizers
module SVG
......
# frozen_string_literal: true
# Generated from:
# SVG element list: https://www.w3.org/TR/SVG/eltindex.html
# SVG Attribute list: https://www.w3.org/TR/SVG/attindex.html
......
# frozen_string_literal: true
module Gitlab
module Search
class ParsedQuery
......
# frozen_string_literal: true
module Gitlab
module Search
class Query < SimpleDelegator
......
# frozen_string_literal: true
module Gitlab
module Serializer
module Ci
......
# frozen_string_literal: true
module Gitlab
module Serializer
class Pagination
......
# frozen_string_literal: true
module Gitlab
module Sherlock
# A collection of transactions recorded by Sherlock.
......
# frozen_string_literal: true
module Gitlab
module Sherlock
class FileSample
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment