Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
5b98c2c506
commit
fd8183c340
|
|
@ -1 +1 @@
|
|||
5c143379d62a9489c5c24e42fb177bb5b7f09318
|
||||
c832720d9ad3948e6cf2c371f01c85e9dd9a3a5a
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import SafeHtml from '~/vue_shared/directives/safe_html';
|
|||
import { createAlert, VARIANT_INFO } from '~/flash';
|
||||
import { s__, sprintf } from '~/locale';
|
||||
import createEmptyBadge from '../empty_badge';
|
||||
import { PLACEHOLDERS } from '../constants';
|
||||
import Badge from './badge.vue';
|
||||
|
||||
const badgePreviewDelayInMilliseconds = 1500;
|
||||
|
|
@ -51,9 +50,9 @@ export default {
|
|||
return this.badgeInAddForm;
|
||||
},
|
||||
helpText() {
|
||||
const placeholders = PLACEHOLDERS.map((placeholder) => `<code>%{${placeholder}}</code>`).join(
|
||||
', ',
|
||||
);
|
||||
const placeholders = ['project_path', 'project_id', 'default_branch', 'commit_sha']
|
||||
.map((placeholder) => `<code>%{${placeholder}}</code>`)
|
||||
.join(', ');
|
||||
return sprintf(
|
||||
s__('Badges|Supported %{docsLinkStart}variables%{docsLinkEnd}: %{placeholders}'),
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,9 +1,2 @@
|
|||
export const GROUP_BADGE = 'group';
|
||||
export const PROJECT_BADGE = 'project';
|
||||
export const PLACEHOLDERS = [
|
||||
'project_path',
|
||||
'project_name',
|
||||
'project_id',
|
||||
'default_branch',
|
||||
'commit_sha',
|
||||
];
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
mutation updateAlertStatus($projectPath: ID!, $status: AlertManagementStatus!, $iid: String!) {
|
||||
updateAlertStatus(input: { iid: $iid, status: $status, projectPath: $projectPath }) {
|
||||
errors
|
||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
||||
alert {
|
||||
iid
|
||||
status
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ query alertDetails($fullPath: ID!, $alertId: String) {
|
|||
project(fullPath: $fullPath) {
|
||||
id
|
||||
alertManagementAlerts(iid: $alertId) {
|
||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
||||
nodes {
|
||||
...AlertDetailItem
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ query getAlerts(
|
|||
before: $prevPageCursor
|
||||
domain: $domain
|
||||
) {
|
||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
||||
nodes {
|
||||
...AlertListItem
|
||||
assignees {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ query getAlert($iid: String!, $fullPath: ID!) {
|
|||
id
|
||||
issue(iid: $iid) {
|
||||
id
|
||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
||||
alertManagementAlert {
|
||||
iid
|
||||
title
|
||||
|
|
|
|||
|
|
@ -0,0 +1,87 @@
|
|||
<script>
|
||||
import { GlListbox } from '@gitlab/ui';
|
||||
import { debounce } from 'lodash';
|
||||
import { createAlert } from '~/flash';
|
||||
import { __ } from '~/locale';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
GlListbox,
|
||||
},
|
||||
inject: {
|
||||
targetProjectsPath: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
currentProject: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentProject: this.currentProject,
|
||||
selected: this.currentProject.value,
|
||||
isLoading: false,
|
||||
projects: [],
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
async fetchProjects(search = '') {
|
||||
this.isLoading = true;
|
||||
|
||||
try {
|
||||
const { data } = await axios.get(this.targetProjectsPath, {
|
||||
params: { search },
|
||||
});
|
||||
|
||||
this.projects = data.map((p) => ({
|
||||
value: `${p.id}`,
|
||||
text: p.full_path.replace(/^\//, ''),
|
||||
refsUrl: p.refs_url,
|
||||
}));
|
||||
this.isLoading = false;
|
||||
} catch {
|
||||
createAlert({
|
||||
message: __('Error fetching target projects. Please try again.'),
|
||||
primaryButton: { text: __('Try again'), clickHandler: () => this.fetchProjects(search) },
|
||||
});
|
||||
}
|
||||
},
|
||||
searchProjects: debounce(function searchProjects(search) {
|
||||
this.fetchProjects(search);
|
||||
}, 500),
|
||||
selectProject(projectId) {
|
||||
this.currentProject = this.projects.find((p) => p.value === projectId);
|
||||
|
||||
this.$emit('project-selected', this.currentProject.refsUrl);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<input
|
||||
id="merge_request_target_project_id"
|
||||
type="hidden"
|
||||
:value="currentProject.value"
|
||||
name="merge_request[target_project_id]"
|
||||
data-testid="target-project-input"
|
||||
/>
|
||||
<gl-listbox
|
||||
v-model="selected"
|
||||
:items="projects"
|
||||
:toggle-text="currentProject.text"
|
||||
:header-text="__('Select target project')"
|
||||
:searching="isLoading"
|
||||
searchable
|
||||
class="gl-w-full dropdown-target-project"
|
||||
toggle-class="gl-align-items-flex-start! gl-justify-content-start! mr-compare-dropdown js-target-project"
|
||||
@shown="fetchProjects"
|
||||
@search="searchProjects"
|
||||
@select="selectProject"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -26,7 +26,10 @@ const updateCommitList = (url, $emptyState, $loadingIndicator, $commitList, para
|
|||
|
||||
export default (mrNewCompareNode) => {
|
||||
const { sourceBranchUrl, targetBranchUrl } = mrNewCompareNode.dataset;
|
||||
initTargetProjectDropdown();
|
||||
|
||||
if (!window.gon?.features?.mrCompareDropdowns) {
|
||||
initTargetProjectDropdown();
|
||||
}
|
||||
|
||||
const updateSourceBranchCommitList = () =>
|
||||
updateCommitList(
|
||||
|
|
|
|||
|
|
@ -1,10 +1,37 @@
|
|||
import $ from 'jquery';
|
||||
import Vue from 'vue';
|
||||
import initPipelines from '~/commit/pipelines/pipelines_bundle';
|
||||
import MergeRequest from '~/merge_request';
|
||||
import TargetProjectDropdown from '~/merge_requests/components/target_project_dropdown.vue';
|
||||
import initCompare from './compare';
|
||||
|
||||
const mrNewCompareNode = document.querySelector('.js-merge-request-new-compare');
|
||||
if (mrNewCompareNode) {
|
||||
initCompare(mrNewCompareNode);
|
||||
|
||||
const el = document.getElementById('js-target-project-dropdown');
|
||||
const { targetProjectsPath, currentProject } = el.dataset;
|
||||
|
||||
// eslint-disable-next-line no-new
|
||||
new Vue({
|
||||
el,
|
||||
name: 'TargetProjectDropdown',
|
||||
provide: {
|
||||
targetProjectsPath,
|
||||
currentProject: JSON.parse(currentProject),
|
||||
},
|
||||
render(h) {
|
||||
return h(TargetProjectDropdown, {
|
||||
on: {
|
||||
'project-selected': function projectSelectedFunction(refsUrl) {
|
||||
const $targetBranchDropdown = $('.js-target-branch');
|
||||
$targetBranchDropdown.data('refsUrl', refsUrl);
|
||||
$targetBranchDropdown.data('deprecatedJQueryDropdown').clearMenu();
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
} else {
|
||||
const mrNewSubmitNode = document.querySelector('.js-merge-request-new-submit');
|
||||
// eslint-disable-next-line no-new
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ query alertAssignees(
|
|||
) {
|
||||
workspace: project(fullPath: $fullPath) {
|
||||
id
|
||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
||||
issuable: alertManagementAlert(domain: $domain, iid: $iid) {
|
||||
iid
|
||||
assignees {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ mutation alertSetAssignees($fullPath: ID!, $assigneeUsernames: [String!]!, $iid:
|
|||
input: { iid: $iid, assigneeUsernames: $assigneeUsernames, projectPath: $fullPath }
|
||||
) {
|
||||
errors
|
||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
||||
issuable: alert {
|
||||
iid
|
||||
assignees {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
mutation alertTodoCreate($projectPath: ID!, $iid: String!) {
|
||||
alertTodoCreate(input: { iid: $iid, projectPath: $projectPath }) {
|
||||
errors
|
||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
||||
alert {
|
||||
...AlertDetailItem
|
||||
assignees {
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ query alertDetailsAssignees($fullPath: ID!, $alertId: String) {
|
|||
project(fullPath: $fullPath) {
|
||||
id
|
||||
alertManagementAlerts(iid: $alertId) {
|
||||
# eslint-disable-next-line @graphql-eslint/require-id-when-available
|
||||
nodes {
|
||||
...AlertDetailItem
|
||||
assignees {
|
||||
|
|
|
|||
|
|
@ -382,3 +382,9 @@ $comparison-empty-state-height: 62px;
|
|||
.survey-slide-up-enter-active {
|
||||
@include gl-transition-slow;
|
||||
}
|
||||
|
||||
.mr-compare-dropdown {
|
||||
.gl-button-text {
|
||||
@include gl-w-full;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,12 @@ module Observability
|
|||
default_frame_src = p.directives['frame-src'] || p.directives['default-src']
|
||||
|
||||
# When ObservabilityUI is not authenticated, it needs to be able
|
||||
# to redirect to the GL sign-in page, hence 'self'
|
||||
frame_src_values = Array.wrap(default_frame_src) | [Gitlab::Observability.observability_url, "'self'"]
|
||||
# to redirect to the GL sign-in page, hence '/users/sign_in' and '/oauth/authorize'
|
||||
frame_src_values = Array.wrap(default_frame_src) | [Gitlab::Observability.observability_url,
|
||||
Gitlab::Utils.append_path(Gitlab.config.gitlab.url,
|
||||
'/users/sign_in'),
|
||||
Gitlab::Utils.append_path(Gitlab.config.gitlab.url,
|
||||
'/oauth/authorize')]
|
||||
|
||||
p.frame_src(*frame_src_values)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -169,6 +169,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
|
|||
# available in the logs for this request.
|
||||
Gitlab::ApplicationContext.push(user: user)
|
||||
log_audit_event(user, with: oauth['provider'])
|
||||
Gitlab::Tracking.event(self.class.name, "#{oauth['provider']}_sso", user: user) if new_user
|
||||
|
||||
set_remember_me(user)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ class Projects::IssuesController < Projects::ApplicationController
|
|||
include IssuableCollections
|
||||
include IssuesCalendar
|
||||
include RecordUserLastActivity
|
||||
include ::Observability::ContentSecurityPolicy
|
||||
|
||||
ISSUES_EXCEPT_ACTIONS = %i[index calendar new create bulk_update import_csv export_csv service_desk].freeze
|
||||
SET_ISSUABLES_INDEX_ONLY_ACTIONS = %i[index calendar service_desk].freeze
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
|
|||
include DiffForPath
|
||||
include DiffHelper
|
||||
include RendersCommits
|
||||
include ::Observability::ContentSecurityPolicy
|
||||
|
||||
skip_before_action :merge_request
|
||||
before_action :authorize_create_merge_request_from!
|
||||
|
|
@ -19,6 +20,10 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
|
|||
:branch_to
|
||||
]
|
||||
|
||||
before_action do
|
||||
push_frontend_feature_flag(:mr_compare_dropdowns, project)
|
||||
end
|
||||
|
||||
def new
|
||||
define_new_vars
|
||||
end
|
||||
|
|
@ -89,6 +94,14 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
|
|||
render layout: false
|
||||
end
|
||||
|
||||
def target_projects
|
||||
projects = MergeRequestTargetProjectFinder
|
||||
.new(current_user: current_user, source_project: @project, project_feature: :repository)
|
||||
.execute(include_routes: true).limit(20).search(params[:search])
|
||||
|
||||
render json: ProjectSerializer.new.represent(projects)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def build_merge_request
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
|
|||
include SourcegraphDecorator
|
||||
include DiffHelper
|
||||
include Gitlab::Cache::Helpers
|
||||
include ::Observability::ContentSecurityPolicy
|
||||
|
||||
prepend_before_action(only: [:index]) { authenticate_sessionless_user!(:rss) }
|
||||
skip_before_action :merge_request, only: [:index, :bulk_update, :export_csv]
|
||||
|
|
|
|||
|
|
@ -111,8 +111,11 @@ class RegistrationsController < Devise::RegistrationsController
|
|||
super
|
||||
end
|
||||
|
||||
# overridden by EE module
|
||||
def after_request_hook(user)
|
||||
# overridden by EE module
|
||||
return unless user.persisted?
|
||||
|
||||
Gitlab::Tracking.event(self.class.name, 'successfully_submitted_form', user: user)
|
||||
end
|
||||
|
||||
def after_sign_up_path_for(user)
|
||||
|
|
@ -226,12 +229,14 @@ class RegistrationsController < Devise::RegistrationsController
|
|||
Gitlab::Recaptcha.load_configurations!
|
||||
end
|
||||
|
||||
# overridden by EE module
|
||||
def set_resource_fields
|
||||
return unless set_blocked_pending_approval?
|
||||
|
||||
resource.state = User::BLOCKED_PENDING_APPROVAL_STATE
|
||||
end
|
||||
|
||||
# overridden by EE module
|
||||
def set_blocked_pending_approval?
|
||||
Gitlab::CurrentSettings.require_admin_approval_after_user_signup
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,6 +13,11 @@ module Types
|
|||
|
||||
authorize :read_alert_management_alert
|
||||
|
||||
field :id,
|
||||
GraphQL::Types::ID,
|
||||
null: false,
|
||||
description: 'ID of the alert.'
|
||||
|
||||
field :iid,
|
||||
GraphQL::Types::ID,
|
||||
null: false,
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@ class Badge < ApplicationRecord
|
|||
# the placeholder is found.
|
||||
PLACEHOLDERS = {
|
||||
'project_path' => :full_path,
|
||||
'project_name' => :name,
|
||||
'project_id' => :id,
|
||||
'default_branch' => :default_branch,
|
||||
'commit_sha' => ->(project) { project.commit&.sha }
|
||||
|
|
|
|||
|
|
@ -1352,8 +1352,7 @@ module Ci
|
|||
return unless bridge_waiting?
|
||||
return unless current_user.can?(:update_pipeline, source_bridge.pipeline)
|
||||
|
||||
source_bridge.pending!
|
||||
Ci::ResetSkippedJobsService.new(project, current_user).execute(source_bridge) # rubocop:disable CodeReuse/ServiceClass
|
||||
Ci::EnqueueJobService.new(source_bridge, current_user: current_user).execute(&:pending!) # rubocop:disable CodeReuse/ServiceClass
|
||||
end
|
||||
|
||||
# EE-only
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ module HasUserType
|
|||
scope :humans, -> { where(user_type: :human) }
|
||||
scope :bots, -> { where(user_type: BOT_USER_TYPES) }
|
||||
scope :without_bots, -> { humans.or(where.not(user_type: BOT_USER_TYPES)) }
|
||||
scope :bots_without_project_bot, -> { where(user_type: BOT_USER_TYPES - ['project_bot']) }
|
||||
scope :non_internal, -> { humans.or(where(user_type: NON_INTERNAL_USER_TYPES)) }
|
||||
scope :without_ghosts, -> { humans.or(where.not(user_type: :ghost)) }
|
||||
scope :without_project_bot, -> { humans.or(where.not(user_type: :project_bot)) }
|
||||
|
|
|
|||
|
|
@ -13,4 +13,8 @@ class ProjectEntity < Grape::Entity
|
|||
expose :full_name, documentation: { type: 'string', example: 'GitLab Org / GitLab' } do |project|
|
||||
project.full_name
|
||||
end
|
||||
|
||||
expose :refs_url do |project|
|
||||
refs_project_path(project)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Ci
|
||||
class EnqueueJobService
|
||||
attr_accessor :job, :current_user, :variables
|
||||
|
||||
def initialize(job, current_user:, variables: nil)
|
||||
@job = job
|
||||
@current_user = current_user
|
||||
@variables = variables
|
||||
end
|
||||
|
||||
def execute(&transition)
|
||||
job.user = current_user
|
||||
job.job_variables_attributes = variables if variables
|
||||
|
||||
transition ||= ->(job) { job.enqueue! }
|
||||
Gitlab::OptimisticLocking.retry_lock(job, name: 'ci_enqueue_job', &transition)
|
||||
|
||||
ResetSkippedJobsService.new(job.project, current_user).execute(job)
|
||||
|
||||
job
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -5,12 +5,7 @@ module Ci
|
|||
def execute(bridge)
|
||||
check_access!(bridge)
|
||||
|
||||
bridge.tap do |bridge|
|
||||
bridge.user = current_user
|
||||
bridge.enqueue!
|
||||
|
||||
ResetSkippedJobsService.new(project, current_user).execute(bridge)
|
||||
end
|
||||
Ci::EnqueueJobService.new(bridge, current_user: current_user).execute
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -5,17 +5,7 @@ module Ci
|
|||
def execute(build, job_variables_attributes = nil)
|
||||
check_access!(build, job_variables_attributes)
|
||||
|
||||
if build.can_enqueue?
|
||||
build.user = current_user
|
||||
build.job_variables_attributes = job_variables_attributes || []
|
||||
build.enqueue!
|
||||
|
||||
ResetSkippedJobsService.new(project, current_user).execute(build)
|
||||
|
||||
build
|
||||
else
|
||||
retry_build(build)
|
||||
end
|
||||
Ci::EnqueueJobService.new(build, current_user: current_user, variables: job_variables_attributes || []).execute
|
||||
rescue StateMachines::InvalidTransition
|
||||
retry_build(build.reset)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -40,17 +40,20 @@
|
|||
%h2.gl-font-size-h2
|
||||
= _('Target branch')
|
||||
.clearfix
|
||||
- projects = target_projects(@project)
|
||||
.merge-request-select.dropdown
|
||||
= f.hidden_field :target_project_id
|
||||
= dropdown_toggle f.object.target_project.full_path, { toggle: "dropdown", 'field-name': "#{f.object_name}[target_project_id]", disabled: @merge_request.persisted?, default_text: _("Select target project") }, { toggle_class: "js-compare-dropdown js-target-project" }
|
||||
.dropdown-menu.dropdown-menu-selectable.dropdown-target-project
|
||||
= dropdown_title(_("Select target project"))
|
||||
= dropdown_filter(_("Search projects"))
|
||||
= dropdown_content do
|
||||
= render 'projects/merge_requests/dropdowns/project',
|
||||
projects: projects,
|
||||
selected: f.object.target_project_id
|
||||
- if Feature.enabled?(:mr_compare_dropdowns, @project)
|
||||
#js-target-project-dropdown{ data: { target_projects_path: project_new_merge_request_json_target_projects_path(@project), current_project: { value: f.object.target_project_id.to_s, text: f.object.target_project.full_path }.to_json } }
|
||||
- else
|
||||
- projects = target_projects(@project)
|
||||
= f.hidden_field :target_project_id
|
||||
= dropdown_toggle f.object.target_project.full_path, { toggle: "dropdown", 'field-name': "#{f.object_name}[target_project_id]", disabled: @merge_request.persisted?, default_text: _("Select target project") }, { toggle_class: "js-compare-dropdown js-target-project" }
|
||||
.dropdown-menu.dropdown-menu-selectable.dropdown-target-project
|
||||
= dropdown_title(_("Select target project"))
|
||||
= dropdown_filter(_("Search projects"))
|
||||
= dropdown_content do
|
||||
= render 'projects/merge_requests/dropdowns/project',
|
||||
projects: projects,
|
||||
selected: f.object.target_project_id
|
||||
.merge-request-select.dropdown
|
||||
= f.hidden_field :target_branch
|
||||
= dropdown_toggle f.object.target_branch.presence || _("Select target branch"), { toggle: "dropdown", 'field-name': "#{f.object_name}[target_branch]", 'refs-url': refs_project_path(f.object.target_project), selected: f.object.target_branch, default_text: _("Select target branch") }, { toggle_class: "js-compare-dropdown js-target-branch monospace" }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: mr_compare_dropdowns
|
||||
introduced_by_url:
|
||||
rollout_issue_url:
|
||||
milestone: '15.7'
|
||||
type: development
|
||||
group: group::code review
|
||||
default_enabled: false
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
name: report_heap_dumps
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106406
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/385175
|
||||
milestone: '15.7'
|
||||
type: ops
|
||||
group: group::application performance
|
||||
default_enabled: false
|
||||
|
|
@ -8,8 +8,6 @@ Gitlab::Cluster::LifecycleEvents.on_worker_start do
|
|||
Gitlab::Memory::ReportsDaemon.instance.start
|
||||
end
|
||||
|
||||
return unless Gitlab::Utils.to_boolean(ENV['GITLAB_MEMWD_DUMP_HEAP'])
|
||||
|
||||
Gitlab::Cluster::LifecycleEvents.on_worker_stop do
|
||||
Gitlab::Memory::Reporter.new.run_report(
|
||||
Gitlab::Memory::Reports::HeapDump.new
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ scope path: 'merge_requests', controller: 'merge_requests/creations' do
|
|||
scope constraints: ->(req) { req.format == :json }, as: :json do
|
||||
get :diffs
|
||||
get :pipelines
|
||||
get :target_projects
|
||||
end
|
||||
|
||||
scope action: :new do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
class RemoveIndexICiJobTokenProjectScopeLinksOnSourceAndTargetProject < Gitlab::Database::Migration[2.0]
|
||||
disable_ddl_transaction!
|
||||
|
||||
TABLE_NAME = 'ci_job_token_project_scope_links'
|
||||
OLD_INDEX_NAME = 'i_ci_job_token_project_scope_links_on_source_and_target_project'
|
||||
NEW_INDEX_NAME = 'ci_job_token_scope_links_source_and_target_project_direction'
|
||||
NEW_INDEX_COL = %w[source_project_id target_project_id direction]
|
||||
|
||||
def up
|
||||
add_concurrent_index(
|
||||
TABLE_NAME,
|
||||
NEW_INDEX_COL,
|
||||
name: NEW_INDEX_NAME,
|
||||
unique: true
|
||||
)
|
||||
remove_concurrent_index_by_name(TABLE_NAME, OLD_INDEX_NAME)
|
||||
end
|
||||
|
||||
def down
|
||||
# noop: as we can have duplicate records once the unique index is removed
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
8e9641a603bd9540d0004fb76b407a5cb4392c8cc41c084cd746f354b9a8d417
|
||||
|
|
@ -27999,6 +27999,8 @@ CREATE INDEX ca_aggregations_last_incremental_run_at ON analytics_cycle_analytic
|
|||
|
||||
CREATE INDEX ci_builds_gitlab_monitor_metrics ON ci_builds USING btree (status, created_at, project_id) WHERE ((type)::text = 'Ci::Build'::text);
|
||||
|
||||
CREATE UNIQUE INDEX ci_job_token_scope_links_source_and_target_project_direction ON ci_job_token_project_scope_links USING btree (source_project_id, target_project_id, direction);
|
||||
|
||||
CREATE INDEX ci_pipeline_artifacts_on_expire_at_for_removal ON ci_pipeline_artifacts USING btree (expire_at) WHERE ((locked = 0) AND (expire_at IS NOT NULL));
|
||||
|
||||
CREATE INDEX code_owner_approval_required ON protected_branches USING btree (project_id, code_owner_approval_required) WHERE (code_owner_approval_required = true);
|
||||
|
|
@ -28029,8 +28031,6 @@ CREATE INDEX finding_links_on_vulnerability_occurrence_id ON vulnerability_findi
|
|||
|
||||
CREATE INDEX i_batched_background_migration_job_transition_logs_on_job_id ON ONLY batched_background_migration_job_transition_logs USING btree (batched_background_migration_job_id);
|
||||
|
||||
CREATE UNIQUE INDEX i_ci_job_token_project_scope_links_on_source_and_target_project ON ci_job_token_project_scope_links USING btree (source_project_id, target_project_id);
|
||||
|
||||
CREATE INDEX i_compliance_frameworks_on_id_and_created_at ON compliance_management_frameworks USING btree (id, created_at, pipeline_configuration_full_path);
|
||||
|
||||
CREATE UNIQUE INDEX i_pm_licenses_on_spdx_identifier ON pm_licenses USING btree (spdx_identifier);
|
||||
|
|
|
|||
|
|
@ -264,7 +264,7 @@ Install the correct certificate based on your certificate type:
|
|||
- **Multi-domain certificate** that includes both primary and secondary site domains: Install the certificate at `/etc/gitlab/ssl` on all **Rails, Sidekiq, and Gitaly** nodes in the **secondary** site.
|
||||
- **Single-domain certificate** where the certificates are specific to each Geo site domain: Generate a valid certificate for your **secondary** site's domain and install it at `/etc/gitlab/ssl` per [these instructions](https://docs.gitlab.com/omnibus/settings/ssl.html#install-custom-public-certificates) on all **Rails, Sidekiq, and Gitaly** nodes in the **secondary** site.
|
||||
|
||||
#### Connecting to external services that use customer certificates
|
||||
#### Connecting to external services that use custom certificates
|
||||
|
||||
A copy of the self-signed certificate for the external service needs to be added to the trust store on all the **primary** site's nodes that require access to the service.
|
||||
|
||||
|
|
|
|||
|
|
@ -161,11 +161,13 @@ seconds:
|
|||
- `gitaly_calls`: Total number of calls made to Gitaly
|
||||
- `redis_calls`: Total number of calls made to Redis
|
||||
- `redis_cross_slot_calls`: Total number of cross-slot calls made to Redis
|
||||
- `redis_allowed_cross_slot_calls`: Total number of allowed cross-slot calls made to Redis
|
||||
- `redis_duration_s`: Total time to retrieve data from Redis
|
||||
- `redis_read_bytes`: Total bytes read from Redis
|
||||
- `redis_write_bytes`: Total bytes written to Redis
|
||||
- `redis_<instance>_calls`: Total number of calls made to a Redis instance
|
||||
- `redis_<instance>_cross_slot_calls`: Total number of cross-slot calls made to a Redis instance
|
||||
- `redis_<instance>_allowed_cross_slot_calls`: Total number of allowed cross-slot calls made to a Redis instance
|
||||
- `redis_<instance>_duration_s`: Total time to retrieve data from a Redis instance
|
||||
- `redis_<instance>_read_bytes`: Total bytes read from a Redis instance
|
||||
- `redis_<instance>_write_bytes`: Total bytes written to a Redis instance
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ them to disable Maintenance Mode after it's been enabled.
|
|||
|
||||
All users can sign in and out of the GitLab instance but no new users can be created.
|
||||
|
||||
If there are [LDAP syncs](../auth/ldap/index.md) scheduled for that time, they fail since user creation is disabled. Similarly, [user creations based on SAML](../../integration/saml.md#general-setup) fail.
|
||||
If there are [LDAP syncs](../auth/ldap/index.md) scheduled for that time, they fail since user creation is disabled. Similarly, [user creations based on SAML](../../integration/saml.md#configure-saml-support-in-gitlab) fail.
|
||||
|
||||
### Git actions
|
||||
|
||||
|
|
|
|||
|
|
@ -379,7 +379,7 @@ To enable LDAP with the synchronization worker for Sidekiq:
|
|||
|
||||
## Configure SAML Groups for SAML Group Sync
|
||||
|
||||
If you use [SAML Group Sync](../../user/group/saml_sso/group_sync.md), you must configure [SAML Groups](../../integration/saml.md#saml-groups) on all your Sidekiq nodes.
|
||||
If you use [SAML Group Sync](../../user/group/saml_sso/group_sync.md), you must configure [SAML Groups](../../integration/saml.md#configure-users-based-on-saml-group-membership) on all your Sidekiq nodes.
|
||||
|
||||
## Disable Rugged
|
||||
|
||||
|
|
|
|||
|
|
@ -10195,6 +10195,7 @@ Describes an alert from the project's Alert Management.
|
|||
| <a id="alertmanagementalertenvironment"></a>`environment` | [`Environment`](#environment) | Environment for the alert. |
|
||||
| <a id="alertmanagementalerteventcount"></a>`eventCount` | [`Int`](#int) | Number of events of this alert. |
|
||||
| <a id="alertmanagementalerthosts"></a>`hosts` | [`[String!]`](#string) | List of hosts the alert came from. |
|
||||
| <a id="alertmanagementalertid"></a>`id` | [`ID!`](#id) | ID of the alert. |
|
||||
| <a id="alertmanagementalertiid"></a>`iid` | [`ID!`](#id) | Internal ID of the alert. |
|
||||
| <a id="alertmanagementalertissue"></a>`issue` | [`Issue`](#issue) | Issue attached to the alert. |
|
||||
| <a id="alertmanagementalertissueiid"></a>`issueIid` **{warning-solid}** | [`ID`](#id) | **Deprecated** in 13.10. Use issue field. |
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ Badges support placeholders that are replaced in real time in both the link and
|
|||
<!-- vale gitlab.Spelling = NO -->
|
||||
|
||||
- **%{project_path}**: replaced by the project path.
|
||||
- **%{project_name}**: replaced by the project name.
|
||||
- **%{project_id}**: replaced by the project ID.
|
||||
- **%{default_branch}**: replaced by the project default branch.
|
||||
- **%{commit_sha}**: replaced by the last project's commit SHA.
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ Badges support placeholders that are replaced in real-time in both the link and
|
|||
<!-- vale gitlab.Spelling = NO -->
|
||||
|
||||
- **%{project_path}**: Replaced by the project path.
|
||||
- **%{project_name}**: Replaced by the project name.
|
||||
- **%{project_id}**: Replaced by the project ID.
|
||||
- **%{default_branch}**: Replaced by the project default branch.
|
||||
- **%{commit_sha}**: Replaced by the last project's commit SHA.
|
||||
|
|
|
|||
|
|
@ -18,9 +18,11 @@ Jobs handled by macOS shared runners on GitLab.com **time out after 3 hours**, r
|
|||
|
||||
## Access request process
|
||||
|
||||
While in beta, to run CI jobs on the macOS runners, GitLab SaaS customer namespaces must be explicitly added to the macOS `allow-list`.
|
||||
While in beta, to run CI jobs on the macOS runners, you must specify the GitLab SaaS customer personal or group [namespaces](../../../user/namespace/index.md) in the macOS `allow-list`. These are the namespaces that use the macOS runners.
|
||||
|
||||
After you have been added, you can use the macOS runners for any projects in your namespace.
|
||||
When you specify a personal or group namespace, the top level group is not added unless you specify it.
|
||||
|
||||
After you add your namespace, you can use the macOS runners for any projects under the namespace you included.
|
||||
|
||||
To request access, open an [access request](https://gitlab.com/gitlab-com/runner-saas-macos-limited-availability/-/issues/new).
|
||||
The expected turnaround for activation is two business days.
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ for the OpenID Connect provider and the Twitter OAuth provider.
|
|||
|
||||
This method of enabling automatic linking works for all providers
|
||||
[except SAML](https://gitlab.com/gitlab-org/gitlab/-/issues/338293).
|
||||
To enable automatic linking for SAML, see the [SAML setup instructions](saml.md#general-setup).
|
||||
To enable automatic linking for SAML, see the [SAML setup instructions](saml.md#configure-saml-support-in-gitlab).
|
||||
|
||||
## Create an external providers list
|
||||
|
||||
|
|
|
|||
|
|
@ -5,34 +5,21 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
type: reference
|
||||
---
|
||||
|
||||
# SAML OmniAuth Provider **(FREE SELF)**
|
||||
# SAML SSO for self-managed GitLab instances **(FREE SELF)**
|
||||
|
||||
This page describes instance-wide SAML for self-managed GitLab instances. For
|
||||
SAML on GitLab.com, see [SAML SSO for GitLab.com groups](../user/group/saml_sso/index.md).
|
||||
This page describes instance-wide SAML 2.0 for self-managed GitLab instances. For
|
||||
SAML 2.0 on GitLab.com, see [SAML SSO for GitLab.com groups](../user/group/saml_sso/index.md).
|
||||
|
||||
You should also reference the [OmniAuth documentation](omniauth.md) for general
|
||||
settings that apply to all OmniAuth providers.
|
||||
|
||||
## Glossary of common terms
|
||||
|
||||
| Term | Description |
|
||||
|--------------------------------|-------------|
|
||||
| Identity provider (IdP) | The service which manages your user identities, such as Okta or OneLogin. |
|
||||
| Service provider (SP) | GitLab can be configured as a SAML 2.0 SP. |
|
||||
| Assertion | A piece of information about a user's identity, such as their name or role. Also known as claims or attributes. |
|
||||
| Single Sign-On (SSO) | Name of authentication scheme. |
|
||||
| Assertion consumer service URL | The callback on GitLab where users are redirected after successfully authenticating with the identity provider. |
|
||||
| Issuer | How GitLab identifies itself to the identity provider. Also known as a "Relying party trust identifier". |
|
||||
| Certificate fingerprint | Used to confirm that communications over SAML are secure by checking that the server is signing communications with the correct certificate. Also known as a certificate thumbprint. |
|
||||
|
||||
## General Setup
|
||||
If required, you can find a [glossary of common terms](#glossary-of-common-terms).
|
||||
|
||||
GitLab can be configured to act as a SAML 2.0 Service Provider (SP). This allows
|
||||
GitLab to consume assertions from a SAML 2.0 Identity Provider (IdP), such as
|
||||
GitLab to consume assertions from a SAML 2.0 identity provider (IdP), such as
|
||||
Okta to authenticate users.
|
||||
|
||||
First configure SAML 2.0 support in GitLab, then register the GitLab application
|
||||
in your SAML IdP:
|
||||
## Configure SAML support in GitLab
|
||||
|
||||
1. Make sure GitLab is configured with HTTPS.
|
||||
See [Using HTTPS](../install/installation.md#using-https) for instructions.
|
||||
|
|
@ -73,7 +60,7 @@ in your SAML IdP:
|
|||
block_auto_created_users: false
|
||||
```
|
||||
|
||||
1. You can also automatically link SAML users with existing GitLab users if their
|
||||
1. Optional. You can automatically link SAML users with existing GitLab users if their
|
||||
email addresses match by adding the following setting:
|
||||
|
||||
For Omnibus package:
|
||||
|
|
@ -88,8 +75,16 @@ in your SAML IdP:
|
|||
auto_link_saml_user: true
|
||||
```
|
||||
|
||||
1. Ensure that the SAML [`NameID`](../user/group/saml_sso/index.md#nameid) and email address are fixed for each user,
|
||||
as described in the section on [Security](#security). Otherwise, your users are able to sign in as other authorized users.
|
||||
Alternatively, a user can manually link their SAML identity to an existing GitLab
|
||||
account by following the steps in
|
||||
[Enable OmniAuth for an existing user](omniauth.md#enable-omniauth-for-an-existing-user).
|
||||
|
||||
1. Ensure that the SAML [`NameID`](../user/group/saml_sso/index.md#nameid) and email
|
||||
address are fixed for each user. These attributes define the SAML user. If users
|
||||
can change these attributes, they can impersonate others.
|
||||
|
||||
Refer to the documentation for your SAML identity provider for information on
|
||||
how to fix these attributes.
|
||||
|
||||
1. Add the provider configuration:
|
||||
|
||||
|
|
@ -138,7 +133,7 @@ as described in the section on [Security](#security). Otherwise, your users are
|
|||
be a SHA1 fingerprint; check
|
||||
[the OmniAuth SAML documentation](https://github.com/omniauth/omniauth-saml)
|
||||
for more details on these options.
|
||||
See the [notes on configuring your identity provider](#notes-on-configuring-your-identity-provider) for more information.
|
||||
See the [notes on configuring a SAML 2.0 app on your IdP](#configure-saml-on-your-idp) for more information.
|
||||
|
||||
1. Change the value of `issuer` to a unique name, which identifies the application
|
||||
to the IdP.
|
||||
|
|
@ -147,6 +142,8 @@ as described in the section on [Security](#security). Otherwise, your users are
|
|||
- If you installed via Omnibus, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure).
|
||||
- If you installed from source, [restart GitLab](../administration/restart_gitlab.md#installations-from-source).
|
||||
|
||||
### Register GitLab in your SAML IdP
|
||||
|
||||
1. Register the GitLab SP in your SAML 2.0 IdP, using the application name specified
|
||||
in `issuer`.
|
||||
|
||||
|
|
@ -159,17 +156,31 @@ https://gitlab.example.com/users/auth/saml/metadata
|
|||
```
|
||||
|
||||
At a minimum the IdP *must* provide a claim containing the user's email address using `email` or `mail`.
|
||||
See [the assertions list](#assertions) for other available claims.
|
||||
See [configuring assertions](#configure-assertions) for other available claims.
|
||||
|
||||
On the sign in page there should now be a SAML button below the regular sign in form.
|
||||
Select the icon to begin the authentication process. If everything goes well the user
|
||||
is returned to GitLab and signed in.
|
||||
|
||||
### Use multiple SAML identity providers
|
||||
### Configure SAML on your IdP
|
||||
|
||||
When configuring a SAML app on the IdP, you need at least:
|
||||
|
||||
- Assertion consumer service URL
|
||||
- Issuer
|
||||
- [`NameID`](../user/group/saml_sso/index.md#nameid)
|
||||
- [Email address claim](#configure-assertions)
|
||||
|
||||
For example configurations, see the [notes on specific providers](#set-up-identity-providers).
|
||||
|
||||
Your identity provider may require additional configuration.
|
||||
See [additional information on configuring a SAML app](#additional-configuration-for-saml-apps-on-your-idp) on your IdP for more information.
|
||||
|
||||
### Configure GitLab to use multiple SAML IdPs
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/14361) in GitLab 14.6.
|
||||
|
||||
You can configure GitLab to use multiple SAML identity providers if:
|
||||
You can configure GitLab to use multiple SAML 2.0 identity providers if:
|
||||
|
||||
- Each provider has a unique name set that matches a name set in `args`. At least one provider **must** have the name `saml` to mitigate a
|
||||
[known issue](https://gitlab.com/gitlab-org/gitlab/-/issues/366450) in GitLab 14.6 and newer.
|
||||
|
|
@ -234,54 +245,99 @@ omniauth:
|
|||
}
|
||||
```
|
||||
|
||||
### Notes on configuring your identity provider
|
||||
## Set up identity providers
|
||||
|
||||
When configuring a SAML app on the IdP, you need at least:
|
||||
GitLab support of SAML means that you can sign in to GitLab with a wide range of identity providers.
|
||||
Your identity provider may have additional documentation. Some identity providers include
|
||||
documentation on how to use SAML to sign in to GitLab.
|
||||
|
||||
- Assertion consumer service URL
|
||||
- Issuer
|
||||
- [`NameID`](../user/group/saml_sso/index.md#nameid)
|
||||
- [Email address claim](#assertions)
|
||||
Examples:
|
||||
|
||||
Your identity provider may require additional configuration, such as the following:
|
||||
- [ADFS (Active Directory Federation Services)](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust)
|
||||
- [Auth0](https://auth0.com/docs/authenticate/protocols/saml/saml-sso-integrations/configure-auth0-saml-identity-provider)
|
||||
|
||||
| Field | Value | Notes |
|
||||
|-------|-------|-------|
|
||||
| SAML profile | Web browser SSO profile | GitLab uses SAML to sign users in through their browser. No requests are made directly to the identity provider. |
|
||||
| SAML request binding | HTTP Redirect | GitLab (the service provider) redirects users to your identity provider with a base64 encoded `SAMLRequest` HTTP parameter. |
|
||||
| SAML response binding | HTTP POST | Specifies how the SAML token is sent by your identity provider. Includes the `SAMLResponse`, which a user's browser submits back to GitLab. |
|
||||
| Sign SAML response | Required | Prevents tampering. |
|
||||
| X.509 certificate in response | Required | Signs the response and checks against the provided fingerprint. |
|
||||
| Fingerprint algorithm | SHA-1 | GitLab uses a SHA-1 hash of the certificate to sign the SAML Response. |
|
||||
| Signature algorithm | SHA-1/SHA-256/SHA-384/SHA-512 | Determines how a response is signed. Also known as the digest method, this can be specified in the SAML response. |
|
||||
| Encrypt SAML assertion | Optional | Uses TLS between your identity provider, the user's browser, and GitLab. |
|
||||
| Sign SAML assertion | Optional | Validates the integrity of a SAML assertion. When active, signs the whole response. |
|
||||
| Check SAML request signature | Optional | Checks the signature on the SAML response. |
|
||||
| Default RelayState | Optional | Specifies the URL users should end up on after successfully signing in through SAML at your identity provider. |
|
||||
| NameID format | Persistent | See [NameID format details](../user/group/saml_sso/index.md#nameid-format). |
|
||||
| Additional URLs | Optional | May include the issuer (or identifier) or the assertion consumer service URL in other fields on some providers. |
|
||||
GitLab provides the following setup notes for guidance only.
|
||||
If you have any questions on configuring the SAML app, please contact your provider's support.
|
||||
|
||||
For example configurations, see the [notes on specific providers](#providers).
|
||||
### Set up Okta
|
||||
|
||||
### Assertions
|
||||
1. In the Okta administrator section choose **Applications**.
|
||||
1. When the app screen comes up you see another button to **Create App Integration** and
|
||||
choose SAML 2.0 on the next screen.
|
||||
1. Optionally, you can add a logo
|
||||
(you can choose it from <https://about.gitlab.com/press/>). You must
|
||||
crop and resize it.
|
||||
1. Next, fill in the SAML general configuration with
|
||||
the assertion consumer service URL as "Single sign-on URL" and
|
||||
the issuer as "Audience URI" along with the [NameID](../user/group/saml_sso/index.md#nameid)
|
||||
and [assertions](#configure-assertions).
|
||||
1. The last part of the configuration is the feedback section where you can
|
||||
just say you're a customer and creating an app for internal use.
|
||||
1. When you have your app you can see a few tabs on the top of the app's
|
||||
profile. Select the SAML 2.0 configuration instructions button.
|
||||
1. On the screen that comes up take note of the
|
||||
**Identity Provider Single Sign-On URL** which you can use for the
|
||||
`idp_sso_target_url` on your GitLab configuration file.
|
||||
1. **Before you leave Okta, make sure you add your user and groups if any.**
|
||||
|
||||
| Field | Supported keys |
|
||||
|-----------------|----------------|
|
||||
| Email (required)| `email`, `mail` |
|
||||
| Full Name | `name` |
|
||||
### Set up Google Workspace
|
||||
|
||||
The following guidance is based on this Google Workspace article, on how to [Set up your own custom SAML application](https://support.google.com/a/answer/6087519?hl=en):
|
||||
|
||||
Make sure you have access to a Google Workspace [Super Admin](https://support.google.com/a/answer/2405986#super_admin) account.
|
||||
Use the information below and follow the instructions in the linked Google Workspace article.
|
||||
|
||||
| | Typical value | Description |
|
||||
|------------------|--------------------------------------------------|----------------------------------------------------------|
|
||||
| Name of SAML App | GitLab | Other names OK. |
|
||||
| ACS URL | `https://<GITLAB_DOMAIN>/users/auth/saml/callback` | ACS is short for Assertion Consumer Service. |
|
||||
| GITLAB_DOMAIN | `gitlab.example.com` | Set to the domain of your GitLab instance. |
|
||||
| Entity ID | `https://gitlab.example.com` | A value unique to your SAML app, set it to the `issuer` in your GitLab configuration. |
|
||||
| Name ID format | EMAIL | Required value. Also known as `name_identifier_format` |
|
||||
| Name ID | Primary email address | Make sure someone receives content sent to that address |
|
||||
| First name | `first_name` | Required value to communicate with GitLab. |
|
||||
| Last name | `last_name` | Required value to communicate with GitLab. |
|
||||
|
||||
You also must setup the following SAML attribute mappings:
|
||||
|
||||
| Google Directory attributes | App attributes |
|
||||
|-----------------------------------|----------------|
|
||||
| Basic information > Email | `email` |
|
||||
| Basic Information > First name | `first_name` |
|
||||
| Basic Information > Last name | `last_name` |
|
||||
|
||||
You may also use some of this information when you [configure GitLab](#configure-saml-support-in-gitlab).
|
||||
|
||||
When configuring the Google Workspace SAML app, be sure to record the following information:
|
||||
|
||||
| | Value | Description |
|
||||
|-------------|--------------|-----------------------------------------------------------------------------------|
|
||||
| SSO URL | Depends | Google Identity Provider details. Set to the GitLab `idp_sso_target_url` setting. |
|
||||
| Certificate | Downloadable | Run `openssl x509 -in <your_certificate.crt> -noout -fingerprint` to generate the SHA1 fingerprint that can be used in the `idp_cert_fingerprint` setting. |
|
||||
|
||||
While the Google Workspace Administrator provides IdP metadata, Entity ID, and SHA-256
|
||||
fingerprint, they are not required. GitLab does not need that information to
|
||||
connect to the Google Workspace SAML app.
|
||||
|
||||
### Configure assertions
|
||||
|
||||
| Field | Supported default keys |
|
||||
|-----------------|------------------------|
|
||||
| Email (required)| `email`, `mail` |
|
||||
| Full Name | `name` |
|
||||
| First Name | `first_name`, `firstname`, `firstName` |
|
||||
| Last Name | `last_name`, `lastname`, `lastName` |
|
||||
| Last Name | `last_name`, `lastname`, `lastName` |
|
||||
|
||||
See [`attribute_statements`](#attribute_statements) for examples on how custom
|
||||
See [`attribute_statements`](#map-saml-response-attribute-names) for examples on how custom
|
||||
assertions are configured. This section also describes how to configure custom
|
||||
username attributes.
|
||||
|
||||
Please refer to [the OmniAuth SAML gem](https://github.com/omniauth/omniauth-saml/blob/master/lib/omniauth/strategies/saml.rb)
|
||||
for a full list of supported assertions.
|
||||
|
||||
## SAML Groups
|
||||
## Configure users based on SAML group membership
|
||||
|
||||
You can require users to be members of a certain group, or assign users [external](../user/admin_area/external_users.md), administrator or [auditor](../user/permissions.md#auditor-users) roles based on group membership.
|
||||
You can require users to be members of a certain group, or assign users [external](../user/admin_area/external_users.md), administrator or [auditor](../administration/auditor_users.md) access levels based on group membership.
|
||||
These groups are checked on each SAML login and user attributes updated as necessary.
|
||||
This feature **does not** allow you to
|
||||
automatically add users to GitLab [Groups](../user/group/index.md).
|
||||
|
|
@ -296,7 +352,7 @@ and whether you've installed [GitLab Enterprise Edition (EE)](https://about.gitl
|
|||
| [Admin](#administrator-groups) | **(FREE SELF)** | Yes |
|
||||
| [Auditor](#auditor-groups) | **(PREMIUM SELF)** | Yes |
|
||||
|
||||
### Requirements
|
||||
### Prerequisites
|
||||
|
||||
First tell GitLab where to look for group information. For this, you
|
||||
must make sure that your IdP server sends a specific `AttributeStatement` along
|
||||
|
|
@ -394,7 +450,7 @@ The requirements are the same as the previous settings:
|
|||
|
||||
- The IdP must pass Group information to GitLab.
|
||||
- GitLab should know where to look for the groups in the SAML response, as well as which
|
||||
groups include users with the [Auditor role](../user/permissions.md#auditor-users).
|
||||
groups include users with the [Auditor access level](../administration/auditor_users.md).
|
||||
|
||||
```yaml
|
||||
{ name: 'saml',
|
||||
|
|
@ -410,11 +466,11 @@ The requirements are the same as the previous settings:
|
|||
} }
|
||||
```
|
||||
|
||||
## Group Sync
|
||||
## Automatically manage SAML Group Sync
|
||||
|
||||
For information on automatically managing GitLab group membership, see [SAML Group Sync](../user/group/saml_sso/group_sync.md).
|
||||
|
||||
## Bypass two factor authentication
|
||||
## Bypass two-factor authentication
|
||||
|
||||
If you want some SAML authentication methods to count as 2FA on a per session
|
||||
basis, you can register them in the `upstream_two_factor_authn_contexts` list.
|
||||
|
|
@ -488,9 +544,57 @@ In addition to the changes in GitLab, make sure that your IdP is returning the
|
|||
|
||||
1. Save the file and [restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes to take effect
|
||||
|
||||
## Customization
|
||||
## Validate response signatures
|
||||
|
||||
### `auto_sign_in_with_provider`
|
||||
We require Identity Providers to sign SAML responses to ensure that the assertions are
|
||||
not tampered with.
|
||||
|
||||
This prevents user impersonation and prevents privilege escalation when specific group
|
||||
membership is required. Typically this:
|
||||
|
||||
- Is configured using `idp_cert_fingerprint`.
|
||||
- Includes the full certificate in the response, although if your Identity Provider
|
||||
doesn't support this, you can directly configure GitLab using the `idp_cert` option.
|
||||
|
||||
Example configuration with `idp_cert_fingerprint`:
|
||||
|
||||
```yaml
|
||||
args: {
|
||||
assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
|
||||
idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
|
||||
idp_sso_target_url: 'https://login.example.com/idp',
|
||||
issuer: 'https://gitlab.example.com',
|
||||
name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
|
||||
}
|
||||
```
|
||||
|
||||
Example configuration with `idp_cert`:
|
||||
|
||||
```yaml
|
||||
args: {
|
||||
assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
|
||||
idp_cert: '-----BEGIN CERTIFICATE-----
|
||||
<redacted>
|
||||
-----END CERTIFICATE-----',
|
||||
idp_sso_target_url: 'https://login.example.com/idp',
|
||||
issuer: 'https://gitlab.example.com',
|
||||
name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
|
||||
}
|
||||
```
|
||||
|
||||
If the response signature validation is configured incorrectly, you can see error messages
|
||||
such as:
|
||||
|
||||
- A key validation error.
|
||||
- Digest mismatch.
|
||||
- Fingerprint mismatch.
|
||||
|
||||
Refer to the [troubleshooting section](#troubleshooting) for more information on
|
||||
solving these errors.
|
||||
|
||||
## Customize SAML settings
|
||||
|
||||
### Redirect users to SAML server for authentication
|
||||
|
||||
You can add this setting to your GitLab configuration to automatically redirect you
|
||||
to your SAML server for authentication. This removes the requirement to select a button
|
||||
|
|
@ -516,7 +620,7 @@ SAML users has administrator access.
|
|||
You may also bypass the auto sign-in feature by browsing to
|
||||
`https://gitlab.example.com/users/sign_in?auto_sign_in=false`.
|
||||
|
||||
### `attribute_statements` **(FREE SELF)**
|
||||
### Map SAML response attribute names **(FREE SELF)**
|
||||
|
||||
NOTE:
|
||||
This setting should be used only to map attributes that are part of the OmniAuth
|
||||
|
|
@ -566,7 +670,7 @@ args: {
|
|||
|
||||
This also sets the `username` attribute in your SAML Response to the username in GitLab.
|
||||
|
||||
### `allowed_clock_drift`
|
||||
### Allow for clock drift
|
||||
|
||||
The clock of the Identity Provider may drift slightly ahead of your system clocks.
|
||||
To allow for a small amount of clock drift, you can use `allowed_clock_drift` in
|
||||
|
|
@ -585,7 +689,7 @@ args: {
|
|||
}
|
||||
```
|
||||
|
||||
### `uid_attribute`
|
||||
### Designate a unique attribute for the `uid`
|
||||
|
||||
By default, the `uid` is set as the `name_id` in the SAML response. If you'd like to designate a unique attribute for the `uid`, you can set the `uid_attribute`. In the example below, the value of `uid` attribute in the SAML response is set as the `uid_attribute`.
|
||||
|
||||
|
|
@ -600,59 +704,13 @@ args: {
|
|||
}
|
||||
```
|
||||
|
||||
Make sure you read the [Security](#security) section before changing this value.
|
||||
Ensure that attributes define the SAML user, such as
|
||||
[`NameID`](../user/group/saml_sso/index.md#nameid) and email address, are fixed
|
||||
for each user before changing this value.
|
||||
|
||||
## Response signature validation (required)
|
||||
## Assertion encryption (optional)
|
||||
|
||||
We require Identity Providers to sign SAML responses to ensure that the assertions are
|
||||
not tampered with.
|
||||
|
||||
This prevents user impersonation and prevents privilege escalation when specific group
|
||||
membership is required. Typically this:
|
||||
|
||||
- Is configured using `idp_cert_fingerprint`.
|
||||
- Includes the full certificate in the response, although if your Identity Provider
|
||||
doesn't support this, you can directly configure GitLab using the `idp_cert` option.
|
||||
|
||||
Example configuration with `idp_cert_fingerprint`:
|
||||
|
||||
```yaml
|
||||
args: {
|
||||
assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
|
||||
idp_cert_fingerprint: '43:51:43:a1:b5:fc:8b:b7:0a:3a:a9:b1:0f:66:73:a8',
|
||||
idp_sso_target_url: 'https://login.example.com/idp',
|
||||
issuer: 'https://gitlab.example.com',
|
||||
name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
|
||||
}
|
||||
```
|
||||
|
||||
Example configuration with `idp_cert`:
|
||||
|
||||
```yaml
|
||||
args: {
|
||||
assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback',
|
||||
idp_cert: '-----BEGIN CERTIFICATE-----
|
||||
<redacted>
|
||||
-----END CERTIFICATE-----',
|
||||
idp_sso_target_url: 'https://login.example.com/idp',
|
||||
issuer: 'https://gitlab.example.com',
|
||||
name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent',
|
||||
}
|
||||
```
|
||||
|
||||
If the response signature validation is configured incorrectly, you can see error messages
|
||||
such as:
|
||||
|
||||
- A key validation error.
|
||||
- Digest mismatch.
|
||||
- Fingerprint mismatch.
|
||||
|
||||
Refer to the [troubleshooting section](#troubleshooting) for more information on
|
||||
debugging these errors.
|
||||
|
||||
## Assertion Encryption (optional)
|
||||
|
||||
GitLab requires the use of TLS encryption with SAML, but in some cases there can be a
|
||||
GitLab requires the use of TLS encryption with SAML 2.0, but in some cases there can be a
|
||||
need for additional encryption of the assertions.
|
||||
|
||||
This may be the case, for example, if you terminate TLS encryption early at a load
|
||||
|
|
@ -679,7 +737,7 @@ Your Identity Provider encrypts the assertion with the public certificate of Git
|
|||
NOTE:
|
||||
This integration uses the `certificate` and `private_key` settings for both assertion encryption and request signing.
|
||||
|
||||
## Request signing (optional)
|
||||
## Sign SAML authentication requests (optional)
|
||||
|
||||
Another optional configuration is to sign SAML authentication requests. GitLab
|
||||
SAML Requests use the SAML redirect binding, so this isn't necessary (unlike the
|
||||
|
|
@ -713,18 +771,7 @@ args: {
|
|||
|
||||
GitLab signs the request with the provided private key. GitLab includes the configured public x500 certificate in the metadata for your Identity Provider to validate the signature of the received request with. For more information on this option, see the [Ruby SAML gem documentation](https://github.com/onelogin/ruby-saml/tree/v1.7.0). The Ruby SAML gem is used by the [OmniAuth SAML gem](https://github.com/omniauth/omniauth-saml) to implement the client side of the SAML authentication.
|
||||
|
||||
## Security
|
||||
|
||||
Avoid user control of the following attributes:
|
||||
|
||||
- [`NameID`](../user/group/saml_sso/index.md#nameid)
|
||||
- `Email` when used with `omniauth_auto_link_saml_user`
|
||||
|
||||
These attributes define the SAML user. If users can change these attributes, they can impersonate others.
|
||||
|
||||
Refer to the documentation for your SAML Identity Provider for information on how to fix these attributes.
|
||||
|
||||
## Passwords for users created via SAML
|
||||
## Password generation for users created through SAML
|
||||
|
||||
The [Generated passwords for users created through integrated authentication](../security/passwords_for_integrated_authentication_methods.md) guide provides an overview of how GitLab generates and sets passwords for users created via SAML.
|
||||
|
||||
|
|
@ -738,7 +785,7 @@ Users authenticated with SSO or SAML must not use a password for Git operations
|
|||
A user can manually link their SAML identity to an existing GitLab account by following the steps in
|
||||
[Enable OmniAuth for an existing user](omniauth.md#enable-omniauth-for-an-existing-user).
|
||||
|
||||
## Configuring Group SAML on a self-managed GitLab instance **(PREMIUM SELF)**
|
||||
## Group SAML on a self-managed GitLab instance **(PREMIUM SELF)**
|
||||
|
||||
For information on the GitLab.com implementation, please see the [SAML SSO for GitLab.com groups page](../user/group/saml_sso).
|
||||
|
||||
|
|
@ -746,10 +793,10 @@ Group SAML SSO helps if you have to allow access via multiple SAML identity prov
|
|||
|
||||
To proceed with configuring Group SAML SSO instead, enable the `group_saml` OmniAuth provider. This can be done from:
|
||||
|
||||
- `gitlab.rb` for [Omnibus GitLab installations](#omnibus-installations).
|
||||
- `gitlab/config/gitlab.yml` for [source installations](#source-installations).
|
||||
- `gitlab.rb` for Omnibus GitLab installations.
|
||||
- `gitlab/config/gitlab.yml` for source installations.
|
||||
|
||||
### Limitations
|
||||
### Self-managed instance group SAML limitations
|
||||
|
||||
Group SAML on a self-managed instance is limited when compared to the recommended
|
||||
[instance-wide SAML](../user/group/saml_sso/index.md). The recommended solution allows you to take advantage of:
|
||||
|
|
@ -760,7 +807,7 @@ Group SAML on a self-managed instance is limited when compared to the recommende
|
|||
- [Administrator groups](#administrator-groups).
|
||||
- [Auditor groups](#auditor-groups).
|
||||
|
||||
### Omnibus installations
|
||||
For Omnibus installations:
|
||||
|
||||
1. Make sure GitLab is
|
||||
[configured with HTTPS](../install/installation.md#using-https).
|
||||
|
|
@ -771,7 +818,7 @@ Group SAML on a self-managed instance is limited when compared to the recommende
|
|||
gitlab_rails['omniauth_providers'] = [{ name: 'group_saml' }]
|
||||
```
|
||||
|
||||
### Source installations
|
||||
For installations from source:
|
||||
|
||||
1. Make sure GitLab is
|
||||
[configured with HTTPS](../install/installation.md#using-https).
|
||||
|
|
@ -784,78 +831,39 @@ Group SAML on a self-managed instance is limited when compared to the recommende
|
|||
- { name: 'group_saml' }
|
||||
```
|
||||
|
||||
## Providers
|
||||
## Additional configuration for SAML apps on your IdP
|
||||
|
||||
GitLab support of SAML means that you can sign in to GitLab with a wide range of identity providers.
|
||||
Your identity provider may have additional documentation. Some identity providers include
|
||||
documentation on how to use SAML to sign in to GitLab.
|
||||
When configuring a SAML app on the IdP, your identity provider may require additional configuration, such as the following:
|
||||
|
||||
Examples:
|
||||
| Field | Value | Notes |
|
||||
|-------|-------|-------|
|
||||
| SAML profile | Web browser SSO profile | GitLab uses SAML to sign users in through their browser. No requests are made directly to the identity provider. |
|
||||
| SAML request binding | HTTP Redirect | GitLab (the service provider) redirects users to your identity provider with a base64 encoded `SAMLRequest` HTTP parameter. |
|
||||
| SAML response binding | HTTP POST | Specifies how the SAML token is sent by your identity provider. Includes the `SAMLResponse`, which a user's browser submits back to GitLab. |
|
||||
| Sign SAML response | Required | Prevents tampering. |
|
||||
| X.509 certificate in response | Required | Signs the response and checks against the provided fingerprint. |
|
||||
| Fingerprint algorithm | SHA-1 | GitLab uses a SHA-1 hash of the certificate to sign the SAML Response. |
|
||||
| Signature algorithm | SHA-1/SHA-256/SHA-384/SHA-512 | Determines how a response is signed. Also known as the digest method, this can be specified in the SAML response. |
|
||||
| Encrypt SAML assertion | Optional | Uses TLS between your identity provider, the user's browser, and GitLab. |
|
||||
| Sign SAML assertion | Optional | Validates the integrity of a SAML assertion. When active, signs the whole response. |
|
||||
| Check SAML request signature | Optional | Checks the signature on the SAML response. |
|
||||
| Default RelayState | Optional | Specifies the URL users should end up on after successfully signing in through SAML at your identity provider. |
|
||||
| NameID format | Persistent | See [NameID format details](../user/group/saml_sso/index.md#nameid-format). |
|
||||
| Additional URLs | Optional | May include the issuer (or identifier) or the assertion consumer service URL in other fields on some providers. |
|
||||
|
||||
- [ADFS (Active Directory Federation Services)](https://learn.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust)
|
||||
- [Auth0](https://auth0.com/docs/authenticate/protocols/saml/saml-sso-integrations/configure-auth0-saml-identity-provider)
|
||||
For example configurations, see the [notes on specific providers](#set-up-identity-providers).
|
||||
|
||||
GitLab provides the following setup notes for guidance only.
|
||||
If you have any questions on configuring the SAML app, please contact your provider's support.
|
||||
## Glossary of common terms
|
||||
|
||||
### Okta setup notes
|
||||
|
||||
1. In the Okta administrator section choose **Applications**.
|
||||
1. When the app screen comes up you see another button to **Create App Integration** and
|
||||
choose SAML 2.0 on the next screen.
|
||||
1. Optionally, you can add a logo
|
||||
(you can choose it from <https://about.gitlab.com/press/>). You must
|
||||
crop and resize it.
|
||||
1. Next, fill in the SAML general configuration with
|
||||
the assertion consumer service URL as "Single sign-on URL" and
|
||||
the issuer as "Audience URI" along with the [NameID](../user/group/saml_sso/index.md#nameid) and [assertions](#assertions).
|
||||
1. The last part of the configuration is the feedback section where you can
|
||||
just say you're a customer and creating an app for internal use.
|
||||
1. When you have your app you can see a few tabs on the top of the app's
|
||||
profile. Select the SAML 2.0 configuration instructions button.
|
||||
1. On the screen that comes up take note of the
|
||||
**Identity Provider Single Sign-On URL** which you can use for the
|
||||
`idp_sso_target_url` on your GitLab configuration file.
|
||||
1. **Before you leave Okta, make sure you add your user and groups if any.**
|
||||
|
||||
### Google workspace setup notes
|
||||
|
||||
The following guidance is based on this Google Workspace article, on how to [Set up your own custom SAML application](https://support.google.com/a/answer/6087519?hl=en):
|
||||
|
||||
Make sure you have access to a Google Workspace [Super Admin](https://support.google.com/a/answer/2405986#super_admin) account.
|
||||
Use the information below and follow the instructions in the linked Google Workspace article.
|
||||
|
||||
| | Typical value | Description |
|
||||
|------------------|--------------------------------------------------|----------------------------------------------------------|
|
||||
| Name of SAML App | GitLab | Other names OK. |
|
||||
| ACS URL | `https://<GITLAB_DOMAIN>/users/auth/saml/callback` | ACS is short for Assertion Consumer Service. |
|
||||
| GITLAB_DOMAIN | `gitlab.example.com` | Set to the domain of your GitLab instance. |
|
||||
| Entity ID | `https://gitlab.example.com` | A value unique to your SAML app, set it to the `issuer` in your GitLab configuration. |
|
||||
| Name ID format | EMAIL | Required value. Also known as `name_identifier_format` |
|
||||
| Name ID | Primary email address | Make sure someone receives content sent to that address |
|
||||
| First name | `first_name` | Required value to communicate with GitLab. |
|
||||
| Last name | `last_name` | Required value to communicate with GitLab. |
|
||||
|
||||
You also must setup the following SAML attribute mappings:
|
||||
|
||||
| Google Directory attributes | App attributes |
|
||||
|-----------------------------------|----------------|
|
||||
| Basic information > Email | `email` |
|
||||
| Basic Information > First name | `first_name` |
|
||||
| Basic Information > Last name | `last_name` |
|
||||
|
||||
You may also use some of this information when you [configure GitLab](#general-setup).
|
||||
|
||||
When configuring the Google Workspace SAML app, be sure to record the following information:
|
||||
|
||||
| | Value | Description |
|
||||
|-------------|--------------|-----------------------------------------------------------------------------------|
|
||||
| SSO URL | Depends | Google Identity Provider details. Set to the GitLab `idp_sso_target_url` setting. |
|
||||
| Certificate | Downloadable | Run `openssl x509 -in <your_certificate.crt> -noout -fingerprint` to generate the SHA1 fingerprint that can be used in the `idp_cert_fingerprint` setting. |
|
||||
|
||||
While the Google Workspace Administrator provides IdP metadata, Entity ID, and SHA-256
|
||||
fingerprint, they are not required. GitLab does not need that information to
|
||||
connect to the Google Workspace SAML app.
|
||||
| Term | Description |
|
||||
|--------------------------------|-------------|
|
||||
| Identity provider (IdP) | The service which manages your user identities, such as Okta or OneLogin. |
|
||||
| Service provider (SP) | GitLab can be configured as a SAML 2.0 SP. |
|
||||
| Assertion | A piece of information about a user's identity, such as their name or role. Also known as claims or attributes. |
|
||||
| Single Sign-On (SSO) | Name of authentication scheme. |
|
||||
| Assertion consumer service URL | The callback on GitLab where users are redirected after successfully authenticating with the identity provider. |
|
||||
| Issuer | How GitLab identifies itself to the identity provider. Also known as a "Relying party trust identifier". |
|
||||
| Certificate fingerprint | Used to confirm that communications over SAML are secure by checking that the server is signing communications with the correct certificate. Also known as a certificate thumbprint. |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
|
|
|||
|
|
@ -14,14 +14,14 @@ GitLab Dedicated is a fully isolated, single-tenant SaaS service that is:
|
|||
- Hosted and managed by GitLab, Inc.
|
||||
- Deployed on AWS in a cloud region of your choice (see the [regions that are not supported](#aws-regions-not-supported)).
|
||||
|
||||
GitLab Dedicated removes the overhead of platform management to increase your operational efficiency, reduce risk, and enhance the speed and agility of your organization. Each GitLab Dedicated instance is highly available with disaster recovery and deployed into the cloud region of your choice. GitLab teams fully manage the maintenance and operations of each isolated instance, so customers can access our latest product improvements while meeting the most complex compliance standards.
|
||||
GitLab Dedicated removes the overhead of platform management to increase your operational efficiency, reduce risk, and enhance the speed and agility of your organization. Each GitLab Dedicated instance is highly available with disaster recovery and deployed into the cloud region of your choice. GitLab teams fully manage the maintenance and operations of each isolated instance, so customers can access our latest product improvements while meeting the most complex compliance standards.
|
||||
|
||||
It's the offering of choice for enterprises and organizations in highly regulated industries that have complex regulatory, compliance, and data residency requirements.
|
||||
|
||||
## Available features
|
||||
|
||||
- Authentication: Support for instance-level [SAML OmniAuth](../../integration/saml.md) functionality. GitLab Dedicated acts as the service provider, and you must provide the necessary [configuration](../../integration/saml.md#general-setup) in order for GitLab to communicate with your IdP. This is provided during onboarding.
|
||||
- SAML [request signing](../../integration/saml.md#request-signing-optional), [group sync](../../user/group/saml_sso/group_sync.md#configure-saml-group-sync), and [SAML groups](../../integration/saml.md#saml-groups) are supported.
|
||||
- Authentication: Support for instance-level [SAML OmniAuth](../../integration/saml.md) functionality. GitLab Dedicated acts as the service provider, and you must provide the necessary [configuration](../../integration/saml.md#configure-saml-support-in-gitlab) in order for GitLab to communicate with your IdP. This is provided during onboarding.
|
||||
- SAML [request signing](../../integration/saml.md#sign-saml-authentication-requests-optional), [group sync](../../user/group/saml_sso/group_sync.md#configure-saml-group-sync), and [SAML groups](../../integration/saml.md#configure-users-based-on-saml-group-membership) are supported.
|
||||
- Networking:
|
||||
- Public connectivity with support for IP Allowlists. During onboarding, you can optionally specify a list of IP addresses that can access your GitLab Dedicated instance. Subsequently, when an IP not on the allowlist tries to access your instance the connection is refused.
|
||||
- Optional. Private connectivity via [AWS PrivateLink](https://aws.amazon.com/privatelink/).
|
||||
|
|
|
|||
|
|
@ -46,7 +46,10 @@ limit on the number of [CI/CD minutes](../../../ci/pipelines/cicd_minutes.md) yo
|
|||
|
||||
## Enable a specific runner for multiple projects
|
||||
|
||||
To enable a specific runner for one or more projects:
|
||||
If you have already registered a [specific runner](../../../ci/runners/runners_scope.md#specific-runners)
|
||||
you can assign that runner to other projects.
|
||||
|
||||
To enable a specific runner for more than one project:
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. From the left sidebar, select **Overview > Runners**.
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ Instance-level analytics make it possible to aggregate analytics across
|
|||
GitLab, so that users can view information across multiple projects and groups
|
||||
in one place.
|
||||
|
||||
[Learn more about instance-level analytics](../admin_area/analytics/index.md).
|
||||
For more information, see [instance-level analytics](../admin_area/analytics/index.md).
|
||||
|
||||
## Group-level analytics
|
||||
|
||||
|
|
|
|||
|
|
@ -172,7 +172,7 @@ Prerequisite:
|
|||
1. On the left sidebar, select **Group information > Members**.
|
||||
1. Select **Invite members**.
|
||||
1. Fill in the fields.
|
||||
- The role applies to all projects in the group. [Learn more about permissions](../permissions.md).
|
||||
- The role applies to all projects in the group. For more information, see [permissions](../permissions.md).
|
||||
- On the **Access expiration date**, the user can no longer access projects in the group.
|
||||
1. Select **Invite**.
|
||||
|
||||
|
|
@ -530,10 +530,10 @@ in a subgroup has access to the templates for that subgroup and
|
|||
any immediate parent groups.
|
||||
|
||||
To learn how to create templates for issues and merge requests, see
|
||||
[Description templates](../project/description_templates.md).
|
||||
[description templates](../project/description_templates.md).
|
||||
|
||||
Define project templates at a group level by setting a group as the template source.
|
||||
[Learn more about group-level project templates](custom_project_templates.md).
|
||||
For more information, see [group-level project templates](custom_project_templates.md).
|
||||
|
||||
### Enable group file template **(PREMIUM)**
|
||||
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ must be specified as an attribute named `email` or `mail`.
|
|||
You can configure the following attributes with GitLab.com Group SAML:
|
||||
|
||||
- `username` or `nickname`. We recommend you configure only one of these.
|
||||
- The [attributes available](../../../integration/saml.md#assertions) to self-managed GitLab instances.
|
||||
- The [attributes available](../../../integration/saml.md#configure-assertions) to self-managed GitLab instances.
|
||||
|
||||
### Metadata configuration
|
||||
|
||||
|
|
@ -98,7 +98,7 @@ After you set up your identity provider to work with GitLab, you must configure
|
|||

|
||||
|
||||
NOTE:
|
||||
The certificate [fingerprint algorithm](../../../integration/saml.md#notes-on-configuring-your-identity-provider) must be in SHA1. When configuring the identity provider (such as [Google Workspace](#google-workspace-setup-notes)), use a secure signature algorithm.
|
||||
The certificate [fingerprint algorithm](../../../integration/saml.md#configure-saml-on-your-idp) must be in SHA1. When configuring the identity provider (such as [Google Workspace](#google-workspace-setup-notes)), use a secure signature algorithm.
|
||||
|
||||
### Additional configuration information
|
||||
|
||||
|
|
@ -184,7 +184,7 @@ The SAML standard means that you can use a wide range of identity providers with
|
|||
|
||||
When [configuring your identity provider](#configure-your-identity-provider), consider the notes below for specific providers to help avoid common issues and as a guide for terminology used.
|
||||
|
||||
For providers not listed below, you can refer to the [instance SAML notes on configuring an identity provider](../../../integration/saml.md#notes-on-configuring-your-identity-provider)
|
||||
For providers not listed below, you can refer to the [instance SAML notes on configuring an identity provider](../../../integration/saml.md#configure-saml-on-your-idp)
|
||||
for additional guidance on information your identity provider may require.
|
||||
|
||||
GitLab provides the following information for guidance only.
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ You can use one of the following to troubleshoot SAML:
|
|||
- A [quick start guide to start a Docker container](../../../administration/troubleshooting/test_environments.md#saml)
|
||||
with a plug and play SAML 2.0 identity provider if you only require a SAML provider.
|
||||
- A local environment by
|
||||
[enabling SAML for groups on a self-managed instance](../../../integration/saml.md#configuring-group-saml-on-a-self-managed-gitlab-instance).
|
||||
[enabling SAML for groups on a self-managed instance](../../../integration/saml.md#group-saml-on-a-self-managed-gitlab-instance).
|
||||
|
||||
## Verify configuration
|
||||
|
||||
|
|
@ -138,7 +138,7 @@ Make sure this information is provided.
|
|||
Another issue that can result in this error is when the correct information is being sent by
|
||||
the identity provider, but the attributes don't match the names in the OmniAuth `info` hash. In this case,
|
||||
you must set `attribute_statements` in the SAML configuration to
|
||||
[map the attribute names in your SAML Response to the corresponding OmniAuth `info` hash names](../../../integration/saml.md#attribute_statements).
|
||||
[map the attribute names in your SAML Response to the corresponding OmniAuth `info` hash names](../../../integration/saml.md#map-saml-response-attribute-names).
|
||||
|
||||
## User sign in banner error messages
|
||||
|
||||
|
|
@ -221,7 +221,7 @@ If all users are receiving a `404` when attempting to sign in using SAML, confir
|
|||
[there is an active subscription](../../../subscriptions/gitlab_com/index.md#view-your-gitlab-saas-subscription) being used in this SAML SSO namespace.
|
||||
|
||||
If you receive a `404` during setup when using "verify configuration", make sure you have used the correct
|
||||
[SHA-1 generated fingerprint](../../../integration/saml.md#notes-on-configuring-your-identity-provider).
|
||||
[SHA-1 generated fingerprint](../../../integration/saml.md#configure-saml-on-your-idp).
|
||||
|
||||
If a user is trying to sign in for the first time and the GitLab single sign-on URL has not [been configured](index.md#configure-your-identity-provider), they may see a 404.
|
||||
As outlined in the [user access section](index.md#linking-saml-to-your-existing-gitlabcom-account), a group Owner needs to provide the URL to users.
|
||||
|
|
|
|||
|
|
@ -12,13 +12,7 @@ The role determines which actions they can take in GitLab.
|
|||
If you add a user to both a project's group and the
|
||||
project itself, the higher role is used.
|
||||
|
||||
When a member leaves a team's project, all the assigned [issues](project/issues/index.md) and
|
||||
[merge requests](project/merge_requests/index.md) are automatically unassigned.
|
||||
|
||||
GitLab [administrators](../administration/index.md) receive all permissions.
|
||||
|
||||
To add or import a user, you can follow the
|
||||
[project members documentation](project/members/index.md).
|
||||
GitLab [administrators](../administration/index.md) have all permissions.
|
||||
|
||||
## Roles
|
||||
|
||||
|
|
@ -33,11 +27,9 @@ The available roles are:
|
|||
A user assigned the Guest role has the least permissions,
|
||||
and the Owner has the most.
|
||||
|
||||
## Instance-wide user permissions
|
||||
|
||||
By default, users can create top-level groups and change their
|
||||
usernames. A GitLab administrator can configure the GitLab instance to
|
||||
[modify this behavior](../administration/user_settings.md).
|
||||
By default, all users can create top-level groups and change their
|
||||
usernames. A GitLab administrator can [change this behavior](../administration/user_settings.md)
|
||||
for the GitLab instance.
|
||||
|
||||
## Project members permissions
|
||||
|
||||
|
|
@ -337,18 +329,6 @@ This table shows granted privileges for jobs triggered by specific types of user
|
|||
1. Only if the triggering user is not an external one.
|
||||
1. Only if the triggering user is a member of the project. See also [Usage of private Docker images with `if-not-present` pull policy](http://docs.gitlabl.com/runner/security/index.html#usage-of-private-docker-images-with-if-not-present-pull-policy).
|
||||
|
||||
### Protected branches
|
||||
|
||||
Additional restrictions can be applied on a per-branch basis with [protected branches](project/protected_branches.md).
|
||||
Additionally, you can customize permissions to allow or prevent project Developers or Maintainers
|
||||
from pushing to a protected branch. Read through the documentation on
|
||||
[protected branches](project/protected_branches.md) to learn more.
|
||||
|
||||
### Value stream analytics permissions
|
||||
|
||||
Find the current permissions on the value stream analytics dashboard, as described in
|
||||
[related documentation](analytics/value_stream_analytics.md#access-permissions-for-value-stream-analytics).
|
||||
|
||||
### File Locking permissions **(PREMIUM)**
|
||||
|
||||
The user that locks a file or directory is the only one that can edit and push their changes back to the repository where the locked objects are located.
|
||||
|
|
@ -459,16 +439,6 @@ nested groups if you have membership in one of its parents.
|
|||
To learn more, read through the documentation on
|
||||
[subgroups memberships](group/subgroups/index.md#subgroup-membership).
|
||||
|
||||
## Auditor users **(PREMIUM SELF)**
|
||||
|
||||
Auditor users are given read-only access to all projects, groups, and other
|
||||
resources on the GitLab instance.
|
||||
|
||||
An Auditor user should be able to access all projects and groups of a GitLab instance
|
||||
with the permissions described on the documentation on [auditor users permissions](../administration/auditor_users.md#auditor-user-permissions-and-restrictions).
|
||||
|
||||
[Read more about Auditor users.](../administration/auditor_users.md)
|
||||
|
||||
## Users with minimal access **(PREMIUM)**
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/40942) in GitLab 13.4.
|
||||
|
|
@ -506,5 +476,9 @@ for more information.
|
|||
## Related topics
|
||||
|
||||
- [The GitLab principles behind permissions](https://about.gitlab.com/handbook/product/gitlab-the-product/#permissions-in-gitlab)
|
||||
- [Project aliases](../user/project/import/index.md#project-aliases)
|
||||
- [Members](project/members/index.md)
|
||||
- Customize permissions on [protected branches](project/protected_branches.md)
|
||||
- [LDAP users permissions](group/access_and_permissions.md#manage-group-memberships-via-ldap)
|
||||
- [Value stream analytics permissions](analytics/value_stream_analytics.md#access-permissions-for-value-stream-analytics)
|
||||
- [Project aliases](../user/project/import/index.md#project-aliases)
|
||||
- [Auditor users](../administration/auditor_users.md)
|
||||
|
|
|
|||
|
|
@ -89,7 +89,6 @@ which are evaluated when displaying the badge. The following placeholders
|
|||
are available:
|
||||
|
||||
- `%{project_path}`: Path of a project including the parent groups
|
||||
- `%{project_name}`: Name of the project
|
||||
- `%{project_id}`: Database ID associated with a project
|
||||
- `%{default_branch}`: Default branch name configured for a project's repository
|
||||
- `%{commit_sha}`: ID of the most recent commit to the default branch of a
|
||||
|
|
|
|||
|
|
@ -61,20 +61,43 @@ file with a URL host (`lfs.url`) different from the repository URL host, LFS fil
|
|||
|
||||
## Migrate from self-managed GitLab to GitLab.com
|
||||
|
||||
Depending on your requirements, there are several ways to migrate from self-managed GitLab to GitLab.com.
|
||||
|
||||
### Migrate using GitLab Migration (recommended)
|
||||
|
||||
Using [GitLab Migration](../../group/import/index.md), you can migrate top-level groups you are the Owner of, with all their subgroups and projects included.
|
||||
|
||||
GitLab Migration maps users and their contributions correctly on GitLab.com provided:
|
||||
|
||||
- Contributing users exist on GitLab.com at the time of the import.
|
||||
- Those users have a public email on the source GitLab instance that matches their primary email on GitLab.com.
|
||||
|
||||
If you use [SAML SSO for GitLab.com groups](../../group/saml_sso/index.md),
|
||||
contributing users must have [linked their SAML identity to their GitLab.com account](../../group/saml_sso/index.md#linking-saml-to-your-existing-gitlabcom-account).
|
||||
|
||||
When migrating to GitLab.com, you must create users manually unless [SCIM](../../group/saml_sso/scim_setup.md) is used. Creating users with the API is only
|
||||
available to self-managed instances because it requires administrator access.
|
||||
|
||||
### Migrate specific projects only
|
||||
|
||||
If you only need to migrate Git repositories, you can [import each project by URL](repo_by_url.md).
|
||||
However, you can't import issues and merge requests this way. To retain all metadata like issues and
|
||||
However, you can't import issues and merge requests this way. To retain metadata like issues and
|
||||
merge requests, use the [import/export feature](../settings/import_export.md)
|
||||
to export projects from self-managed GitLab and import those projects into GitLab.com. All GitLab
|
||||
user associations (such as comment author) are changed to the user importing the project. For more
|
||||
to export projects from self-managed GitLab and import those projects into GitLab.com.
|
||||
|
||||
GitLab maps user contributions correctly when an admin access token is used to perform the import.
|
||||
|
||||
As a result, the import/export feature does not map user contributions correctly when you are importing projects from a self-managed instance to GitLab.com.
|
||||
|
||||
Instead, all GitLab user associations (such as comment author) are changed to the user importing the project. For more
|
||||
information, see the prerequisites and important notes in these sections:
|
||||
|
||||
- [Export a project and its data](../settings/import_export.md#export-a-project-and-its-data).
|
||||
- [Import the project](../settings/import_export.md#import-a-project-and-its-data).
|
||||
|
||||
NOTE:
|
||||
When migrating to GitLab.com, you must create users manually unless [SCIM](../../../user/group/saml_sso/scim_setup.md)
|
||||
will be used. Creating users with the API is limited to self-managed instances as it requires
|
||||
administrator access.
|
||||
To preserve contribution history, [migrate using GitLab Migration](#migrate-using-gitlab-migration-recommended).
|
||||
|
||||
### Migrate using the API
|
||||
|
||||
To migrate all data from self-managed to GitLab.com, you can leverage the [API](../../../api/index.md).
|
||||
Migrate the assets in this order:
|
||||
|
|
@ -83,7 +106,7 @@ Migrate the assets in this order:
|
|||
1. [Projects](../../../api/projects.md)
|
||||
1. [Project variables](../../../api/project_level_variables.md)
|
||||
|
||||
Keep in mind the limitations of the [import/export feature](../settings/import_export.md#items-that-are-exported).
|
||||
Keep in mind the limitations of the [import/export feature](../settings/import_export.md#items-that-are-exported). As with [Migrating specific projects using the import/export feature](#migrate-specific-projects-only) user associations (such as comment author) are changed to the user importing projects when migrating from self-managed to GitLab.com.
|
||||
|
||||
You must still migrate your [Container Registry](../../packages/container_registry/index.md)
|
||||
over a series of Docker pulls and pushes. Re-run any CI pipelines to retrieve any build artifacts.
|
||||
|
|
|
|||
|
|
@ -74,6 +74,25 @@ Prerequisites:
|
|||
|
||||
- You must have at least the Reporter role for the project.
|
||||
|
||||
#### Using the user interface
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/101563) in GitLab 15.7.
|
||||
|
||||
To add a time entry using the user interface:
|
||||
|
||||
1. In the **Time tracking** section of the sidebar, select **Add time entry** (**{plus}**). A modal opens.
|
||||
1. Enter:
|
||||
|
||||
- The amount of time spent.
|
||||
- Optional. When it was spent.
|
||||
- Optional. A summary.
|
||||
|
||||
1. Select **Save**.
|
||||
|
||||
The **Spent** total in the sidebar is updated and you can view all entries in a [time tracking report](#view-a-time-tracking-report).
|
||||
|
||||
#### Using a quick action
|
||||
|
||||
To enter time spent, use the `/spend` [quick action](quick_actions.md), followed by the time.
|
||||
|
||||
For example, if you need
|
||||
|
|
@ -90,15 +109,10 @@ Draft MR and respond to initial comments
|
|||
/spend 30m
|
||||
```
|
||||
|
||||
### Add time spent on a specific date
|
||||
To log when time was spent, enter a date after the time, using the `YYYY-MM-DD` format.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- You must have at least the Reporter role for the project.
|
||||
|
||||
You can log time in the past by providing a date after the time.
|
||||
For example, to log 1 hour of time spent on 31 January 2021,
|
||||
type `/spend 1h 2021-01-31`.
|
||||
enter `/spend 1h 2021-01-31`.
|
||||
|
||||
If you type a future date, no time is logged.
|
||||
|
||||
|
|
|
|||
|
|
@ -363,8 +363,11 @@ Prerequisite:
|
|||
|
||||
## Leave a project
|
||||
|
||||
If you leave a project, you are no longer a project
|
||||
member and cannot contribute.
|
||||
When you leave a project:
|
||||
|
||||
- You are no longer a project member and cannot contribute.
|
||||
- All the issues and merge requests that were assigned
|
||||
to you are unassigned.
|
||||
|
||||
To leave a project:
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ Our goal is to reach feature parity between SaaS and self-managed installations,
|
|||
- Hardware Controls. For functionality that does not apply to groups, Hardware Controls are only
|
||||
applicable to self-managed installations. There is one Hardware Controls section per installation.
|
||||
|
||||
To learn about the current state of workspace development,
|
||||
For more information about the state of workspace development,
|
||||
see [epic 9265](https://gitlab.com/groups/gitlab-org/-/epics/9265).
|
||||
|
||||
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ module Gitlab
|
|||
if uses_primary?
|
||||
load_balancer.primary_write_location
|
||||
else
|
||||
load_balancer.host.database_replica_location
|
||||
load_balancer.host&.database_replica_location || load_balancer.primary_write_location
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
%i[get_request_count get_cross_slot_request_count query_time read_bytes write_bytes].each do |method|
|
||||
%i[get_request_count get_cross_slot_request_count get_allowed_cross_slot_request_count query_time read_bytes
|
||||
write_bytes].each do |method|
|
||||
define_method method do
|
||||
STORAGES.sum(&method)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -50,6 +50,11 @@ module Gitlab
|
|||
::RequestStore[cross_slots_key] += amount
|
||||
end
|
||||
|
||||
def increment_allowed_cross_slot_request_count(amount = 1)
|
||||
::RequestStore[allowed_cross_slots_key] ||= 0
|
||||
::RequestStore[allowed_cross_slots_key] += amount
|
||||
end
|
||||
|
||||
def get_request_count
|
||||
::RequestStore[request_count_key] || 0
|
||||
end
|
||||
|
|
@ -70,6 +75,10 @@ module Gitlab
|
|||
::RequestStore[cross_slots_key] || 0
|
||||
end
|
||||
|
||||
def get_allowed_cross_slot_request_count
|
||||
::RequestStore[allowed_cross_slots_key] || 0
|
||||
end
|
||||
|
||||
def query_time
|
||||
query_time = ::RequestStore[call_duration_key] || 0
|
||||
query_time.round(::Gitlab::InstrumentationHelper::DURATION_PRECISION)
|
||||
|
|
@ -85,6 +94,8 @@ module Gitlab
|
|||
raise RedisClusterValidator::CrossSlotError, "Redis command #{result[:command_name]} arguments hash to different slots. See https://docs.gitlab.com/ee/development/redis.html#multi-key-commands"
|
||||
end
|
||||
|
||||
increment_allowed_cross_slot_request_count if result[:allowed]
|
||||
|
||||
result[:valid]
|
||||
end
|
||||
|
||||
|
|
@ -144,6 +155,10 @@ module Gitlab
|
|||
strong_memoize(:cross_slots_key) { build_key(:redis_cross_slot_request_count) }
|
||||
end
|
||||
|
||||
def allowed_cross_slots_key
|
||||
strong_memoize(:allowed_cross_slots_key) { build_key(:redis_allowed_cross_slot_request_count) }
|
||||
end
|
||||
|
||||
def build_key(namespace)
|
||||
"#{storage_key}_#{namespace}"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ module Gitlab
|
|||
{
|
||||
"#{key_prefix}_calls": -> { get_request_count },
|
||||
"#{key_prefix}_cross_slot_calls": -> { get_cross_slot_request_count },
|
||||
"#{key_prefix}_allowed_cross_slot_calls": -> { get_allowed_cross_slot_request_count },
|
||||
"#{key_prefix}_duration_s": -> { query_time },
|
||||
"#{key_prefix}_read_bytes": -> { read_bytes },
|
||||
"#{key_prefix}_write_bytes": -> { write_bytes }
|
||||
|
|
|
|||
|
|
@ -18,16 +18,15 @@ module Gitlab
|
|||
'heap_dump'
|
||||
end
|
||||
|
||||
# This will be enabled once https://gitlab.com/gitlab-org/gitlab/-/issues/370077 is done.
|
||||
def active?
|
||||
false
|
||||
Feature.enabled?(:report_heap_dumps, type: :ops)
|
||||
end
|
||||
|
||||
# This is a no-op currently and will be implemented at a later time in
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/370077
|
||||
def run(writer)
|
||||
return false unless self.class.enqueued?
|
||||
|
||||
ObjectSpace.dump_all(output: writer)
|
||||
|
||||
true
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -94,7 +94,7 @@ module Gitlab
|
|||
def strike_exceeded_callback(monitor_name, monitor_payload)
|
||||
event_reporter.strikes_exceeded(monitor_name, log_labels(monitor_payload))
|
||||
|
||||
Gitlab::Memory::Reports::HeapDump.enqueue! if @configuration.write_heap_dumps?
|
||||
Gitlab::Memory::Reports::HeapDump.enqueue!
|
||||
|
||||
handler.call
|
||||
end
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ module Gitlab
|
|||
|
||||
DEFAULT_SLEEP_TIME_SECONDS = 60
|
||||
|
||||
attr_writer :event_reporter, :handler, :sleep_time_seconds, :write_heap_dumps
|
||||
attr_writer :event_reporter, :handler, :sleep_time_seconds
|
||||
|
||||
def monitors
|
||||
@monitor_stack ||= MonitorStack.new
|
||||
|
|
@ -55,10 +55,6 @@ module Gitlab
|
|||
def sleep_time_seconds
|
||||
@sleep_time_seconds ||= DEFAULT_SLEEP_TIME_SECONDS
|
||||
end
|
||||
|
||||
def write_heap_dumps?
|
||||
!!@write_heap_dumps
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ module Gitlab
|
|||
def configure_for_puma
|
||||
->(config) do
|
||||
config.handler = Gitlab::Memory::Watchdog::PumaHandler.new
|
||||
config.write_heap_dumps = write_heap_dumps?
|
||||
config.sleep_time_seconds = ENV.fetch('GITLAB_MEMWD_SLEEP_TIME_SEC', DEFAULT_SLEEP_INTERVAL_S).to_i
|
||||
config.monitors(&configure_monitors_for_puma)
|
||||
end
|
||||
|
|
@ -27,7 +26,6 @@ module Gitlab
|
|||
def configure_for_sidekiq
|
||||
->(config) do
|
||||
config.handler = Gitlab::Memory::Watchdog::TermProcessHandler.new
|
||||
config.write_heap_dumps = write_heap_dumps?
|
||||
config.sleep_time_seconds = sidekiq_sleep_time
|
||||
config.monitors(&configure_monitors_for_sidekiq)
|
||||
config.event_reporter = SidekiqEventReporter.new
|
||||
|
|
@ -36,10 +34,6 @@ module Gitlab
|
|||
|
||||
private
|
||||
|
||||
def write_heap_dumps?
|
||||
Gitlab::Utils.to_boolean(ENV['GITLAB_MEMWD_DUMP_HEAP'], default: false)
|
||||
end
|
||||
|
||||
def configure_monitors_for_puma
|
||||
->(stack) do
|
||||
max_strikes = ENV.fetch('GITLAB_MEMWD_MAX_STRIKES', DEFAULT_MAX_STRIKES).to_i
|
||||
|
|
|
|||
|
|
@ -15805,6 +15805,9 @@ msgstr ""
|
|||
msgid "Error fetching refs"
|
||||
msgstr ""
|
||||
|
||||
msgid "Error fetching target projects. Please try again."
|
||||
msgstr ""
|
||||
|
||||
msgid "Error fetching the dependency list. Please check your network connection and try again."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -391,6 +391,32 @@ RSpec.describe OmniauthCallbacksController, type: :controller do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with snowplow tracking', :snowplow do
|
||||
let(:provider) { 'google_oauth2' }
|
||||
let(:extern_uid) { 'my-uid' }
|
||||
|
||||
context 'when sign_in' do
|
||||
it 'does not track the event' do
|
||||
post provider
|
||||
expect_no_snowplow_event
|
||||
end
|
||||
end
|
||||
|
||||
context 'when sign_up' do
|
||||
let(:user) { double(email: generate(:email)) }
|
||||
|
||||
it 'tracks the event' do
|
||||
post provider
|
||||
|
||||
expect_snowplow_event(
|
||||
category: described_class.name,
|
||||
action: "#{provider}_sso",
|
||||
user: User.find_by(email: user.email)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#saml' do
|
||||
|
|
|
|||
|
|
@ -306,4 +306,18 @@ RSpec.describe Projects::MergeRequests::CreationsController do
|
|||
post :create, params: merge_request_params
|
||||
end
|
||||
end
|
||||
|
||||
describe 'GET target_projects', feature_category: :code_review do
|
||||
it 'returns target projects JSON' do
|
||||
get :target_projects, params: { namespace_id: project.namespace.to_param, project_id: project }
|
||||
|
||||
expect(json_response.size).to be(2)
|
||||
|
||||
forked_project = json_response.first
|
||||
expect(forked_project).to have_key('id')
|
||||
expect(forked_project).to have_key('name')
|
||||
expect(forked_project).to have_key('full_path')
|
||||
expect(forked_project).to have_key('refs_url')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ RSpec.describe RegistrationsController do
|
|||
|
||||
let(:session_params) { {} }
|
||||
|
||||
subject { post(:create, params: user_params, session: session_params) }
|
||||
subject(:post_create) { post(:create, params: user_params, session: session_params) }
|
||||
|
||||
context '`blocked_pending_approval` state' do
|
||||
context 'when the `require_admin_approval_after_user_signup` setting is turned on' do
|
||||
|
|
@ -484,18 +484,19 @@ RSpec.describe RegistrationsController do
|
|||
render_views
|
||||
let_it_be(:new_user_params) { { new_user: base_user_params.merge({ password: "password" }) } }
|
||||
|
||||
subject { post(:create, params: new_user_params) }
|
||||
subject(:post_create) { post(:create, params: new_user_params) }
|
||||
|
||||
it 'renders the form with errors' do
|
||||
expect { subject }.not_to change(User, :count)
|
||||
expect { post_create }.not_to change(User, :count)
|
||||
|
||||
expect(controller.current_user).to be_nil
|
||||
expect(response).to render_template(:new)
|
||||
expect(response.body).to include(_('Password must not contain commonly used combinations of words and letters'))
|
||||
end
|
||||
|
||||
it 'tracks the error' do
|
||||
subject
|
||||
it 'tracks a weak password error' do
|
||||
post_create
|
||||
|
||||
expect_snowplow_event(
|
||||
category: 'Gitlab::Tracking::Helpers::WeakPasswordErrorEvent',
|
||||
action: 'track_weak_password_error',
|
||||
|
|
@ -503,16 +504,36 @@ RSpec.describe RegistrationsController do
|
|||
method: 'create'
|
||||
)
|
||||
end
|
||||
|
||||
it 'does not track failed form submission' do
|
||||
post_create
|
||||
|
||||
expect_no_snowplow_event(
|
||||
category: described_class.name,
|
||||
action: 'successfully_submitted_form'
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the password is not weak' do
|
||||
it 'does not track a weak password error' do
|
||||
subject
|
||||
post_create
|
||||
|
||||
expect_no_snowplow_event(
|
||||
category: 'Gitlab::Tracking::Helpers::WeakPasswordErrorEvent',
|
||||
action: 'track_weak_password_error'
|
||||
)
|
||||
end
|
||||
|
||||
it 'tracks successful form submission' do
|
||||
post_create
|
||||
|
||||
expect_snowplow_event(
|
||||
category: described_class.name,
|
||||
action: 'successfully_submitted_form',
|
||||
user: User.find_by(email: base_user_params[:email])
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with preferred language' do
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ RSpec.describe 'User creates a merge request', :js, feature_category: :code_revi
|
|||
first('.dropdown-source-project a', text: forked_project.full_path)
|
||||
|
||||
first('.js-target-project').click
|
||||
first('.dropdown-target-project a', text: project.full_path)
|
||||
first('.dropdown-target-project li', text: project.full_path)
|
||||
|
||||
first('.js-source-branch').click
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,77 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import MockAdapter from 'axios-mock-adapter';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import TargetProjectDropdown from '~/merge_requests/components/target_project_dropdown.vue';
|
||||
|
||||
let wrapper;
|
||||
let mock;
|
||||
|
||||
function factory() {
|
||||
wrapper = mount(TargetProjectDropdown, {
|
||||
provide: {
|
||||
targetProjectsPath: '/gitlab-org/gitlab/target_projects',
|
||||
currentProject: { value: 1, text: 'gitlab-org/gitlab' },
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
describe('Merge requests target project dropdown component', () => {
|
||||
beforeEach(() => {
|
||||
mock = new MockAdapter(axios);
|
||||
mock.onGet('/gitlab-org/gitlab/target_projects').reply(200, [
|
||||
{
|
||||
id: 10,
|
||||
name: 'Gitlab Test',
|
||||
full_path: '/root/gitlab-test',
|
||||
full_name: 'Administrator / Gitlab Test',
|
||||
refs_url: '/root/gitlab-test/refs',
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
name: 'Gitlab Test',
|
||||
full_path: '/gitlab-org/gitlab-test',
|
||||
full_name: 'Gitlab Org / Gitlab Test',
|
||||
refs_url: '/gitlab-org/gitlab-test/refs',
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
mock.restore();
|
||||
});
|
||||
|
||||
it('creates hidden input with currentProject ID', () => {
|
||||
factory();
|
||||
|
||||
expect(wrapper.find('[data-testid="target-project-input"]').attributes('value')).toBe('1');
|
||||
});
|
||||
|
||||
it('renders list of projects', async () => {
|
||||
factory();
|
||||
|
||||
wrapper.find('[data-testid="base-dropdown-toggle"]').trigger('click');
|
||||
|
||||
await waitForPromises();
|
||||
|
||||
expect(wrapper.findAll('li').length).toBe(2);
|
||||
expect(wrapper.findAll('li').at(0).text()).toBe('root/gitlab-test');
|
||||
expect(wrapper.findAll('li').at(1).text()).toBe('gitlab-org/gitlab-test');
|
||||
});
|
||||
|
||||
it('searches projects', async () => {
|
||||
factory();
|
||||
|
||||
wrapper.find('[data-testid="base-dropdown-toggle"]').trigger('click');
|
||||
|
||||
await waitForPromises();
|
||||
|
||||
wrapper.find('[data-testid="listbox-search-input"]').setValue('test');
|
||||
|
||||
jest.advanceTimersByTime(500);
|
||||
await waitForPromises();
|
||||
|
||||
expect(mock.history.get[1].params).toEqual({ search: 'test' });
|
||||
});
|
||||
});
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe GitlabSchema.types['AlertManagementAlert'] do
|
||||
RSpec.describe GitlabSchema.types['AlertManagementAlert'], feature_category: :incident_management do
|
||||
specify { expect(described_class.graphql_name).to eq('AlertManagementAlert') }
|
||||
|
||||
specify { expect(described_class).to require_graphql_authorizations(:read_alert_management_alert) }
|
||||
|
|
@ -11,6 +11,7 @@ RSpec.describe GitlabSchema.types['AlertManagementAlert'] do
|
|||
|
||||
it 'exposes the expected fields' do
|
||||
expected_fields = %i[
|
||||
id
|
||||
iid
|
||||
issueIid
|
||||
issue
|
||||
|
|
|
|||
|
|
@ -2,16 +2,17 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'diagnostic reports' do
|
||||
RSpec.describe 'diagnostic reports', :aggregate_failures, feature_category: :application_performance do
|
||||
subject(:load_initializer) do
|
||||
load Rails.root.join('config/initializers/diagnostic_reports.rb')
|
||||
end
|
||||
|
||||
shared_examples 'does not modify worker startup hooks' do
|
||||
shared_examples 'does not modify worker hooks' do
|
||||
it do
|
||||
expect(Gitlab::Cluster::LifecycleEvents).not_to receive(:on_worker_start)
|
||||
expect(Gitlab::Cluster::LifecycleEvents).not_to receive(:on_worker_stop)
|
||||
expect(Gitlab::Memory::ReportsDaemon).not_to receive(:instance)
|
||||
expect(Gitlab::Memory::Reporter).not_to receive(:new)
|
||||
|
||||
load_initializer
|
||||
end
|
||||
|
|
@ -32,6 +33,7 @@ RSpec.describe 'diagnostic reports' do
|
|||
|
||||
it 'modifies worker startup hooks, starts Gitlab::Memory::ReportsDaemon' do
|
||||
expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_start).and_call_original
|
||||
expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_stop) # stub this out to not mutate global state
|
||||
expect_next_instance_of(Gitlab::Memory::ReportsDaemon) do |daemon|
|
||||
expect(daemon).to receive(:start)
|
||||
end
|
||||
|
|
@ -39,30 +41,15 @@ RSpec.describe 'diagnostic reports' do
|
|||
load_initializer
|
||||
end
|
||||
|
||||
context 'when GITLAB_MEMWD_DUMP_HEAP is set' do
|
||||
before do
|
||||
stub_env('GITLAB_MEMWD_DUMP_HEAP', '1')
|
||||
end
|
||||
it 'writes scheduled heap dumps in on_worker_stop' do
|
||||
expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_start)
|
||||
expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_stop).and_call_original
|
||||
expect(Gitlab::Memory::Reporter).to receive(:new).and_return(reporter)
|
||||
expect(reporter).to receive(:run_report).with(an_instance_of(Gitlab::Memory::Reports::HeapDump))
|
||||
|
||||
it 'writes scheduled heap dumps in on_worker_stop' do
|
||||
expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_start)
|
||||
expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_stop).and_call_original
|
||||
expect(Gitlab::Memory::Reporter).to receive(:new).and_return(reporter)
|
||||
expect(reporter).to receive(:run_report).with(an_instance_of(Gitlab::Memory::Reports::HeapDump))
|
||||
|
||||
load_initializer
|
||||
# This is necessary because this hook normally fires during worker shutdown.
|
||||
Gitlab::Cluster::LifecycleEvents.do_worker_stop
|
||||
end
|
||||
end
|
||||
|
||||
context 'when GITLAB_MEMWD_DUMP_HEAP is not set' do
|
||||
it 'does not write heap dumps' do
|
||||
expect(Gitlab::Cluster::LifecycleEvents).to receive(:on_worker_start)
|
||||
expect(Gitlab::Cluster::LifecycleEvents).not_to receive(:on_worker_stop)
|
||||
|
||||
load_initializer
|
||||
end
|
||||
load_initializer
|
||||
# This is necessary because this hook normally fires during worker shutdown.
|
||||
Gitlab::Cluster::LifecycleEvents.do_worker_stop
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -71,7 +58,7 @@ RSpec.describe 'diagnostic reports' do
|
|||
allow(::Gitlab::Runtime).to receive(:puma?).and_return(false)
|
||||
end
|
||||
|
||||
include_examples 'does not modify worker startup hooks'
|
||||
include_examples 'does not modify worker hooks'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -80,7 +67,7 @@ RSpec.describe 'diagnostic reports' do
|
|||
allow(::Gitlab::Runtime).to receive(:puma?).and_return(true)
|
||||
end
|
||||
|
||||
include_examples 'does not modify worker startup hooks'
|
||||
include_examples 'does not modify worker hooks'
|
||||
end
|
||||
|
||||
context 'when GITLAB_DIAGNOSTIC_REPORTS_ENABLED is set to false' do
|
||||
|
|
@ -89,6 +76,6 @@ RSpec.describe 'diagnostic reports' do
|
|||
allow(::Gitlab::Runtime).to receive(:puma?).and_return(true)
|
||||
end
|
||||
|
||||
include_examples 'does not modify worker startup hooks'
|
||||
include_examples 'does not modify worker hooks'
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Database::LoadBalancing::SidekiqClientMiddleware do
|
||||
RSpec.describe Gitlab::Database::LoadBalancing::SidekiqClientMiddleware, feature_category: :database do
|
||||
let(:middleware) { described_class.new }
|
||||
|
||||
let(:worker_class) { 'TestDataConsistencyWorker' }
|
||||
|
|
@ -82,21 +82,41 @@ RSpec.describe Gitlab::Database::LoadBalancing::SidekiqClientMiddleware do
|
|||
allow(Gitlab::Database::LoadBalancing::Session.current).to receive(:use_primary?).and_return(false)
|
||||
end
|
||||
|
||||
it 'passes database_replica_location' do
|
||||
expected_location = {}
|
||||
context 'when replica hosts are available' do
|
||||
it 'passes database_replica_location' do
|
||||
expected_location = {}
|
||||
|
||||
Gitlab::Database::LoadBalancing.each_load_balancer do |lb|
|
||||
expect(lb.host)
|
||||
.to receive(:database_replica_location)
|
||||
.and_return(location)
|
||||
Gitlab::Database::LoadBalancing.each_load_balancer do |lb|
|
||||
expect(lb.host)
|
||||
.to receive(:database_replica_location)
|
||||
.and_return(location)
|
||||
|
||||
expected_location[lb.name] = location
|
||||
expected_location[lb.name] = location
|
||||
end
|
||||
|
||||
run_middleware
|
||||
|
||||
expect(job['wal_locations']).to eq(expected_location)
|
||||
expect(job['wal_location_source']).to eq(:replica)
|
||||
end
|
||||
end
|
||||
|
||||
run_middleware
|
||||
context 'when no replica hosts are available' do
|
||||
it 'passes primary_write_location' do
|
||||
expected_location = {}
|
||||
|
||||
expect(job['wal_locations']).to eq(expected_location)
|
||||
expect(job['wal_location_source']).to eq(:replica)
|
||||
Gitlab::Database::LoadBalancing.each_load_balancer do |lb|
|
||||
expect(lb).to receive(:host).and_return(nil)
|
||||
expect(lb).to receive(:primary_write_location).and_return(location)
|
||||
|
||||
expected_location[lb.name] = location
|
||||
end
|
||||
|
||||
run_middleware
|
||||
|
||||
expect(job['wal_locations']).to eq(expected_location)
|
||||
expect(job['wal_location_source']).to eq(:replica)
|
||||
end
|
||||
end
|
||||
|
||||
include_examples 'job data consistency'
|
||||
|
|
|
|||
|
|
@ -109,6 +109,25 @@ RSpec.describe Gitlab::Instrumentation::RedisBase, :request_store do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.increment_allowed_cross_slot_request_count' do
|
||||
context 'storage key overlapping' do
|
||||
it 'keys do not overlap across storages' do
|
||||
3.times { instrumentation_class_a.increment_allowed_cross_slot_request_count }
|
||||
2.times { instrumentation_class_b.increment_allowed_cross_slot_request_count }
|
||||
|
||||
expect(instrumentation_class_a.get_allowed_cross_slot_request_count).to eq(3)
|
||||
expect(instrumentation_class_b.get_allowed_cross_slot_request_count).to eq(2)
|
||||
end
|
||||
|
||||
it 'increments by the given amount' do
|
||||
instrumentation_class_a.increment_allowed_cross_slot_request_count(2)
|
||||
instrumentation_class_a.increment_allowed_cross_slot_request_count(3)
|
||||
|
||||
expect(instrumentation_class_a.get_allowed_cross_slot_request_count).to eq(5)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.increment_read_bytes' do
|
||||
context 'storage key overlapping' do
|
||||
it 'keys do not overlap across storages' do
|
||||
|
|
|
|||
|
|
@ -83,12 +83,14 @@ RSpec.describe Gitlab::Instrumentation::RedisInterceptor, :clean_gitlab_redis_sh
|
|||
|
||||
it 'counts disallowed cross-slot requests' do
|
||||
expect(instrumentation_class).to receive(:increment_cross_slot_request_count).and_call_original
|
||||
expect(instrumentation_class).not_to receive(:increment_allowed_cross_slot_request_count).and_call_original
|
||||
|
||||
Gitlab::Redis::SharedState.with { |redis| redis.call(:mget, 'foo', 'bar') }
|
||||
end
|
||||
|
||||
it 'does not count allowed cross-slot requests' do
|
||||
expect(instrumentation_class).not_to receive(:increment_cross_slot_request_count).and_call_original
|
||||
expect(instrumentation_class).to receive(:increment_allowed_cross_slot_request_count).and_call_original
|
||||
|
||||
Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
|
||||
Gitlab::Redis::SharedState.with { |redis| redis.call(:mget, 'foo', 'bar') }
|
||||
|
|
@ -97,6 +99,7 @@ RSpec.describe Gitlab::Instrumentation::RedisInterceptor, :clean_gitlab_redis_sh
|
|||
|
||||
it 'skips count for non-cross-slot requests' do
|
||||
expect(instrumentation_class).not_to receive(:increment_cross_slot_request_count).and_call_original
|
||||
expect(instrumentation_class).not_to receive(:increment_allowed_cross_slot_request_count).and_call_original
|
||||
|
||||
Gitlab::Redis::SharedState.with { |redis| redis.call(:mget, '{foo}bar', '{foo}baz') }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ RSpec.describe Gitlab::Instrumentation::Redis do
|
|||
|
||||
it_behaves_like 'aggregation of redis storage data', :get_request_count
|
||||
it_behaves_like 'aggregation of redis storage data', :get_cross_slot_request_count
|
||||
it_behaves_like 'aggregation of redis storage data', :get_allowed_cross_slot_request_count
|
||||
it_behaves_like 'aggregation of redis storage data', :query_time
|
||||
it_behaves_like 'aggregation of redis storage data', :read_bytes
|
||||
it_behaves_like 'aggregation of redis storage data', :write_bytes
|
||||
|
|
@ -39,21 +40,26 @@ RSpec.describe Gitlab::Instrumentation::Redis do
|
|||
|
||||
stub_rails_env('staging') # to avoid raising CrossSlotError
|
||||
Gitlab::Redis::Cache.with { |redis| redis.mset('cache-test', 321, 'cache-test-2', 321) }
|
||||
Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
|
||||
Gitlab::Redis::Cache.with { |redis| redis.mget('cache-test', 'cache-test-2') }
|
||||
end
|
||||
Gitlab::Redis::SharedState.with { |redis| redis.set('shared-state-test', 123) }
|
||||
end
|
||||
|
||||
it 'returns payload filtering out zeroed values' do
|
||||
expected_payload = {
|
||||
# Aggregated results
|
||||
redis_calls: 2,
|
||||
redis_calls: 3,
|
||||
redis_cross_slot_calls: 1,
|
||||
redis_allowed_cross_slot_calls: 1,
|
||||
redis_duration_s: be >= 0,
|
||||
redis_read_bytes: be >= 0,
|
||||
redis_write_bytes: be >= 0,
|
||||
|
||||
# Cache results
|
||||
redis_cache_calls: 1,
|
||||
redis_cache_calls: 2,
|
||||
redis_cache_cross_slot_calls: 1,
|
||||
redis_cache_allowed_cross_slot_calls: 1,
|
||||
redis_cache_duration_s: be >= 0,
|
||||
redis_cache_read_bytes: be >= 0,
|
||||
redis_cache_write_bytes: be >= 0,
|
||||
|
|
|
|||
|
|
@ -41,13 +41,17 @@ RSpec.describe Gitlab::InstrumentationHelper do
|
|||
it 'adds Redis data and omits Gitaly data' do
|
||||
stub_rails_env('staging') # to avoid raising CrossSlotError
|
||||
Gitlab::Redis::Cache.with { |redis| redis.mset('test-cache', 123, 'test-cache2', 123) }
|
||||
Gitlab::Instrumentation::RedisClusterValidator.allow_cross_slot_commands do
|
||||
Gitlab::Redis::Cache.with { |redis| redis.mget('cache-test', 'cache-test-2') }
|
||||
end
|
||||
Gitlab::Redis::Queues.with { |redis| redis.set('test-queues', 321) }
|
||||
|
||||
subject
|
||||
|
||||
# Aggregated payload
|
||||
expect(payload[:redis_calls]).to eq(2)
|
||||
expect(payload[:redis_calls]).to eq(3)
|
||||
expect(payload[:redis_cross_slot_calls]).to eq(1)
|
||||
expect(payload[:redis_allowed_cross_slot_calls]).to eq(1)
|
||||
expect(payload[:redis_duration_s]).to be >= 0
|
||||
expect(payload[:redis_read_bytes]).to be >= 0
|
||||
expect(payload[:redis_write_bytes]).to be >= 0
|
||||
|
|
@ -59,8 +63,9 @@ RSpec.describe Gitlab::InstrumentationHelper do
|
|||
expect(payload[:redis_queues_write_bytes]).to be >= 0
|
||||
|
||||
# Cache payload
|
||||
expect(payload[:redis_cache_calls]).to eq(1)
|
||||
expect(payload[:redis_cache_calls]).to eq(2)
|
||||
expect(payload[:redis_cache_cross_slot_calls]).to eq(1)
|
||||
expect(payload[:redis_cache_allowed_cross_slot_calls]).to eq(1)
|
||||
expect(payload[:redis_cache_duration_s]).to be >= 0
|
||||
expect(payload[:redis_cache_read_bytes]).to be >= 0
|
||||
expect(payload[:redis_cache_write_bytes]).to be >= 0
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Memory::Reports::HeapDump do
|
||||
RSpec.describe Gitlab::Memory::Reports::HeapDump, feature_category: :application_performance do
|
||||
# Copy this class so we do not mess with its state.
|
||||
let(:klass) { described_class.dup }
|
||||
|
||||
|
|
@ -16,8 +16,13 @@ RSpec.describe Gitlab::Memory::Reports::HeapDump do
|
|||
end
|
||||
|
||||
describe '#active?' do
|
||||
# This will be enabled once https://gitlab.com/gitlab-org/gitlab/-/issues/370077 is done.
|
||||
it 'is false' do
|
||||
it 'is true when report_heap_dumps is enabled' do
|
||||
expect(report).to be_active
|
||||
end
|
||||
|
||||
it 'is false when report_heap_dumps is disabled' do
|
||||
stub_feature_flags(report_heap_dumps: false)
|
||||
|
||||
expect(report).not_to be_active
|
||||
end
|
||||
end
|
||||
|
|
@ -29,15 +34,22 @@ RSpec.describe Gitlab::Memory::Reports::HeapDump do
|
|||
|
||||
context 'when no heap dump is enqueued' do
|
||||
it 'does nothing and returns false' do
|
||||
expect(ObjectSpace).not_to receive(:dump_all)
|
||||
|
||||
expect(run).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a heap dump is enqueued' do
|
||||
it 'does nothing and returns true' do
|
||||
context 'when a heap dump is enqueued', :aggregate_failures do
|
||||
it 'dumps heap and returns true' do
|
||||
expect(ObjectSpace).to receive(:dump_all).with(output: writer) do |output:|
|
||||
output << 'heap contents'
|
||||
end
|
||||
|
||||
klass.enqueue!
|
||||
|
||||
expect(run).to be(true)
|
||||
expect(writer.string).to eq('heap contents')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -25,12 +25,6 @@ RSpec.describe Gitlab::Memory::Watchdog::Configurator do
|
|||
expect(configuration.event_reporter.logger).to eq(logger)
|
||||
end
|
||||
|
||||
it 'does not enable writing heap dumps by default' do
|
||||
configurator.call(configuration)
|
||||
|
||||
expect(configuration.write_heap_dumps?).to be(false)
|
||||
end
|
||||
|
||||
context 'when sleep_time_seconds is not passed through the environment' do
|
||||
let(:sleep_time_seconds) { sleep_time }
|
||||
|
||||
|
|
@ -54,42 +48,6 @@ RSpec.describe Gitlab::Memory::Watchdog::Configurator do
|
|||
expect(configuration.sleep_time_seconds).to eq(sleep_time_seconds)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when GITLAB_MEMWD_DUMP_HEAP is set' do
|
||||
before do
|
||||
stub_env('GITLAB_MEMWD_DUMP_HEAP', env_var)
|
||||
end
|
||||
|
||||
context 'with null value' do
|
||||
let(:env_var) { nil }
|
||||
|
||||
it 'does not enable writing heap dumps' do
|
||||
configurator.call(configuration)
|
||||
|
||||
expect(configuration.write_heap_dumps?).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with falsey value' do
|
||||
let(:env_var) { '0' }
|
||||
|
||||
it 'does not enable writing heap dumps' do
|
||||
configurator.call(configuration)
|
||||
|
||||
expect(configuration.write_heap_dumps?).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with truthy value' do
|
||||
let(:env_var) { '1' }
|
||||
|
||||
it 'enables writing heap dumps' do
|
||||
configurator.call(configuration)
|
||||
|
||||
expect(configuration.write_heap_dumps?).to be(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'as monitor configurator' do
|
||||
|
|
|
|||
|
|
@ -2,13 +2,12 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures do
|
||||
RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures, feature_category: :application_performance do
|
||||
context 'watchdog' do
|
||||
let(:configuration) { instance_double(described_class::Configuration) }
|
||||
let(:handler) { instance_double(described_class::NullHandler) }
|
||||
let(:reporter) { instance_double(described_class::EventReporter) }
|
||||
let(:sleep_time_seconds) { 60 }
|
||||
let(:write_heap_dumps) { false }
|
||||
let(:threshold_violated) { false }
|
||||
let(:watchdog_iterations) { 1 }
|
||||
let(:name) { :monitor_name }
|
||||
|
|
@ -50,7 +49,6 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures do
|
|||
config.handler = handler
|
||||
config.event_reporter = reporter
|
||||
config.sleep_time_seconds = sleep_time_seconds
|
||||
config.write_heap_dumps = write_heap_dumps
|
||||
config.monitors.push monitor_class, threshold_violated, payload, max_strikes: max_strikes
|
||||
end
|
||||
|
||||
|
|
@ -123,16 +121,6 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures do
|
|||
|
||||
watchdog.call
|
||||
end
|
||||
|
||||
context 'and heap dumps are enabled' do
|
||||
let(:write_heap_dumps) { true }
|
||||
|
||||
it 'does not schedule a heap dump' do
|
||||
expect(Gitlab::Memory::Reports::HeapDump).not_to receive(:enqueue!)
|
||||
|
||||
watchdog.call
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when monitor exceeds the allowed number of strikes' do
|
||||
|
|
@ -158,14 +146,10 @@ RSpec.describe Gitlab::Memory::Watchdog, :aggregate_failures do
|
|||
watchdog.call
|
||||
end
|
||||
|
||||
context 'and heap dumps are enabled' do
|
||||
let(:write_heap_dumps) { true }
|
||||
it 'schedules a heap dump' do
|
||||
expect(Gitlab::Memory::Reports::HeapDump).to receive(:enqueue!)
|
||||
|
||||
it 'schedules a heap dump' do
|
||||
expect(Gitlab::Memory::Reports::HeapDump).to receive(:enqueue!)
|
||||
|
||||
watchdog.call
|
||||
end
|
||||
watchdog.call
|
||||
end
|
||||
|
||||
context 'when enforce_memory_watchdog ops toggle is off' do
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Badge do
|
||||
let(:placeholder_url) { 'http://www.example.com/%{project_path}/%{project_id}/%{project_name}/%{default_branch}/%{commit_sha}' }
|
||||
let(:placeholder_url) { 'http://www.example.com/%{project_path}/%{project_id}/%{default_branch}/%{commit_sha}' }
|
||||
|
||||
describe 'validations' do
|
||||
# Requires the let variable url_sym
|
||||
|
|
@ -64,7 +64,7 @@ RSpec.describe Badge do
|
|||
it 'uses the project information to populate the url placeholders' do
|
||||
stub_project_commit_info(project)
|
||||
|
||||
expect(badge.public_send("rendered_#{method}", project)).to eq "http://www.example.com/#{project.full_path}/#{project.id}/#{project.name}/master/whatever"
|
||||
expect(badge.public_send("rendered_#{method}", project)).to eq "http://www.example.com/#{project.full_path}/#{project.id}/master/whatever"
|
||||
end
|
||||
|
||||
it 'returns the url if the project used is nil' do
|
||||
|
|
|
|||
|
|
@ -5310,6 +5310,20 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the current user is not the bridge user' do
|
||||
let(:current_user) { create(:user) }
|
||||
|
||||
before do
|
||||
project.add_maintainer(current_user)
|
||||
end
|
||||
|
||||
it 'changes bridge user to current user' do
|
||||
expect { reset_bridge }
|
||||
.to change { bridge.reload.user }
|
||||
.from(owner).to(current_user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the user does not have permissions for the processable' do
|
||||
|
|
@ -5328,6 +5342,15 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
|
|||
.and not_change { bridge_dependant_dag_job.reload.status }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the current user is not the bridge user' do
|
||||
let(:current_user) { create(:user) }
|
||||
|
||||
it 'does not change bridge user' do
|
||||
expect { reset_bridge }
|
||||
.to not_change { bridge.reload.user }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -37,12 +37,6 @@ RSpec.describe User do
|
|||
end
|
||||
end
|
||||
|
||||
describe '.bots_without_project_bot' do
|
||||
it 'includes all bots except project_bot' do
|
||||
expect(described_class.bots_without_project_bot).to match_array(bots - [project_bot])
|
||||
end
|
||||
end
|
||||
|
||||
describe '.non_internal' do
|
||||
it 'includes all non_internal users' do
|
||||
expect(described_class.non_internal).to match_array(non_internal)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Deleting Sidekiq jobs', :clean_gitlab_redis_queues do
|
||||
RSpec.describe 'Deleting Sidekiq jobs', :clean_gitlab_redis_queues, feature_category: :not_owned do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:admin) { create(:admin) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Create an alert issue from an alert' do
|
||||
RSpec.describe 'Create an alert issue from an alert', feature_category: :incident_management do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Setting assignees of an alert' do
|
||||
RSpec.describe 'Setting assignees of an alert', feature_category: :incident_management do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:project) { create(:project) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Creating a todo for the alert' do
|
||||
RSpec.describe 'Creating a todo for the alert', feature_category: :incident_management do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Setting the status of an alert' do
|
||||
RSpec.describe 'Setting the status of an alert', feature_category: :incident_management do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Creating a new HTTP Integration' do
|
||||
RSpec.describe 'Creating a new HTTP Integration', feature_category: :integrations do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Removing an HTTP Integration' do
|
||||
RSpec.describe 'Removing an HTTP Integration', feature_category: :integrations do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Resetting a token on an existing HTTP Integration' do
|
||||
RSpec.describe 'Resetting a token on an existing HTTP Integration', feature_category: :integrations do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Updating an existing HTTP Integration' do
|
||||
RSpec.describe 'Updating an existing HTTP Integration', feature_category: :integrations do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Creating a new Prometheus Integration' do
|
||||
RSpec.describe 'Creating a new Prometheus Integration', feature_category: :incident_management do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Resetting a token on an existing Prometheus Integration' do
|
||||
RSpec.describe 'Resetting a token on an existing Prometheus Integration', feature_category: :incident_management do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Updating an existing Prometheus Integration' do
|
||||
RSpec.describe 'Updating an existing Prometheus Integration', feature_category: :incident_management do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Adding an AwardEmoji' do
|
||||
RSpec.describe 'Adding an AwardEmoji', feature_category: :not_owned do
|
||||
include GraphqlHelpers
|
||||
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Removing an AwardEmoji' do
|
||||
RSpec.describe 'Removing an AwardEmoji', feature_category: :not_owned do
|
||||
include GraphqlHelpers
|
||||
|
||||
let(:current_user) { create(:user) }
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue