Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-12-09 15:08:59 +00:00
parent 5b98c2c506
commit fd8183c340
220 changed files with 1172 additions and 616 deletions

View File

@ -1 +1 @@
5c143379d62a9489c5c24e42fb177bb5b7f09318
c832720d9ad3948e6cf2c371f01c85e9dd9a3a5a

View File

@ -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}'),
{

View File

@ -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',
];

View File

@ -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

View File

@ -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
}

View File

@ -26,6 +26,7 @@ query getAlerts(
before: $prevPageCursor
domain: $domain
) {
# eslint-disable-next-line @graphql-eslint/require-id-when-available
nodes {
...AlertListItem
assignees {

View File

@ -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

View File

@ -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>

View File

@ -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(

View File

@ -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

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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;
}
}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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]

View File

@ -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

View File

@ -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,

View File

@ -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 }

View File

@ -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

View File

@ -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)) }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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" }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1 @@
8e9641a603bd9540d0004fb76b407a5cb4392c8cc41c084cd746f354b9a8d417

View File

@ -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);

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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. |

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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/).

View File

@ -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**.

View File

@ -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

View File

@ -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)**

View File

@ -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
![Group SAML Settings for GitLab.com](img/group_saml_settings_v13_12.png)
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.

View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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:

View File

@ -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>

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 ""

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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' });
});
});

View File

@ -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

View File

@ -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

View File

@ -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'

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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) }

View File

@ -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) }

View File

@ -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) }

View File

@ -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) }

View File

@ -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) }

View File

@ -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) }

View File

@ -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) }

View File

@ -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) }

View File

@ -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) }

View File

@ -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) }

View File

@ -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) }

View File

@ -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) }

View File

@ -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) }

View File

@ -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