Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-03-09 18:09:41 +00:00
parent 6f2b1c32f3
commit 72c331ebf5
145 changed files with 1742 additions and 666 deletions

View File

@ -44,7 +44,6 @@ Graphql/Descriptions:
# WIP See https://gitlab.com/gitlab-org/gitlab/-/issues/267606
FactoryBot/InlineAssociation:
Exclude:
- 'ee/spec/factories/geo/event_log.rb'
- 'ee/spec/factories/merge_request_blocks.rb'
- 'ee/spec/factories/vulnerabilities/feedback.rb'
- 'spec/factories/atlassian_identities.rb'

View File

@ -1 +1 @@
d1f4340a1123d2436c7544d6ba64635c4c8f6104
58bf16b78b3c99757a2f283a5befe57a2cb7f009

View File

@ -54,15 +54,17 @@ export default {
required: false,
},
},
data: () => ({
currentServerSideSettings: {
host: null,
port: null,
protocol: null,
wafLogEnabled: null,
ciliumLogEnabled: null,
},
}),
data() {
return {
currentServerSideSettings: {
host: null,
port: null,
protocol: null,
wafLogEnabled: null,
ciliumLogEnabled: null,
},
};
},
computed: {
isSaving() {
return [UPDATING].includes(this.status);

View File

@ -53,11 +53,13 @@ export default {
}),
},
},
data: () => ({
modSecurityLogo,
initialValue: null,
initialMode: null,
}),
data() {
return {
modSecurityLogo,
initialValue: null,
initialMode: null,
};
},
computed: {
modSecurityEnabled: {
get() {

View File

@ -259,19 +259,28 @@ export default {
class="line-resolve-btn note-action-button"
@click="onResolve"
/>
<a
<gl-button
v-if="canAwardEmoji"
v-gl-tooltip
:class="{ 'js-user-authored': isAuthoredByCurrentUser }"
class="note-action-button note-emoji-button js-add-award js-note-emoji gl-text-gray-600 gl-m-2"
href="#"
class="note-action-button note-emoji-button add-reaction-button js-add-award js-note-emoji"
category="tertiary"
variant="default"
size="small"
title="Add reaction"
data-position="right"
:aria-label="__('Add reaction')"
>
<gl-icon class="link-highlight award-control-icon-neutral" name="slight-smile" />
<gl-icon class="link-highlight award-control-icon-positive" name="smiley" />
<gl-icon class="link-highlight award-control-icon-super-positive" name="smile" />
</a>
<span class="reaction-control-icon reaction-control-icon-neutral">
<gl-icon name="slight-smile" />
</span>
<span class="reaction-control-icon reaction-control-icon-positive">
<gl-icon name="smiley" />
</span>
<span class="reaction-control-icon reaction-control-icon-super-positive">
<gl-icon name="smile" />
</span>
</gl-button>
<reply-button
v-if="showReply"
ref="replyButton"

View File

@ -0,0 +1,72 @@
<script>
import ForkForm from './fork_form.vue';
export default {
components: {
ForkForm,
},
props: {
forkIllustration: {
type: String,
required: true,
},
endpoint: {
type: String,
required: true,
},
projectFullPath: {
type: String,
required: true,
},
projectId: {
type: String,
required: true,
},
projectName: {
type: String,
required: true,
},
projectPath: {
type: String,
required: true,
},
projectDescription: {
type: String,
required: true,
},
projectVisibility: {
type: String,
required: true,
},
},
};
</script>
<template>
<div class="row gl-mt-5">
<div class="col-lg-3">
<img :src="forkIllustration" />
<h4 class="">{{ s__('ForkProject|Fork project') }}</h4>
<p>
{{ s__('ForkProject|A fork is a copy of a project.') }}
<br />
{{
s__(
'ForkProject|Forking a repository allows you to make changes without affecting the original project.',
)
}}
</p>
</div>
<div class="col-lg-9">
<fork-form
:endpoint="endpoint"
:project-full-path="projectFullPath"
:project-id="projectId"
:project-name="projectName"
:project-path="projectPath"
:project-description="projectDescription"
:project-visibility="projectVisibility"
/>
</div>
</div>
</template>

View File

@ -45,23 +45,23 @@ export default {
GlFormRadioGroup,
GlFormSelect,
},
inject: {
newGroupPath: {
default: '',
},
visibilityHelpPath: {
default: '',
},
},
props: {
endpoint: {
type: String,
required: true,
},
newGroupPath: {
type: String,
required: true,
},
projectFullPath: {
type: String,
required: true,
},
visibilityHelpPath: {
type: String,
required: true,
},
projectId: {
type: String,
required: true,

View File

@ -1,11 +1,12 @@
import Vue from 'vue';
import ForkForm from './components/fork_form.vue';
import App from './components/app.vue';
import ForkGroupsList from './components/fork_groups_list.vue';
const mountElement = document.getElementById('fork-groups-mount-element');
if (gon.features.forkProjectForm) {
const {
forkIllustration,
endpoint,
newGroupPath,
projectFullPath,
@ -20,9 +21,14 @@ if (gon.features.forkProjectForm) {
// eslint-disable-next-line no-new
new Vue({
el: mountElement,
provide: {
newGroupPath,
visibilityHelpPath,
},
render(h) {
return h(ForkForm, {
return h(App, {
props: {
forkIllustration,
endpoint,
newGroupPath,
projectFullPath,

View File

@ -86,12 +86,11 @@ export default {
];
},
},
mounted() {
// eslint-disable-next-line promise/catch-or-return
this.initializeRelease().then(() => {
// Focus the first non-disabled input element
this.$el.querySelector('input:enabled').focus();
});
async mounted() {
await this.initializeRelease();
// Focus the first non-disabled input or button element
this.$el.querySelector('input:enabled, button:enabled').focus();
},
methods: {
...mapActions('detail', [

View File

@ -1,20 +1,29 @@
<script>
import { GlFormGroup, GlFormInput } from '@gitlab/ui';
import { GlFormGroup, GlDropdownItem, GlSprintf } from '@gitlab/ui';
import { uniqueId } from 'lodash';
import { mapState, mapActions, mapGetters } from 'vuex';
import { __ } from '~/locale';
import RefSelector from '~/ref/components/ref_selector.vue';
import { REF_TYPE_TAGS } from '~/ref/constants';
import FormFieldContainer from './form_field_container.vue';
export default {
name: 'TagFieldNew',
components: { GlFormGroup, GlFormInput, RefSelector, FormFieldContainer },
components: {
GlFormGroup,
RefSelector,
FormFieldContainer,
GlDropdownItem,
GlSprintf,
},
data() {
return {
// Keeps track of whether or not the user has interacted with
// the input field. This is used to avoid showing validation
// errors immediately when the page loads.
isInputDirty: false,
showCreateFrom: true,
};
},
computed: {
@ -26,6 +35,12 @@ export default {
},
set(tagName) {
this.updateReleaseTagName(tagName);
// This setter is used by the `v-model` on the `RefSelector`.
// When this is called, the selection originated from the
// dropdown list of existing tag names, so we know the tag
// already exists and don't need to show the "create from" input
this.showCreateFrom = false;
},
},
createFromModel: {
@ -51,12 +66,28 @@ export default {
markInputAsDirty() {
this.isInputDirty = true;
},
createTagClicked(newTagName) {
this.updateReleaseTagName(newTagName);
// This method is called when the user selects the "create tag"
// option, so the tag does not already exist. Because of this,
// we need to show the "create from" input.
this.showCreateFrom = true;
},
},
translations: {
noRefSelected: __('No source selected'),
searchPlaceholder: __('Search branches, tags, and commits'),
dropdownHeader: __('Select source'),
tagName: {
noRefSelected: __('No tag selected'),
dropdownHeader: __('Tag name'),
searchPlaceholder: __('Search or create tag'),
},
createFrom: {
noRefSelected: __('No source selected'),
searchPlaceholder: __('Search branches, tags, and commits'),
dropdownHeader: __('Select source'),
},
},
tagNameEnabledRefTypes: [REF_TYPE_TAGS],
};
</script>
<template>
@ -69,17 +100,34 @@ export default {
:invalid-feedback="__('Tag name is required')"
>
<form-field-container>
<gl-form-input
<ref-selector
:id="tagNameInputId"
v-model="tagName"
:project-id="projectId"
:translations="$options.translations.tagName"
:enabled-ref-types="$options.tagNameEnabledRefTypes"
:state="!showTagNameValidationError"
type="text"
class="form-control"
@blur.once="markInputAsDirty"
/>
@hide.once="markInputAsDirty"
>
<template #footer="{ isLoading, matches, query }">
<gl-dropdown-item
v-if="!isLoading && matches && matches.tags.totalCount === 0"
is-check-item
:is-checked="tagName === query"
@click="createTagClicked(query)"
>
<gl-sprintf :message="__('Create tag %{tagName}')">
<template #tagName>
<b>{{ query }}</b>
</template>
</gl-sprintf>
</gl-dropdown-item>
</template>
</ref-selector>
</form-field-container>
</gl-form-group>
<gl-form-group
v-if="showCreateFrom"
:label="__('Create from')"
:label-for="createFromSelectorId"
data-testid="create-from-field"
@ -89,7 +137,7 @@ export default {
:id="createFromSelectorId"
v-model="createFromModel"
:project-id="projectId"
:translations="$options.translations"
:translations="$options.translations.createFrom"
/>
</form-field-container>
<template #description>

View File

@ -1,5 +1,5 @@
<script>
import { GlLink, GlSprintf, GlTable, GlAlert } from '@gitlab/ui';
import { GlLink, GlTable, GlAlert } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import {
REPORT_TYPE_SAST,
@ -8,10 +8,11 @@ import {
REPORT_TYPE_DEPENDENCY_SCANNING,
REPORT_TYPE_CONTAINER_SCANNING,
REPORT_TYPE_COVERAGE_FUZZING,
REPORT_TYPE_API_FUZZING,
REPORT_TYPE_LICENSE_COMPLIANCE,
} from '~/vue_shared/security_reports/constants';
import { features } from './features_constants';
import ManageSast from './manage_sast.vue';
import { scanners } from './scanners_constants';
import Upgrade from './upgrade.vue';
const borderClasses = 'gl-border-b-1! gl-border-b-solid! gl-border-gray-100!';
@ -20,14 +21,14 @@ const thClass = `gl-text-gray-900 gl-bg-transparent! ${borderClasses}`;
export default {
components: {
GlLink,
GlSprintf,
GlTable,
GlAlert,
},
data: () => ({
features,
errorMessage: '',
}),
data() {
return {
errorMessage: '',
};
},
methods: {
getFeatureDocumentationLinkLabel(item) {
return sprintf(s__('SecurityConfiguration|Feature documentation for %{featureName}'), {
@ -45,6 +46,7 @@ export default {
[REPORT_TYPE_DEPENDENCY_SCANNING]: Upgrade,
[REPORT_TYPE_CONTAINER_SCANNING]: Upgrade,
[REPORT_TYPE_COVERAGE_FUZZING]: Upgrade,
[REPORT_TYPE_API_FUZZING]: Upgrade,
[REPORT_TYPE_LICENSE_COMPLIANCE]: Upgrade,
};
@ -64,7 +66,7 @@ export default {
thClass,
},
],
items: features,
items: scanners,
},
};
</script>

View File

@ -14,9 +14,11 @@ export default {
default: '',
},
},
data: () => ({
isLoading: false,
}),
data() {
return {
isLoading: false,
};
},
methods: {
async mutate() {
this.isLoading = true;

View File

@ -1,5 +1,5 @@
import { helpPagePath } from '~/helpers/help_page_helper';
import { s__ } from '~/locale';
import { __, s__ } from '~/locale';
import {
REPORT_TYPE_SAST,
@ -9,58 +9,65 @@ import {
REPORT_TYPE_DEPENDENCY_SCANNING,
REPORT_TYPE_CONTAINER_SCANNING,
REPORT_TYPE_COVERAGE_FUZZING,
REPORT_TYPE_API_FUZZING,
REPORT_TYPE_LICENSE_COMPLIANCE,
} from '~/vue_shared/security_reports/constants';
/**
* Translations & helpPagePaths for Static Security Configuration Page
*/
export const SAST_NAME = s__('Static Application Security Testing (SAST)');
export const SAST_DESCRIPTION = s__('Analyze your source code for known vulnerabilities.');
export const SAST_NAME = __('Static Application Security Testing (SAST)');
export const SAST_DESCRIPTION = __('Analyze your source code for known vulnerabilities.');
export const SAST_HELP_PATH = helpPagePath('user/application_security/sast/index');
export const DAST_NAME = s__('Dynamic Application Security Testing (DAST)');
export const DAST_DESCRIPTION = s__('Analyze a review version of your web application.');
export const DAST_NAME = __('Dynamic Application Security Testing (DAST)');
export const DAST_DESCRIPTION = __('Analyze a review version of your web application.');
export const DAST_HELP_PATH = helpPagePath('user/application_security/dast/index');
export const DAST_PROFILES_NAME = s__('DAST Scans');
export const DAST_PROFILES_DESCRIPTION = s__('Analyze a review version of your web application.');
export const DAST_PROFILES_NAME = __('DAST Scans');
export const DAST_PROFILES_DESCRIPTION = __(
'Saved scan settings and target site settings which are reusable.',
);
export const DAST_PROFILES_HELP_PATH = helpPagePath('user/application_security/dast/index');
export const SECRET_DETECTION_NAME = s__('Secret Detection');
export const SECRET_DETECTION_DESCRIPTION = s__(
export const SECRET_DETECTION_NAME = __('Secret Detection');
export const SECRET_DETECTION_DESCRIPTION = __(
'Analyze your source code and git history for secrets.',
);
export const SECRET_DETECTION_HELP_PATH = helpPagePath(
'user/application_security/secret_detection/index',
);
export const DEPENDENCY_SCANNING_NAME = s__('Dependency Scanning');
export const DEPENDENCY_SCANNING_DESCRIPTION = s__(
export const DEPENDENCY_SCANNING_NAME = __('Dependency Scanning');
export const DEPENDENCY_SCANNING_DESCRIPTION = __(
'Analyze your dependencies for known vulnerabilities.',
);
export const DEPENDENCY_SCANNING_HELP_PATH = helpPagePath(
'user/application_security/dependency_scanning/index',
);
export const CONTAINER_SCANNING_NAME = s__('Container Scanning');
export const CONTAINER_SCANNING_DESCRIPTION = s__(
export const CONTAINER_SCANNING_NAME = __('Container Scanning');
export const CONTAINER_SCANNING_DESCRIPTION = __(
'Check your Docker images for known vulnerabilities.',
);
export const CONTAINER_SCANNING_HELP_PATH = helpPagePath(
'user/application_security/container_scanning/index',
);
export const COVERAGE_FUZZING_NAME = s__('Coverage Fuzzing');
export const COVERAGE_FUZZING_DESCRIPTION = s__(
export const COVERAGE_FUZZING_NAME = __('Coverage Fuzzing');
export const COVERAGE_FUZZING_DESCRIPTION = __(
'Find bugs in your code with coverage-guided fuzzing.',
);
export const COVERAGE_FUZZING_HELP_PATH = helpPagePath(
'user/application_security/coverage_fuzzing/index',
);
export const LICENSE_COMPLIANCE_NAME = s__('License Compliance');
export const LICENSE_COMPLIANCE_DESCRIPTION = s__(
export const API_FUZZING_NAME = __('API Fuzzing');
export const API_FUZZING_DESCRIPTION = __('Find bugs in your code with API fuzzing.');
export const API_FUZZING_HELP_PATH = helpPagePath('user/application_security/api_fuzzing/index');
export const LICENSE_COMPLIANCE_NAME = __('License Compliance');
export const LICENSE_COMPLIANCE_DESCRIPTION = __(
'Search your project dependencies for their licenses and apply policies.',
);
export const LICENSE_COMPLIANCE_HELP_PATH = helpPagePath(
@ -71,7 +78,7 @@ export const UPGRADE_CTA = s__(
'SecurityConfiguration|Available with %{linkStart}upgrade or free trial%{linkEnd}',
);
export const features = [
export const scanners = [
{
name: SAST_NAME,
description: SAST_DESCRIPTION,
@ -90,12 +97,6 @@ export const features = [
helpPath: DAST_PROFILES_HELP_PATH,
type: REPORT_TYPE_DAST_PROFILES,
},
{
name: SECRET_DETECTION_NAME,
description: SECRET_DETECTION_DESCRIPTION,
helpPath: SECRET_DETECTION_HELP_PATH,
type: REPORT_TYPE_SECRET_DETECTION,
},
{
name: DEPENDENCY_SCANNING_NAME,
description: DEPENDENCY_SCANNING_DESCRIPTION,
@ -108,12 +109,24 @@ export const features = [
helpPath: CONTAINER_SCANNING_HELP_PATH,
type: REPORT_TYPE_CONTAINER_SCANNING,
},
{
name: SECRET_DETECTION_NAME,
description: SECRET_DETECTION_DESCRIPTION,
helpPath: SECRET_DETECTION_HELP_PATH,
type: REPORT_TYPE_SECRET_DETECTION,
},
{
name: COVERAGE_FUZZING_NAME,
description: COVERAGE_FUZZING_DESCRIPTION,
helpPath: COVERAGE_FUZZING_HELP_PATH,
type: REPORT_TYPE_COVERAGE_FUZZING,
},
{
name: API_FUZZING_NAME,
description: API_FUZZING_DESCRIPTION,
helpPath: API_FUZZING_HELP_PATH,
type: REPORT_TYPE_API_FUZZING,
},
{
name: LICENSE_COMPLIANCE_NAME,
description: LICENSE_COMPLIANCE_DESCRIPTION,

View File

@ -1,6 +1,6 @@
<script>
import { GlLink, GlSprintf } from '@gitlab/ui';
import { UPGRADE_CTA } from './features_constants';
import { UPGRADE_CTA } from './scanners_constants';
export default {
components: {

View File

@ -70,7 +70,7 @@ export default {
data: {
mergeRequestSetWip: {
errors,
mergeRequest: { workInProgress, title },
mergeRequest: { mergeableDiscussionsState, workInProgress, title },
},
},
},
@ -87,6 +87,8 @@ export default {
});
const data = produce(sourceData, (draftState) => {
// eslint-disable-next-line no-param-reassign
draftState.project.mergeRequest.mergeableDiscussionsState = mergeableDiscussionsState;
// eslint-disable-next-line no-param-reassign
draftState.project.mergeRequest.workInProgress = workInProgress;
// eslint-disable-next-line no-param-reassign
@ -107,6 +109,7 @@ export default {
errors: [],
mergeRequest: {
__typename: 'MergeRequest',
mergeableDiscussionsState: true,
title: this.mr.title,
workInProgress: false,
},

View File

@ -1,6 +1,7 @@
mutation toggleWIPStatus($projectPath: ID!, $iid: String!, $wip: Boolean!) {
mergeRequestSetWip(input: { projectPath: $projectPath, iid: $iid, wip: $wip }) {
mergeRequest {
mergeableDiscussionsState
title
workInProgress
}

View File

@ -37,9 +37,11 @@ export default {
required: true,
},
},
data: () => ({
state: STATE_IDLING,
}),
data() {
return {
state: STATE_IDLING,
};
},
computed: {
shortSha() {
return truncateSha(this.diffFile.content_sha);

View File

@ -23,7 +23,7 @@ export const REPORT_TYPE_SECRET_DETECTION = 'secret_detection';
export const REPORT_TYPE_DEPENDENCY_SCANNING = 'dependency_scanning';
export const REPORT_TYPE_CONTAINER_SCANNING = 'container_scanning';
export const REPORT_TYPE_COVERAGE_FUZZING = 'coverage_fuzzing';
export const REPORT_TYPE_LICENSE_COMPLIANCE = 'license_compliance';
export const REPORT_TYPE_LICENSE_COMPLIANCE = 'license_scanning';
export const REPORT_TYPE_API_FUZZING = 'api_fuzzing';
/**

View File

@ -521,7 +521,7 @@ class ProjectsController < Projects::ApplicationController
def export_rate_limit
prefixed_action = "project_#{params[:action]}".to_sym
project_scope = params[:action] == :download_export ? @project : nil
project_scope = params[:action] == 'download_export' ? @project : nil
if rate_limiter.throttled?(prefixed_action, scope: [current_user, project_scope].compact)
rate_limiter.log_request(request, "#{prefixed_action}_request_limit".to_sym, current_user)

View File

@ -232,7 +232,7 @@ module DiffHelper
# Always use HTML to handle case where JSON diff rendered this button
params_copy.delete(:format)
link_to url_for(params_copy), id: "#{name}-diff-btn", class: (selected ? 'btn gl-button active' : 'btn gl-button'), data: { view_type: name } do
link_to url_for(params_copy), id: "#{name}-diff-btn", class: (selected ? 'btn gl-button btn-default selected' : 'btn gl-button btn-default'), data: { view_type: name } do
title
end
end

View File

@ -505,7 +505,7 @@ class Group < Namespace
# @param only_concrete_membership [Bool] whether require admin concrete membership status
def max_member_access_for_user(user, only_concrete_membership: false)
return GroupMember::NO_ACCESS unless user
return GroupMember::OWNER if user.admin? && !only_concrete_membership
return GroupMember::OWNER if user.can_admin_all_resources? && !only_concrete_membership
max_member_access = members_with_parents.where(user_id: user)
.reorder(access_level: :desc)

View File

@ -131,6 +131,10 @@ class Label < ApplicationRecord
nil
end
def self.ids_on_board(board_id)
on_board(board_id).pluck(:label_id)
end
# Searches for labels with a matching title or description.
#
# This method uses ILIKE on PostgreSQL.

View File

@ -191,8 +191,12 @@ class MergeRequest < ApplicationRecord
end
state_machine :merge_status, initial: :unchecked do
event :mark_as_preparing do
transition unchecked: :preparing
end
event :mark_as_unchecked do
transition [:can_be_merged, :checking] => :unchecked
transition [:preparing, :can_be_merged, :checking] => :unchecked
transition [:cannot_be_merged, :cannot_be_merged_rechecking] => :cannot_be_merged_recheck
end
@ -209,6 +213,7 @@ class MergeRequest < ApplicationRecord
transition [:unchecked, :cannot_be_merged_recheck, :checking, :cannot_be_merged_rechecking] => :cannot_be_merged
end
state :preparing
state :unchecked
state :cannot_be_merged_recheck
state :checking
@ -237,7 +242,7 @@ class MergeRequest < ApplicationRecord
# Returns current merge_status except it returns `cannot_be_merged_rechecking` as `checking`
# to avoid exposing unnecessary internal state
def public_merge_status
cannot_be_merged_rechecking? ? 'checking' : merge_status
cannot_be_merged_rechecking? || preparing? ? 'checking' : merge_status
end
validates :source_project, presence: true, unless: [:allow_broken, :importing?, :closed_or_merged_without_fork?]

View File

@ -1704,6 +1704,10 @@ class User < ApplicationRecord
can?(:read_all_resources)
end
def can_admin_all_resources?
can?(:admin_all_resources)
end
def update_two_factor_requirement
periods = expanded_groups_requiring_two_factor_authentication.pluck(:two_factor_grace_period)

View File

@ -55,14 +55,17 @@ class BasePolicy < DeclarativePolicy::Base
prevent :read_cross_project
end
# Policy extended in EE to also enable auditors
rule { admin }.enable :read_all_resources
rule { admin }.policy do
# Only for actual administrator accounts, behaviour affected by admin mode application setting
enable :admin_all_resources
# Policy extended in EE to also enable auditors
enable :read_all_resources
enable :change_repository_storage
end
rule { default }.enable :read_cross_project
condition(:is_gitlab_com) { ::Gitlab.dev_env_or_com? }
rule { admin }.enable :change_repository_storage
end
BasePolicy.prepend_if_ee('EE::BasePolicy')

View File

@ -0,0 +1,72 @@
# frozen_string_literal: true
module Boards
class BaseItemMoveService < Boards::BaseService
def execute(issuable)
issuable_modification_params = issuable_params(issuable)
return false if issuable_modification_params.empty?
move_single_issuable(issuable, issuable_modification_params)
end
private
def issuable_params(issuable)
attrs = {}
if move_between_lists?
attrs.merge!(
add_label_ids: add_label_ids,
remove_label_ids: remove_label_ids,
state_event: issuable_state
)
end
attrs
end
def move_single_issuable(issuable, issuable_modification_params)
ability_name = :"admin_#{issuable.to_ability_name}"
return unless can?(current_user, ability_name, issuable)
update(issuable, issuable_modification_params)
end
def move_between_lists?
moving_from_list.present? && moving_to_list.present? &&
moving_from_list != moving_to_list
end
def moving_from_list
return unless params[:from_list_id].present?
@moving_from_list ||= board.lists.id_in(params[:from_list_id]).first
end
def moving_to_list
return unless params[:to_list_id].present?
@moving_to_list ||= board.lists.id_in(params[:to_list_id]).first
end
def issuable_state
return 'reopen' if moving_from_list.closed?
return 'close' if moving_to_list.closed?
end
def add_label_ids
[moving_to_list.label_id].compact
end
def remove_label_ids
label_ids =
if moving_to_list.movable?
moving_from_list.label_id
else
::Label.ids_on_board(board.id)
end
Array(label_ids).compact
end
end
end

View File

@ -2,13 +2,8 @@
module Boards
module Issues
class MoveService < Boards::BaseService
def execute(issue)
issue_modification_params = issue_params(issue)
return false if issue_modification_params.empty?
move_single_issue(issue, issue_modification_params)
end
class MoveService < Boards::BaseItemMoveService
extend ::Gitlab::Utils::Override
def execute_multiple(issues)
return execute_multiple_empty_result if issues.empty?
@ -16,7 +11,7 @@ module Boards
handled_issues = []
last_inserted_issue_id = nil
count = issues.each.inject(0) do |moved_count, issue|
issue_modification_params = issue_params(issue)
issue_modification_params = issuable_params(issue)
next moved_count if issue_modification_params.empty?
if last_inserted_issue_id
@ -24,7 +19,7 @@ module Boards
end
last_inserted_issue_id = issue.id
handled_issue = move_single_issue(issue, issue_modification_params)
handled_issue = move_single_issuable(issue, issue_modification_params)
handled_issues << present_issue_entity(handled_issue) if handled_issue
handled_issue && handled_issue.valid? ? moved_count + 1 : moved_count
end
@ -54,51 +49,17 @@ module Boards
move_between_ids({ move_after_id: nil, move_before_id: id })
end
def move_single_issue(issue, issue_modification_params)
return unless can?(current_user, :update_issue, issue)
update(issue, issue_modification_params)
end
def board
@board ||= parent.boards.find(params[:board_id])
end
def move_between_lists?
moving_from_list.present? && moving_to_list.present? &&
moving_from_list != moving_to_list
end
# rubocop: disable CodeReuse/ActiveRecord
def moving_from_list
return unless params[:from_list_id].present?
@moving_from_list ||= board.lists.find_by(id: params[:from_list_id])
end
# rubocop: enable CodeReuse/ActiveRecord
# rubocop: disable CodeReuse/ActiveRecord
def moving_to_list
return unless params[:to_list_id].present?
@moving_to_list ||= board.lists.find_by(id: params[:to_list_id])
end
# rubocop: enable CodeReuse/ActiveRecord
def update(issue, issue_modification_params)
::Issues::UpdateService.new(issue.project, current_user, issue_modification_params).execute(issue)
end
def issue_params(issue)
attrs = {}
if move_between_lists?
attrs.merge!(
add_label_ids: add_label_ids,
remove_label_ids: remove_label_ids,
state_event: issue_state
)
end
override :issuable_params
def issuable_params(issuable)
attrs = super
move_between_ids = move_between_ids(params)
if move_between_ids
@ -109,28 +70,6 @@ module Boards
attrs
end
def issue_state
return 'reopen' if moving_from_list.closed?
return 'close' if moving_to_list.closed?
end
def add_label_ids
[moving_to_list.label_id].compact
end
# rubocop: disable CodeReuse/ActiveRecord
def remove_label_ids
label_ids =
if moving_to_list.movable?
moving_from_list.label_id
else
::Label.on_board(board.id).pluck(:label_id)
end
Array(label_ids).compact
end
# rubocop: enable CodeReuse/ActiveRecord
def move_between_ids(move_params)
ids = [move_params[:move_after_id], move_params[:move_before_id]]
.map(&:to_i)

View File

@ -3,6 +3,13 @@
module MergeRequests
class AfterCreateService < MergeRequests::BaseService
def execute(merge_request)
prepare_merge_request(merge_request)
merge_request.mark_as_unchecked if merge_request.preparing?
end
private
def prepare_merge_request(merge_request)
event_service.open_mr(merge_request, current_user)
merge_request_activity_counter.track_create_mr_action(user: current_user)

View File

@ -1,28 +1,29 @@
- page_title _("Fork project")
- page_title s_("ForkProject|Fork project")
.row.gl-mt-3
.col-lg-3
%h4.gl-mt-0
= _("Fork project")
%p
= _("A fork is a copy of a project.")
%br
= _('Forking a repository allows you to make changes without affecting the original project.')
.col-lg-9
- if Feature.enabled?(:fork_project_form)
#fork-groups-mount-element{ data: { endpoint: new_project_fork_path(@project, format: :json),
new_group_path: new_group_path,
project_full_path: project_path(@project),
visibility_help_path: help_page_path("public_access/public_access"),
project_id: @project.id,
project_name: @project.name,
project_path: @project.path,
project_description: @project.description,
project_visibility: @project.visibility } }
- else
- if Feature.enabled?(:fork_project_form)
#fork-groups-mount-element{ data: { fork_illustration: image_path('illustrations/project-create-new-sm.svg'),
endpoint: new_project_fork_path(@project, format: :json),
new_group_path: new_group_path,
project_full_path: project_path(@project),
visibility_help_path: help_page_path("public_access/public_access"),
project_id: @project.id,
project_name: @project.name,
project_path: @project.path,
project_description: @project.description,
project_visibility: @project.visibility } }
- else
.row.gl-mt-3
.col-lg-3
%h4.gl-mt-0
= s_("ForkProject|Fork project")
%p
= s_("ForkProject|A fork is a copy of a project.")
%br
= s_('ForkProject|Forking a repository allows you to make changes without affecting the original project.')
.col-lg-9
- if @own_namespace.present?
.fork-thumbnail-container.js-fork-content
%h5.gl-mt-0.gl-mb-0.gl-ml-3.gl-mr-3
= _("Select a namespace to fork the project")
= s_("ForkProject|Select a namespace to fork the project")
= render 'fork_button', namespace: @own_namespace
#fork-groups-mount-element{ data: { endpoint: new_project_fork_path(@project, format: :json) } }

View File

@ -2,7 +2,7 @@
%section.qa-deploy-tokens-settings.settings.no-animate#js-deploy-tokens{ class: ('expanded' if expanded), data: { qa_selector: 'deploy_tokens_settings_content' } }
.settings-header
%h4= s_('DeployTokens|Deploy tokens')
%h4.settings-title.js-settings-toggle.js-settings-toggle-trigger-only= s_('DeployTokens|Deploy tokens')
%button.btn.gl-button.btn-default.js-settings-toggle.qa-expand-deploy-keys{ type: 'button' }
= expanded ? 'Collapse' : 'Expand'
%p

View File

@ -0,0 +1,5 @@
---
title: Project Settings Repository Deploy tokens header expands/collapses on click / tap
merge_request: 55233
author: Daniel Schömer
type: changed

View File

@ -0,0 +1,5 @@
---
title: Add API Fuzzing to Security Configuration page, and re-order scanners
merge_request: 56022
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Temporary make `GC.compact` no-op
merge_request: 56079
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Fix Web Project Export rate limiting scope
merge_request: 55975
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Move add reaction button of note to gl-button
merge_request: 53565
author: Yogi (@yo)
type: other

View File

@ -0,0 +1,5 @@
---
title: Allow release to be created on existing tag through the UI
merge_request: 55697
author:
type: added

View File

@ -0,0 +1,5 @@
---
title: Use policies for group access rights as admin
merge_request: 55349
author: Diego Louzán
type: changed

View File

@ -0,0 +1,5 @@
---
title: Add selected state for diff view in commit page
merge_request: 54762
author: Yogi (@yo)
type: changed

View File

@ -0,0 +1,5 @@
---
title: Log large multipart messages from Rack
merge_request: 55933
author:
type: added

View File

@ -0,0 +1,40 @@
# frozen_string_literal: true
module Rack
module Multipart
class << self
module MultipartPatch
def extract_multipart(req, params = Rack::Utils.default_query_parser)
log_multipart_warning(req) if log_large_multipart?
super
end
def log_multipart_warning(req)
content_length = req.content_length.to_i
return unless content_length > 500_000_000
message = {
message: "Large multipart body detected",
path: req.path,
content_length: content_length,
correlation_id: ::Labkit::Context.correlation_id
}
log_warn(message)
end
def log_warn(message)
warn message.to_json
end
def log_large_multipart?
Gitlab::Utils.to_boolean(ENV['ENABLE_RACK_MULTIPART_LOGGING'], default: true) && Gitlab.com?
end
end
prepend MultipartPatch
end
end
end

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
# Be sure to restart your server when you modify this file.
#
# Disables `GC.compact` method via monkey-patching.
# This is temporary measure to deal with reguarly appearing compacting issues (resulting in segfaults) in external gems.
# Having this patch allow using `nakayoshi_fork` in `config/puma.rb`,
# only without `GC.compact` (still invoking 4 GC cycles).
# Refer to for details: https://github.com/puma/puma/blob/80274413b04fae77cac7a7fecab7d6e89204343b/lib/puma/util.rb#L27
# rubocop:disable Rails/Output
module NakayoshiForkCompacting
module MonkeyPatch
def compact
puts 'Note: GC compacting is currently disabled.'\
' Refer to `config/initializers_before_autoloader/003_gc_compact.rb` for details.'
end
end
end
GC.singleton_class.prepend NakayoshiForkCompacting::MonkeyPatch

View File

@ -14,9 +14,8 @@ for updating Geo nodes.
## Updating to GitLab 13.9
We've detected an issue [with a column rename](https://gitlab.com/gitlab-org/gitlab/-/issues/322991)
that prevents regular downtime upgrades to GitLab 13.9.0 and 13.9.1. Zero-downtime upgrades are not
affected. We are working on a patch and recommend delaying any upgrade attempt until a fixed version
is released.
that prevents regular downtime upgrades to GitLab 13.9.0, 13.9.1 and 13.9.2. Zero-downtime upgrades are not
affected. To avoid this issue, upgrade to GitLab 13.9.3 or later.
More details are available [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/322991).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -405,8 +405,8 @@ Rackspace Cloud is supported only with the storage-specific form.
| `provider` | The provider name | `Rackspace` |
| `rackspace_username` | The username of the Rackspace account with access to the container | `joe.smith` |
| `rackspace_api_key` | The API key of the Rackspace account with access to the container | `ABC123DEF456ABC123DEF456ABC123DE` |
| `rackspace_region` | The Rackspace storage region to use, a three letter code from the [list of service access endpoints](https://developer.rackspace.com/docs/cloud-files/v1/general-api-info/service-access/) | `iad` |
| `rackspace_temp_url_key` | The private key you have set in the Rackspace API for [temporary URLs](https://developer.rackspace.com/docs/cloud-files/v1/use-cases/public-access-to-your-cloud-files-account/#tempurl). | `ABC123DEF456ABC123DEF456ABC123DE` |
| `rackspace_region` | The Rackspace storage region to use, a three letter code from the [list of service access endpoints](https://docs.rackspace.com/docs/cloud-files/v1/general-api-info/service-access/) | `iad` |
| `rackspace_temp_url_key` | The private key you have set in the Rackspace API for [temporary URLs](https://docs.rackspace.com/docs/cloud-files/v1/use-cases/public-access-to-your-cloud-files-account/#tempurl). | `ABC123DEF456ABC123DEF456ABC123DE` |
Regardless of whether the container has public access enabled or disabled, Fog
uses the TempURL method to grant access to LFS objects. If you see error

View File

@ -1045,6 +1045,67 @@ project = Project.find_by_full_path('<group/project>')
Geo::RepositorySyncService.new(project).execute
```
### Blob types newer than uploads/artifacts/LFS
- `Packages::PackageFile`
- `Terraform::StateVersion`
- `MergeRequestDiff`
`Packages::PackageFile` is used in the following examples, but things generally work the same for the other Blob types.
#### The Replicator
The main kinds of classes are Registry, Model, and Replicator. If you have an instance of one of these classes, you can get the others. The Registry and Model mostly manage PostgreSQL DB state. The Replicator knows how to replicate/verify (or it can call a service to do it):
```ruby
model_record = Packages::PackageFile.last
model_record.replicator.registry.replicator.model_record # just showing that these methods exist
```
#### Replicate a package file, synchronously, given an ID
```ruby
model_record = Packages::PackageFile.find(id)
model_record.replicator.send(:download)
```
#### Replicate a package file, synchronously, given a registry ID
```ruby
registry = Geo::PackageFileRegistry.find(registry_id)
registry.replicator.send(:download)
```
### Repository types newer than project/wiki repositories
- `SnippetRepository`
- `GroupWikiRepository`
`SnippetRepository` is used in the examples below, but things generally work the same for the other Repository types.
#### The Replicator
The main kinds of classes are Registry, Model, and Replicator. If you have an instance of one of these classes, you can get the others. The Registry and Model mostly manage PostgreSQL DB state. The Replicator knows how to replicate/verify (or it can call a service to do it).
```ruby
model_record = SnippetRepository.last
model_record.replicator.registry.replicator.model_record # just showing that these methods exist
```
#### Replicate a snippet repository, synchronously, given an ID
```ruby
model_record = SnippetRepository.find(id)
model_record.replicator.send(:sync_repository)
```
#### Replicate a snippet repository, synchronously, given a registry ID
```ruby
registry = Geo::SnippetRepositoryRegistry.find(registry_id)
registry.replicator.send(:sync_repository)
```
### Generate usage ping
#### Generate or get the cached usage ping

View File

@ -5,13 +5,13 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, api
---
# DORA4 Analytics Group API **(ULTIMATE ONLY)**
# DORA4 Analytics Group API **(ULTIMATE SELF)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/291747) in GitLab 13.9.
> - It's [deployed behind a feature flag](../user/feature_flags.md), disabled by default.
> - It's disabled on GitLab.com.
> - It's not recommended for production use.
> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-dora4-analytics-group-api). **(ULTIMATE ONLY)**
> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-dora4-analytics-group-api). **(ULTIMATE SELF)**
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
@ -64,7 +64,7 @@ Example response:
]
```
## Enable or disable DORA4 Analytics Group API **(ULTIMATE ONLY)**
## Enable or disable DORA4 Analytics Group API **(ULTIMATE SELF)**
DORA4 Analytics Group API is under development and not ready for production use. It is
deployed behind a feature flag that is **disabled by default**.

View File

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: reference, api
---
# DORA4 Analytics Project API **(ULTIMATE ONLY)**
# DORA4 Analytics Project API **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.7.

View File

@ -149,7 +149,7 @@ POST /projects/:id/feature_flags
| `description` | string | no | The description of the feature flag. |
| `active` | boolean | no | The active state of the flag. Defaults to true. [Supported](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38350) in GitLab 13.3 and later. |
| `strategies` | JSON | no | The feature flag [strategies](../operations/feature_flags.md#feature-flag-strategies). |
| `strategies:name` | JSON | no | The strategy name. Can be `default`, `gradualRolloutUserId`, `userWithId`, or `gitlabUserList`. In [GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/36380) and later, can be [`flexibleRollout`](https://unleash.github.io/docs/activation_strategy#flexiblerollout). |
| `strategies:name` | JSON | no | The strategy name. Can be `default`, `gradualRolloutUserId`, `userWithId`, or `gitlabUserList`. In [GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/36380) and later, can be [`flexibleRollout`](https://docs.getunleash.io/docs/activation_strategy#flexiblerollout). |
| `strategies:parameters` | JSON | no | The strategy parameters. |
| `strategies:scopes` | JSON | no | The scopes for the strategy. |
| `strategies:scopes:environment_scope` | string | no | The environment spec for the scope. |

View File

@ -2063,6 +2063,15 @@ Represents an epic board list.
| `position` | Int | Position of the list within the board. |
| `title` | String! | Title of the list. |
### `EpicMoveListPayload`
Autogenerated return type of EpicMoveList.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
### `EpicPermissions`
Check permissions for the current user on an epic.
@ -2602,6 +2611,30 @@ Represents an iteration object.
| `webPath` | String! | Web path of the iteration. |
| `webUrl` | String! | Web URL of the iteration. |
### `IterationCadence`
Represents an iteration cadence.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `active` | Boolean | Whether the iteration cadence is active. |
| `automatic` | Boolean | Whether the iteration cadence should automatically generate future iterations. |
| `durationInWeeks` | Int! | Duration in weeks of the iterations within this cadence. |
| `id` | IterationsCadenceID! | Global ID of the iteration cadence. |
| `iterationsInAdvance` | Int! | Future iterations to be created when iteration cadence is set to automatic. |
| `startDate` | Time | Timestamp of the iteration cadence start date. |
| `title` | String! | Title of the iteration cadence. |
### `IterationCadenceCreatePayload`
Autogenerated return type of IterationCadenceCreate.
| Field | Type | Description |
| ----- | ---- | ----------- |
| `clientMutationId` | String | A unique identifier for the client performing the mutation. |
| `errors` | String! => Array | Errors encountered during execution of the mutation. |
| `iterationCadence` | IterationCadence | The created iteration cadence. |
### `JiraImport`
| Field | Type | Description |

View File

@ -1005,6 +1005,20 @@ If the project is a fork, and you provide a valid token to authenticate, the
}
```
Users of [GitLab Premium or higher](https://about.gitlab.com/pricing/)
can also see the `issues_template` and `merge_requests_template` parameters:
[introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55718)
in GitLab 13.10.
```json
{
"id": 3,
"issues_template": null,
"merge_requests_template": null,
...
}
```
## Get project users
Get the users list of a project.
@ -1303,6 +1317,8 @@ PUT /projects/:id
| `visibility` | string | **{dotted-circle}** No | See [project visibility level](#project-visibility-level). |
| `wiki_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. |
| `wiki_enabled` | boolean | **{dotted-circle}** No | _(Deprecated)_ Enable wiki for this project. Use `wiki_access_level` instead. |
| `issues_template` **(PREMIUM)** | string | **{dotted-circle}** No | Default description for Issues. Description is parsed with GitLab Flavored Markdown. |
| `merge_requests_template` **(PREMIUM)** | string | **{dotted-circle}** No | Default description for Merge Requests. Description is parsed with GitLab Flavored Markdown. |
## Fork project

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Getting started with Continuous Deployment to AWS Elastic Container Service **(FREE)**
This step-by-step guide helps you use [Continuous Deployment to ECS](../index.md#deploy-your-application-to-the-aws-elastic-container-service-ecs)
that deploys a project hosted on GitLab.com to [Elastic Container Service](https://aws.amazon.com/ecs)
that deploys a project hosted on GitLab.com to [Elastic Container Service](https://aws.amazon.com/ecs/)
(ECS) on AWS.
In this guide, you begin by creating an ECS cluster manually using the AWS console. You create and
@ -59,7 +59,7 @@ container registry.
### Push a containerized application image to GitLab Container Registry
[ECS](https://aws.amazon.com/ecs) is a container orchestration service, meaning that you must
[ECS](https://aws.amazon.com/ecs/) is a container orchestration service, meaning that you must
provide a containerized application image during the infrastructure build. To do so, you can use
GitLab [Auto Build](../../../topics/autodevops/stages.md#auto-build)
and [Container Registry](../../../user/packages/container_registry/index.md).

View File

@ -23,7 +23,7 @@ it easier to [deploy to AWS](#deploy-your-application-to-the-aws-elastic-contain
### Quick start
If you're using GitLab.com, see the [quick start guide](ecs/quick_start_guide.md)
for setting up Continuous Deployment to [AWS Elastic Container Service](https://aws.amazon.com/ecs) (ECS).
for setting up Continuous Deployment to [AWS Elastic Container Service](https://aws.amazon.com/ecs/) (ECS).
### Run AWS commands from GitLab CI/CD

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@ -18,7 +18,7 @@ a deployment is created.
GitLab:
- Provides a full history of deployments to each environment.
- Tracks your deployments, so you always know what is currently deployed on your
- Tracks your deployments, so you always know what is deployed on your
servers.
If you have a deployment service like [Kubernetes](../../user/project/clusters/index.md)
@ -116,8 +116,7 @@ In this example:
use `$CI_ENVIRONMENT_SLUG` instead. The `$CI_ENVIRONMENT_SLUG` variable is guaranteed to be unique.
You do not have to use the same prefix or only slashes (`/`) in the dynamic environment name.
However, when you use this format, you can use the [grouping similar environments](#grouping-similar-environments)
feature.
However, when you use this format, you can [group similar environments](#group-similar-environments).
NOTE:
Some variables cannot be used as environment names or URLs.
@ -184,8 +183,8 @@ deploy:
- master
```
When deploying to a Kubernetes cluster using the GitLab Kubernetes integration,
information about the cluster and namespace is displayed above the job
When you use the GitLab Kubernetes integration to deploy to a Kubernetes cluster,
cluster and namespace information is displayed above the job
trace on the deployment job page:
![Deployment cluster information](../img/environments_deployment_cluster_v12_8.png)
@ -202,8 +201,8 @@ When you create an environment, you specify the name and URL.
If you want to use the name or URL in another job, you can use:
- `$CI_ENVIRONMENT_NAME`. The name defined in the `.gitlab-ci.yml` file.
- `$CI_ENVIRONMENT_SLUG`. A "cleaned-up" version of the name, suitable for use in URLs,
DNS, etc. This variable is guaranteed to be unique.
- `$CI_ENVIRONMENT_SLUG`. A "cleaned-up" version of the name, suitable for use in URL and DNS, for example.
This variable is guaranteed to be unique.
- `$CI_ENVIRONMENT_URL`. The environment's URL, which was specified in the
`.gitlab-ci.yml` file or automatically assigned.
@ -220,12 +219,12 @@ If you change the name of an existing environment, the:
In a job script, you can specify a static environment URL.
However, there may be times when you want a dynamic URL. For example,
if you deploy a Review App to an external hosting
service that generates a random URL per deployment, like `https://94dd65b.amazonaws.com/qa-lambda-1234567`,
you don't know the URL before the deployment script finishes.
service that generates a random URL per deployment, like `https://94dd65b.amazonaws.com/qa-lambda-1234567`.
In this case, you don't know the URL before the deployment script finishes.
If you want to use the environment URL in GitLab, you would have to update it manually.
To address this problem, you can configure a deployment job to report back a set of
variables, including the URL that was dynamically-generated by the external service.
variables. These variables include the URL that was dynamically-generated by the external service.
GitLab supports the [dotenv (`.env`)](https://github.com/bkeepers/dotenv) file format,
and expands the `environment:url` value with variables defined in the `.env` file.
@ -286,23 +285,6 @@ Note the following:
for these jobs. This ensures that runners can fetch the repository even after a feature branch is
deleted. For more information, see [Ref Specs for Runners](../pipelines/index.md#ref-specs-for-runners).
## Deployment safety
Deployment jobs can be more sensitive than other jobs in a pipeline,
and might need to be treated with an extra care. There are multiple features
in GitLab that help maintain deployment security and stability.
- [Restrict write-access to a critical environment](deployment_safety.md#restrict-write-access-to-a-critical-environment)
- [Limit the job-concurrency for deployment jobs](deployment_safety.md#ensure-only-one-deployment-job-runs-at-a-time)
- [Skip outdated deployment jobs](deployment_safety.md#skip-outdated-deployment-jobs)
- [Prevent deployments during deploy freeze windows](deployment_safety.md#prevent-deployments-during-deploy-freeze-windows)
## Protected environments
Environments can be "protected", restricting access to them.
For more information, see [Protected environments](protected_environments.md).
## Working with environments
Once environments are configured, GitLab provides many features for working with them,
@ -331,8 +313,8 @@ To retry or rollback a deployment:
### Environment URL
The [environment URL](../yaml/README.md#environmenturl) is exposed in a few
places within GitLab:
The [environment URL](../yaml/README.md#environmenturl) is displayed in a few
places in GitLab:
- In a merge request as a link:
![Environment URL in merge request](../img/environments_mr_review_app.png)
@ -359,8 +341,8 @@ from source files to public pages in the environment set for Review Apps.
When you stop an environment:
- It moves from the list of **Available** environments to the list of **Stopped**
environments on the [**Environments** page](#view-environments-and-deployments).
- On the **Environments** page, it moves from the list of **Available** environments
to the list of **Stopped** environments.
- An [`on_stop` action](../yaml/README.md#environmenton_stop), if defined, is executed.
Dynamic environments stop automatically when their associated branch is
@ -368,10 +350,16 @@ deleted.
#### Stop an environment when a branch is deleted
Environments can be stopped automatically using special configuration.
You can configure environments to stop when a branch is deleted.
Consider the following example where the `deploy_review` job calls `stop_review`
to clean up and stop the environment:
The following example shows a `deploy_review` job that calls a `stop_review` job
to clean up and stop the environment. The `stop_review` job must be in the same
`stage` as the `deploy_review` job.
Both jobs must have the same [`rules`](../yaml/README.md#onlyexcept-basic)
or [`only/except`](../yaml/README.md#onlyexcept-basic) configuration. Otherwise,
the `stop_review` job might not be included in all pipelines that include the
`deploy_review` job, and you cannot trigger `action: stop` to stop the environment automatically.
```yaml
deploy_review:
@ -397,55 +385,30 @@ stop_review:
when: manual
```
If you can't use [Pipelines for merge requests](../merge_request_pipelines/index.md),
setting the [`GIT_STRATEGY`](../runners/README.md#git-strategy) to `none` is necessary in the
`stop_review` job so that the [runner](https://docs.gitlab.com/runner/) doesn't
If you can't use [pipelines for merge requests](../merge_request_pipelines/index.md),
set the [`GIT_STRATEGY`](../runners/README.md#git-strategy) to `none` in the
`stop_review` job. Then the [runner](https://docs.gitlab.com/runner/) doesn't
try to check out the code after the branch is deleted.
When you have an environment that has a stop action defined (typically when
the environment describes a Review App), GitLab automatically triggers a
stop action when the associated branch is deleted. The `stop_review` job must
be in the same `stage` as the `deploy_review` job in order for the environment
to automatically stop.
Additionally, both jobs should have matching [`rules`](../yaml/README.md#onlyexcept-basic)
or [`only/except`](../yaml/README.md#onlyexcept-basic) configuration. In the example
above, if the configuration isn't identical, the `stop_review` job might not be
included in all pipelines that include the `deploy_review` job, and it isn't
possible to trigger `action: stop` to stop the environment automatically.
You can read more in the [`.gitlab-ci.yml` reference](../yaml/README.md#environmenton_stop).
Read more in the [`.gitlab-ci.yml` reference](../yaml/README.md#environmenton_stop).
#### Stop an environment after a certain time period
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20956) in GitLab 12.8.
You can set an expiry time for environments and stop them automatically after a certain period.
You can set environments to stop automatically after a certain time period.
For example, consider the use of this feature with Review App environments. When you set up Review
Apps, sometimes they keep running for a long time because some merge requests are left open and
forgotten. Such idle environments waste resources and should be terminated as soon as possible.
In your `.gitlab-ci.yml` file, specify the [`environment:auto_stop_in`](../yaml/README.md#environmentauto_stop_in)
keyword. You can specify a human-friendly date as the value, such as `1 hour and 30 minutes` or `1 day`.
After the time period passes, GitLab automatically triggers a job to stop the environment.
To address this problem, you can specify an optional expiration date for Review App environments.
When the expiry time is reached, GitLab automatically triggers a job to stop the environment,
eliminating the need of manually doing so. In case an environment is updated, the expiration is
renewed ensuring that only active merge requests keep running Review Apps.
To enable this feature, you must specify the [`environment:auto_stop_in`](../yaml/README.md#environmentauto_stop_in)
keyword in `.gitlab-ci.yml`. You can specify a human-friendly date as the value, such as
`1 hour and 30 minutes` or `1 day`. `auto_stop_in` uses the same format of
[`artifacts:expire_in` docs](../yaml/README.md#artifactsexpire_in).
Note that due to resource limitation, a background worker for stopping environments only runs once
Due to resource limitations, a background worker for stopping environments only runs once
every hour. This means that environments aren't stopped at the exact timestamp specified, but are
instead stopped when the hourly cron worker detects expired environments.
##### Auto-stop example
In the following example, there is a basic review app setup that creates a new environment
per merge request. The `review_app` job is triggered by every push and
creates or updates an environment named `review/your-branch-name`.
The environment keeps running until `stop_review_app` is executed:
In the following example, each merge request creates a new Review App environment.
Each push triggers the `review_app` job and an environment named `review/your-branch-name`
is created or updated. The environment runs until `stop_review_app` is executed:
```yaml
review_app:
@ -467,48 +430,48 @@ stop_review_app:
when: manual
```
As long as a merge request is active and keeps getting new commits,
the review app doesn't stop, so developers don't need to worry about
re-initiating review app.
As long as the merge request is active and keeps getting new commits,
the Review App doesn't stop. Developers don't need to worry about
re-initiating Review App.
On the other hand, since `stop_review_app` is set to `auto_stop_in: 1 week`,
if a merge request becomes inactive for more than a week,
Because `stop_review_app` is set to `auto_stop_in: 1 week`,
if a merge request is inactive for more than a week,
GitLab automatically triggers the `stop_review_app` job to stop the environment.
You can also check the expiration date of environments through the GitLab UI. To do so,
go to **Operations > Environments > Environment**. You can see the auto-stop period
at the left-top section and a pin-mark button at the right-top section. This pin-mark
button can be used to prevent auto-stopping the environment. By clicking this button, the
`auto_stop_in` setting is overwritten and the environment is active until it's stopped manually.
#### View a deployment's scheduled stop time
![Environment auto stop](../img/environment_auto_stop_v12_8.png)
You can view a deployment's expiration date in the GitLab UI.
1. Go to the project's **Operations > Environments** page.
1. Select the name of the deployment.
In the top left, next to the environment name, the expiration date is displayed.
#### Override a deployment's scheduled stop time
You can manually override a deployment's expiration date.
1. Go to the project's **Operations > Environments** page.
1. Select the deployment name.
1. In the top right, select the thumbtack (**{thumbtack}**).
![Environment auto stop](img/environment_auto_stop_v13_10.png)
The `auto_stop_in` setting is overwritten and the environment remains active until it's stopped manually.
#### Delete a stopped environment
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20620) in GitLab 12.10.
You can delete [stopped environments](#stopping-an-environment) in one of two
ways: through the GitLab UI or through the API.
You can delete [stopped environments](#stopping-an-environment) in the GitLab UI or by using
[the API](../../api/environments.md#delete-an-environment).
##### Delete environments through the UI
To delete a stopped environment in the GitLab UI:
To view the list of **Stopped** environments, navigate to **Operations > Environments**
and click the **Stopped** tab.
From there, you can click the **Delete** button directly, or you can click the
environment name to see its details and **Delete** it from there.
You can also delete environments by viewing the details for a
stopped environment:
1. Go to the project's **Operations > Environments** page.
1. Click on the name of an environment within the **Stopped** environments list.
1. Click on the **Delete** button that appears at the top for all stopped environments.
1. Finally, confirm your chosen environment in the modal that appears to delete it.
##### Delete environments through the API
Environments can also be deleted by using the [Environments API](../../api/environments.md#delete-an-environment).
1. Go to the project's **Operations > Environments** page.
1. Select the **Stopped** tab.
1. Next to the environment you want to delete, select **Delete environment**.
1. On the confirmation dialog box, select **Delete environment**.
### Prepare an environment
@ -535,19 +498,19 @@ build:
url: https://staging.example.com
```
### Grouping similar environments
### Group similar environments
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7015) in GitLab 8.14.
As documented in [Create a dynamic environment](#create-a-dynamic-environment), you can
prepend environment name with a word, followed by a `/`, and finally the branch
name, which is automatically defined by the `CI_COMMIT_REF_NAME` predefined CI/CD variable.
You can group environments into collapsible sections in the UI.
In short, environments that are named like `type/foo` are all presented under the same
group, named `type`.
For example, if all of your environments start with the name `review`,
then in the UI, the environments are grouped under that heading:
If you name the environments `review/$CI_COMMIT_REF_NAME`
where `$CI_COMMIT_REF_NAME` is the branch name:
![Environment groups](img/environments_dynamic_groups_v13_10.png)
The following example shows how to start your environment names with `review`.
The `$CI_COMMIT_REF_NAME` variable is populated with the branch name at runtime:
```yaml
deploy_review:
@ -558,11 +521,6 @@ deploy_review:
name: review/$CI_COMMIT_REF_NAME
```
If you visit the **Environments** page and the branches
exist, you should see something like:
![Environment groups](../img/environments_dynamic_groups.png)
### Environment incident management
You have successfully setup a Continuous Delivery/Deployment workflow in your project.
@ -634,8 +592,6 @@ Once configured, GitLab attempts to retrieve [supported performance metrics](../
for any environment that has had a successful deployment. If monitoring data was
successfully retrieved, a **Monitoring** button appears for each environment.
![Environment Detail with Metrics](../img/deployments_view.png)
Clicking the **Monitoring** button displays a new page showing up to the last
8 hours of performance data. It may take a minute or two for data to appear
after initial deployment.
@ -666,13 +622,13 @@ Note that container-based deployments often lack basic tools (like an editor), a
be stopped or restarted at any time. If this happens, you lose all your
changes. Treat this as a debugging tool, not a comprehensive online IDE.
Once enabled, your environments gain a **Terminal** button:
Once enabled, your environments display a **Terminal** button:
![Terminal button on environment index](../img/environments_terminal_button_on_index.png)
![Terminal button on environment index](img/environments_terminal_button_on_index_v13_10.png)
You can also access the terminal button from the page for a specific environment:
![Terminal button for an environment](../img/environments_terminal_button_on_show.png)
![Terminal button for an environment](img/environments_terminal_button_on_show_v13_10.png)
Wherever you find it, clicking the button takes you to a separate page to
establish the terminal session:
@ -749,24 +705,15 @@ such as [Review Apps](../review_apps/index.md) (`review/*`).
Note that the most _specific_ spec takes precedence over the other wildcard matching. In this case,
the `review/feature-1` spec takes precedence over `review/*` and `*` specs.
### Environments Dashboard **(PREMIUM)**
## Related topics
See [Environments Dashboard](../environments/environments_dashboard.md) for a summary of each
environment's operational health.
## Limitations
In the `environment: name`, you are limited to only the [predefined CI/CD variables](../variables/predefined_variables.md).
Re-using variables defined inside `script` as part of the environment name doesn't work.
## Further reading
Below are some links you may find interesting:
- [The `.gitlab-ci.yml` definition of environments](../yaml/README.md#environment)
- [A blog post on Deployments & Environments](https://about.gitlab.com/blog/2021/02/05/ci-deployment-and-environments/)
- [Review Apps - Use dynamic environments to deploy your code for every branch](../review_apps/index.md)
- [Deploy Boards for your applications running on Kubernetes](../../user/project/deploy_boards.md)
- [Use GitLab CI to deploy to multiple environments (blog post)](https://about.gitlab.com/blog/2021/02/05/ci-deployment-and-environments/)
- [Review Apps](../review_apps/index.md): Use dynamic environments to deploy your code for every branch.
- [Deploy Boards](../../user/project/deploy_boards.md): View the status of your applications running on Kubernetes.
- [Protected environments](protected_environments.md): Determine who can deploy code to your environments.
- [Environments Dashboard](../environments/environments_dashboard.md): View a summary of each
environment's operational health. **(PREMIUM)**
- [Deployment safety](deployment_safety.md#restrict-write-access-to-a-critical-environment): Secure your deployments.
<!-- ## Troubleshooting

View File

@ -10,7 +10,6 @@ description: 'Confidence checking your entire app every time a new feature is ad
---
<!-- vale off -->
<!-- Needs review for fixing the broken Webdriver links, which link to a deprecated version of Webdriver. -->
# End-to-end testing with GitLab CI/CD and WebdriverIO
@ -51,14 +50,14 @@ infrastructure is up and running, and that your units of code work well together
[Selenium](https://www.selenium.dev/) is a piece of software that can control web browsers, e.g., to make them
visit a specific URL or interact with elements on the page. It can be programmatically controlled
from a variety of programming languages. In this article we're going to be using the
[WebdriverIO](https://webdriver.io/) JavaScript bindings, but the general concept should carry over
[WebdriverIO](http://v4.webdriver.io/) JavaScript bindings, but the general concept should carry over
pretty well to
[other programming languages supported by Selenium](https://www.selenium.dev/documentation/en/legacy_docs/selenium_rc/).
## Writing tests
You can write tests using
[several testing frameworks supported by WebdriverIO](https://webdriver.io/guide/testrunner/frameworks.html).
[several testing frameworks supported by WebdriverIO](http://v4.webdriver.io/guide/testrunner/frameworks.html).
We will be using [Jasmine](https://jasmine.github.io/) here:
```javascript
@ -83,14 +82,14 @@ multiple tests, such as making sure you are logged in.
The function `it` defines an individual test.
[The `browser` object](https://webdriver.io/guide/testrunner/browserobject.html) is WebdriverIO's
special sauce. It provides most of [the WebdriverIO API methods](https://webdriver.io/docs/api/) that are the key to
[The `browser` object](http://v4.webdriver.io/guide/testrunner/browserobject.html) is WebdriverIO's
special sauce. It provides most of [the WebdriverIO API methods](http://v4.webdriver.io/docs/api/) that are the key to
steering the browser. In this case, we can use
[`browser.url`](https://webdriver.io/api/protocol/url.html) to visit `/page-that-does-not-exist` to
hit our 404 page. We can then use [`browser.getUrl`](https://webdriver.io/api/property/getUrl.html)
[`browser.url`](http://v4.webdriver.io/api/protocol/url.html) to visit `/page-that-does-not-exist` to
hit our 404 page. We can then use [`browser.getUrl`](http://v4.webdriver.io/api/property/getUrl.html)
to verify that the current page is indeed at the location we specified. To interact with the page,
we can simply pass CSS selectors to
[`browser.element`](https://webdriver.io/api/protocol/element.html) to get access to elements on the
[`browser.element`](http://v4.webdriver.io/api/protocol/element.html) to get access to elements on the
page and to interact with them - for example, to click on the link back to the home page.
The simple test shown above
@ -112,9 +111,9 @@ you can use [the Webpack Dev Server WebdriverIO plugin](https://www.npmjs.com/pa
that automatically starts a development server before executing the tests.
The WebdriverIO documentation has
[an overview of all configuration options](https://webdriver.io/guide/getstarted/configuration.html), but the
[an overview of all configuration options](http://v4.webdriver.io/guide/getstarted/configuration.html), but the
easiest way to get started is to start with
[WebdriverIO's default configuration](https://webdriver.io/guide/testrunner/configurationfile.html), which
[WebdriverIO's default configuration](http://v4.webdriver.io/guide/testrunner/configurationfile.html), which
provides an overview of all available options. The two options that are going to be most relevant now are the
`specs` option, which is an array of paths to your tests, and the `baseUrl` option, which points to where your app is
running. And finally, we will need to tell WebdriverIO in which browsers we would like to run our
@ -187,7 +186,7 @@ e2e:chrome:
Now that we have a job to run the end-to-end tests in, we need to tell WebdriverIO how to connect to
the Selenium servers running alongside it. We've already cheated a bit above by
passing the value of the [`host`](https://webdriver.io/guide/getstarted/configuration.html#host)
passing the value of the [`host`](http://v4.webdriver.io/guide/getstarted/configuration.html#host)
option as an argument to `npm run confidence-check` on the command line.
However, we still need to tell WebdriverIO which browser is available for it to use.
@ -254,7 +253,7 @@ production project, see:
- [Flockademic's `.gitlab-ci.yml`](https://gitlab.com/Flockademic/Flockademic/blob/dev/.gitlab-ci.yml)
- [Flockademic's tests](https://gitlab.com/Flockademic/Flockademic/tree/dev/__e2e__)
There's plenty more that WebdriverIO can do. For example, you can configure a [`screenshotPath`](https://webdriver.io/guide/getstarted/configuration.html#screenshotPath) to tell WebdriverIO to take
There's plenty more that WebdriverIO can do. For example, you can configure a [`screenshotPath`](http://v4.webdriver.io/guide/getstarted/configuration.html#screenshotPath) to tell WebdriverIO to take
a screenshot when tests are failing. Then tell GitLab CI/CD to store those
[artifacts](../../yaml/README.md#artifacts), and you'll be able to see what went
wrong within GitLab.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

View File

@ -321,7 +321,3 @@ the user must enter a [personal access token](../../user/profile/personal_access
with `api` scope before submitting feedback.
This same method can be used to require authentication for any public projects.
## Limitations
Review App limitations are the same as [environments limitations](../environments/index.md#limitations).

View File

@ -53,6 +53,6 @@ issue for discussion around setting up Auto DevOps development environments.
## Monitoring on GitLab.com
The metric
[`auto_devops_completed_pipelines_total`](https://thanos-query.ops.gitlab.net/graph?g0.range_input=72h&g0.max_source_resolution=0s&g0.expr=sum(increase(auto_devops_pipelines_completed_total%7Benvironment%3D%22gprd%22%7D%5B60m%5D))%20by%20(status)&g0.tab=0)
[`auto_devops_completed_pipelines_total`](https://thanos.gitlab.net/graph?g0.range_input=72h&g0.max_source_resolution=0s&g0.expr=sum(increase(auto_devops_pipelines_completed_total%7Benvironment%3D%22gprd%22%7D%5B60m%5D))%20by%20(status)&g0.tab=0)
(only available to GitLab team members) counts completed Auto DevOps
pipelines, labeled by status.

View File

@ -43,7 +43,7 @@ hardcoded value (10).
At this point, we need to investigate what is using more connections
than we anticipated. To do that, we can use the
`gitlab_ruby_threads_running_threads` metric. For example, [this
graph](https://thanos-query.ops.gitlab.net/graph?g0.range_input=1h&g0.max_source_resolution=0s&g0.expr=sum%20by%20(thread_name)%20(%20gitlab_ruby_threads_running_threads%7Buses_db_connection%3D%22yes%22%7D%20)&g0.tab=0)
graph](https://thanos.gitlab.net/graph?g0.range_input=1h&g0.max_source_resolution=0s&g0.expr=sum%20by%20(thread_name)%20(%20gitlab_ruby_threads_running_threads%7Buses_db_connection%3D%22yes%22%7D%20)&g0.tab=0)
shows all running threads that connect to the database by their
name. Threads labeled `puma worker` or `sidekiq_worker_thread` are
the threads that define `Gitlab::Runtime.max_threads` so those are

View File

@ -14,6 +14,10 @@ feature flag depends on its state (enabled or disabled). When the state
changes, the developer who made the change **must update the documentation**
accordingly.
Every feature introduced to the codebase, even if it's behind a feature flag,
must be documented. For context, see the
[latest merge request that updated this guideline](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47917#note_459984428).
## Criteria
According to the process of [deploying GitLab features behind feature flags](../feature_flags/process.md):

View File

@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
Experiments can be conducted by any GitLab team, most often the teams from the [Growth Sub-department](https://about.gitlab.com/handbook/engineering/development/growth/). Experiments are not tied to releases because they primarily target GitLab.com.
Experiments are run as an A/B test and are behind a feature flag to turn the test on or off. Based on the data the experiment generates, the team decides if the experiment had a positive impact and should be made the new default or rolled back.
Experiments are run as an A/B/n test, and are behind a feature flag to turn the test on or off. Based on the data the experiment generates, the team decides if the experiment had a positive impact and should be made the new default, or rolled back.
## Experiment tracking issue
@ -36,21 +36,39 @@ and link to the issue that resolves the experiment. If the experiment is
successful and becomes part of the product, any follow up issues should be
addressed.
## Experiments using `gitlab-experiment`
## Implement an experiment
There are two options to conduct experiments:
1. [GitLab Experiment](https://gitlab.com/gitlab-org/gitlab-experiment/) is a gem included in GitLab.
1. [`Experimentation Module`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib%2Fgitlab%2Fexperimentation.rb) is built in the GitLab codebase.
Both methods use [experiment](../feature_flags/development.md#experiment-type) feature flags.
Historical Context: `Experimentation Module` was built iteratively with the needs that appeared while implementing Growth sub-department experiments. The `gitlab-experiment` gem was built with the learnings of the `Experimentation Module` and an easier to use API.
Currently both methods for running experiments are included in the codebase. The features are slightly different:
| Feature | `Experiment Module` | `gitlab-experiment` |
| ------ | ------ | ------ |
| Record user grouping | Yes | No (not natively) |
| Uses feature flags | Yes | Yes |
| Multivariate | No | Yes |
However, there is currently no strong suggestion to use one over the other.
### Experiments using `gitlab-experiment` **(FREE SAAS)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/300383) in GitLab 13.7.
> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default.
> - It's enabled on GitLab.com.
> - It is not yet intended for use in GitLab self-managed instances.
[GitLab Experiment](https://gitlab.com/gitlab-org/gitlab-experiment/) is a gem included
in GitLab that can be used for running experiments.
You find out how to conduct experiments using `gitlab-experiment` in the [README](https://gitlab.com/gitlab-org/gitlab-experiment/-/blob/master/README.md).
## How to create an A/B test using `experimentation.rb`
### Experiments using the `Experimentation Module`
### Implement the experiment
1. Add the experiment to the `Gitlab::Experimentation::EXPERIMENTS` hash in [`experimentation.rb`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib%2Fgitlab%2Fexperimentation.rb):
1. Add the experiment to the `Gitlab::Experimentation::EXPERIMENTS` hash in the [`Experimentation Module`](https://gitlab.com/gitlab-org/gitlab/blob/master/lib%2Fgitlab%2Fexperimentation.rb):
```ruby
EXPERIMENTS = {
@ -151,13 +169,13 @@ in GitLab that can be used for running experiments.
end
```
### Implement the tracking events
#### Implement the tracking events
To determine whether the experiment is a success or not, we must implement tracking events
to acquire data for analyzing. We can send events to Snowplow via either the backend or frontend.
Read the [product intelligence guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/) for more details.
#### Track backend events
##### Track backend events
The framework provides the following helper method that is available in controllers:
@ -190,7 +208,7 @@ context 'when the experiment is active and the user is in the experimental group
end
```
#### Track frontend events
##### Track frontend events
The framework provides the following helper method that is available in controllers:
@ -273,7 +291,7 @@ describe('event tracking', () => {
});
```
### Record experiment user
#### Record experiment user
In addition to the anonymous tracking of events, we can also record which users have participated in which experiments and whether they were given the control experience or the experimental experience.
@ -289,7 +307,7 @@ Subsequent calls to this method for the same experiment and the same user have n
Note that this data is completely separate from the [events tracking data](#implement-the-tracking-events). They are not linked together in any way.
#### Add context
##### Add context
You can add arbitrary context data in a hash which gets stored as part of the experiment user record. New calls to the `record_experiment_user` with newer contexts get merged deeply into the existing context.
@ -306,7 +324,7 @@ record_experiment_user(:signup_flow, foo: 40, bar: { b: 2 }, thor: 3)
# context becomes { "foo" => 40, "bar" => { "a" => 22, "b" => 2 }, "thor" => 3}
```
### Record experiment conversion event
#### Record experiment conversion event
Along with the tracking of backend and frontend events and the [recording of experiment participants](#record-experiment-user), we can also record when a user performs the desired conversion event action. For example:
@ -323,7 +341,7 @@ end
Note that the use of this method requires that we have first [recorded the user as being part of the experiment](#record-experiment-user).
### Enable the experiment
#### Enable the experiment
After all merge requests have been merged, use [`chatops`](../../ci/chatops/index.md) in the
[appropriate channel](../feature_flags/controls.md#communicate-the-change) to start the experiment for 10% of the users.
@ -340,7 +358,7 @@ For visibility, please also share any commands run against production in the `#s
/chatops run feature delete signup_flow_experiment_percentage
```
### Manually force the current user to be in the experiment group
#### Manually force the current user to be in the experiment group
You may force the application to put your current user in the experiment group. To do so
add a query string parameter to the path where the experiment runs. If you do so,
@ -353,7 +371,7 @@ to the URL:
https://gitlab.com/<EXPERIMENT_ENTRY_URL>?force_experiment=<EXPERIMENT_KEY>
```
### A cookie-based approach to force an experiment
#### A cookie-based approach to force an experiment
It's possible to force the current user to be in the experiment group for `<EXPERIMENT_KEY>`
during the browser session by using your browser's developer tools:
@ -374,9 +392,9 @@ To clear the experiments, unset the `force_experiment` cookie:
document.cookie = "force_experiment=; path=/";
```
### Testing and test helpers
#### Testing and test helpers
#### RSpec
##### RSpec
Use the following in RSpec to mock the experiment:
@ -404,7 +422,7 @@ context 'when the experiment is active' do
end
```
#### Jest
##### Jest
Use the following in Jest to mock the experiment:

View File

@ -161,7 +161,7 @@ unnecessary when using `gl-icon`.
// good - decorative images hidden from screen readers
<img src="decorative.jpg" alt="">
<svg role="img" alt="">
<gl-icon name="epic"/>
<gl-icon name="epic"/>
```
## When should ARIA be used
@ -187,7 +187,7 @@ Use of ARIA would then only occur in [GitLab UI](https://gitlab.com/gitlab-org/g
We have two options for Web accessibility testing:
- [axe](https://www.deque.com/axe/) for [Firefox](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/)
- [axe](https://www.deque.com/axe/) for [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd)
- [axe](https://www.deque.com/axe/) for [Chrome](https://chrome.google.com/webstore/detail/axe-devtools-web-accessib/lhdoppojpmngadmnindnejefpokejbdd)
### Other links

View File

@ -91,7 +91,7 @@ projects:
- Avoid global variables, even in packages. By doing so you introduce side
effects if the package is included multiple times.
- Use `goimports` before committing.
[`goimports`](https://godoc.org/golang.org/x/tools/cmd/goimports)
[`goimports`](https://pkg.go.dev/golang.org/x/tools/cmd/goimports)
is a tool that automatically formats Go source code using
[`Gofmt`](https://golang.org/cmd/gofmt/), in addition to formatting import lines,
adding missing ones and removing unreferenced ones.

View File

@ -22,9 +22,17 @@ You may create a new account or use any of their supported sign in services.
GitLab is being translated into many languages.
1. Select the language you would like to contribute translations to by clicking the flag
1. Find the language that you want to contribute to, in our
[GitLab Crowdin project](https://crowdin.com/project/gitlab-ee).
- If the language that you're looking for is available, proceed
to the next step.
- If the language you are looking for is not available,
[open an issue](https://gitlab.com/gitlab-org/gitlab/-/issues?scope=all&utf8=✓&state=all&label_name[]=Category%3AInternationalization). Notify our Crowdin
administrators by including `@gitlab-org/manage/import` in your issue.
in the issue.
- After the issue/Merge Request is complete, restart this procedure.
1. Next, you can view list of files and folders.
Click `gitlab.pot` to open the translation editor.
Select `gitlab.pot` to open the translation editor.
### Translation Editor

View File

@ -151,7 +151,7 @@ To run the Monitor tests locally, against the GDK, please follow the preparation
1. The test setup deploys the app in a Kubernetes cluster, using the Auto DevOps deployment strategy.
To enable Auto DevOps in GDK, follow the [associated setup](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/auto_devops/index.md#setup) instructions. If you have problems, review the [troubleshooting guide](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/auto_devops/tips_and_troubleshooting.md) or reach out to the `#gdk` channel in the internal GitLab Slack.
1. Do [secure your GitLab instance](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/auto_devops/index.md#secure-your-gitlab-instance) since it is now publicly accessible on `https://[YOUR-PORT].qa-tunnel.gitlab.info`.
1. Install the Kubernetes command line tool known as `kubectl`. Use the [official installation instructions](https://kubernetes.io/docs/tasks/tools/install-kubectl/).
1. Install the Kubernetes command line tool known as `kubectl`. Use the [official installation instructions](https://kubernetes.io/docs/tasks/tools/).
You might see NGINX issues when you run `gdk start` or `gdk restart`. In that case, run `sft login` to revalidate your credentials and regain access the QA Tunnel.

View File

@ -212,7 +212,7 @@ When it comes to querying DOM elements in your tests, it is best to uniquely and
the element.
Preferentially, this is done by targeting what the user actually sees using [DOM Testing Library](https://testing-library.com/docs/dom-testing-library/intro/).
When selecting by text it is best to use [`getByRole` or `findByRole`](https://testing-library.com/docs/queries/byrole)
When selecting by text it is best to use [`getByRole` or `findByRole`](https://testing-library.com/docs/queries/byrole/)
as these enforce accessibility best practices as well. The examples below demonstrate the order of preference.
When writing Vue component unit tests, it can be wise to query children by component, so that the unit test can focus on comprehensive value coverage

View File

@ -112,7 +112,7 @@ Review Apps are automatically stopped 2 days after the last deployment thanks to
the [Environment auto-stop](../../ci/environments/index.md#stop-an-environment-after-a-certain-time-period) feature.
If you need your Review App to stay up for a longer time, you can
[pin its environment](../../ci/environments/index.md#auto-stop-example) or retry the
[pin its environment](../../ci/environments/index.md#override-a-deployments-scheduled-stop-time) or retry the
`review-deploy` job to update the "latest deployed at" time.
The `review-cleanup` job that automatically runs in scheduled

View File

@ -351,7 +351,7 @@ Remember to sign in with the username and password you specified when you
[created your Azure VM](#basics).
If you need to reset your VM password, read
[how to reset SSH credentials for a user on an Azure VM](https://docs.microsoft.com/en-us/azure/virtual-machines/troubleshooting/troubleshoot-ssh-connection).
[how to reset SSH credentials for a user on an Azure VM](https://docs.microsoft.com/en-us/troubleshoot/azure/virtual-machines/troubleshoot-ssh-connection).
#### SSH from the command-line
@ -433,7 +433,7 @@ Check out our other [Technical Articles](../../topics/index.md) or browse the [G
- [Azure - Marketplace](https://azuremarketplace.microsoft.com/en-us/marketplace/)
- [Azure Portal](https://portal.azure.com)
- [Azure - Pricing Calculator](https://azure.microsoft.com/en-us/pricing/calculator/)
- [Azure - Troubleshoot SSH Connections to an Azure Linux VM](https://docs.microsoft.com/en-us/azure/virtual-machines/troubleshooting/troubleshoot-ssh-connection)
- [Azure - Troubleshoot SSH Connections to an Azure Linux VM](https://docs.microsoft.com/en-us/troubleshoot/azure/virtual-machines/troubleshoot-ssh-connection)
- [Azure - Properly Shutdown an Azure VM](https://build5nines.com/properly-shutdown-azure-vm-to-save-money/)
- [SSH](https://en.wikipedia.org/wiki/Secure_Shell), [PuTTY](https://www.putty.org) and [Using SSH in PuTTY](https://mediatemple.net/community/products/dv/204404604/using-ssh-in-putty-)

View File

@ -38,7 +38,7 @@ already, go ahead and install the following components as they are essential to
test OpenShift easily:
- [VirtualBox](https://www.virtualbox.org/wiki/Downloads)
- [Vagrant](https://www.vagrantup.com/downloads.html)
- [Vagrant](https://www.vagrantup.com/downloads)
- [OpenShift Client](https://docs.okd.io/3.11/cli_reference/get_started_cli.html) (`oc` for short)
It is also important to mention that for the purposes of this tutorial, the

View File

@ -79,8 +79,8 @@ is 200. For GitLab SaaS, the maximum number is determined by [tier](https://abou
You can apply a feature flag strategy across multiple environments, without defining
the strategy multiple times.
GitLab Feature Flags use [Unleash](https://docs.getunleash.ai/) as the feature flag
engine. In Unleash, there are [strategies](https://docs.getunleash.ai/docs/activation_strategy)
GitLab Feature Flags use [Unleash](https://docs.getunleash.io/) as the feature flag
engine. In Unleash, there are [strategies](https://docs.getunleash.io/docs/activation_strategy)
for granular feature flag controls. GitLab Feature Flags can have multiple strategies,
and the supported strategies are:
@ -95,7 +95,7 @@ and clicking **{pencil}** (edit).
### All users
Enables the feature for all users. It uses the [`default`](https://docs.getunleash.ai/docs/activation_strategy#default)
Enables the feature for all users. It uses the [`default`](https://docs.getunleash.io/docs/activation_strategy#default)
Unleash activation strategy.
### Percent Rollout

View File

@ -24,6 +24,7 @@ type: index
- [Security of running jobs](https://docs.gitlab.com/runner/security/)
- [Proxying images](asset_proxy.md)
- [CI/CD variables](cicd_variables.md)
- [Token overview](token_overview.md)
## Securing your GitLab installation

View File

@ -0,0 +1,108 @@
---
stage: Manage
group: Access
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
type: reference
---
# GitLab Token overview
This document lists tokens used in GitLab, their purpose and, where applicable, security guidance.
## Personal access tokens
You can create [Personal access tokens](../user/profile/personal_access_tokens.md) to authenticate with:
- The GitLab API.
- GitLab repositories.
- The GitLab registry.
You can limit the scope and expiration date of your personal access tokens. By default,
they inherit permissions from the user who created them.
## OAuth2 tokens
GitLab can serve as an [OAuth2 provider](../api/oauth2.md) to allow other services to access the GitLab API on a users behalf.
You can limit the scope and lifetime of your OAuth2 tokens.
## Impersonation tokens
An [Impersonation token](../api/README.md#impersonation-tokens) is a special type of personal access
token. It can be created only by an administrator for a specific user. Impersonation tokens can
help you build applications or scripts that authenticate with the GitLab API, repositories, and the GitLab registry as a specific user.
You can limit the scope and set an expiration date for an impersonation token.
## Project access tokens
[Project access tokens](../user/project/settings/project_access_tokens.md#project-access-tokens)
are scoped to a project. As with [Personal access tokens](#personal-access-tokens), you can use them to authenticate with:
- The GitLab API.
- GitLab repositories.
- The GitLab registry.
You can limit the scope and expiration date of project access tokens. When you
create a project access token, GitLab creates a [project bot user](../user/project/settings/project_access_tokens.md#project-bot-users). Project
bot users are service accounts and do not count as licensed seats.
## Deploy tokens
[Deploy tokens](../user/project/deploy_tokens/index.md) allow you to download (`git clone`) or push and pull packages and container registry images of a project without having a user and a password. Deploy tokens cannot be used with the GitLab API.
Deploy tokens can be managed by project maintainers and owners.
## Deploy keys
[Deploy keys](../user/project/deploy_keys/index.md) allow read-only or read-write access to your repositories by importing an SSH public key into your GitLab instance. Deploy keys cannot be used with the GitLab API or the registry.
This is useful, for example, for cloning repositories to your Continuous Integration (CI) server. By using deploy keys, you dont have to set up a fake user account.
Project maintainers and owners can add or enable a deploy key for a project repository
## Runner registration tokens
Runner registration tokens are used to [register](https://docs.gitlab.com/runner/register/) a [runner](https://docs.gitlab.com/runner/) with GitLab. Group or project owners or instance admins can obtain them through the GitLab user interface. The registration token is limited to runner registration and has no further scope.
You can use the runner registration token to add runners that execute jobs in a project or group. The runner has access to the projects code, so be careful when assigning project and group-level permissions.
## Runner authentication tokens (also called runner tokens)
After registration, the runner receives an authentication token, which it uses to authenticate with GitLab when picking up jobs from the job queue. The authentication token is stored locally in the runner's [`config.toml`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html) file.
After authentication with GitLab, the runner receives a [job token](../user/project/new_ci_build_permissions_model.md#job-token), which it uses to execute the job.
In case of Docker Machine/Kubernetes/VirtualBox/Parallels/SSH executors, the execution environment has no access to the runner authentication token, because it stays on the runner machine. They have access to the job token only, which is needed to execute the job.
Malicious access to a runner's file system may expose the `config.toml` file and thus the authentication token, allowing an attacker to [clone the runner](https://docs.gitlab.com/runner/security/#cloning-a-runner).
## CI/CD job tokens
The [CI/CD](../api/README.md#gitlab-ci-job-token) job token
is a short lived token only valid for the duration of a job. It gives a CI/CD job
access to a limited amount of [API endpoints](../api/README.md#gitlab-ci-job-token).
API authentication uses the job token, by using the authorization of the user
triggering the job.
The job token is secured by its short life-time and limited scope. It could possibly be leaked if multiple jobs run on the same machine ([like with the shell runner](https://docs.gitlab.com/runner/security/#usage-of-shell-executor)). On Docker Machine runners, configuring [`MaxBuilds=1`](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runnersmachine-section) is recommended to make sure runner machines only ever run one build and are destroyed afterwards. This may impact performance, as provisioning machines takes some time.
## Available scopes
This table shows available scopes per token. Scopes can be limited further on token creation.
| | API access | Registry access | Repository access |
|-----------------------------|------------|-----------------|-------------------|
| Personal access token | ✅ | ✅ | ✅ |
| OAuth2 token | ✅ | 🚫 | ✅ |
| Impersonation token | ✅ | ✅ | ✅ |
| Project access token | ✅(1) | ✅(1) | ✅(1) |
| Deploy token | 🚫 | ✅ | ✅ |
| Deploy key | 🚫 | 🚫 | ✅ |
| Runner registration token | 🚫 | 🚫 | ✴️(2) |
| Runner authentication token | 🚫 | 🚫 | ✴️(2) |
| Job token | ✴️(3) | 🚫 | ✅ |
1. Limited to the one project.
1. Runner registration and authentication token don't provide direct access to repositories, but can be used to register and authenticate a new runner that may execute jobs which do have access to the repository
1. Limited to certain [endpoints](../api/README.md#gitlab-ci-job-token).

View File

@ -321,7 +321,7 @@ simplify configuration and prevent any unforeseen issues.
The GitLab integration with Helm does not support installing applications when
behind a proxy. Users who want to do so must inject their proxy settings
into the installation pods at runtime, such as by using a
[`PodPreset`](https://kubernetes.io/docs/concepts/workloads/pods/podpreset/):
[`PodPreset`](https://v1-19.docs.kubernetes.io/docs/concepts/workloads/pods/podpreset/):
```yaml
apiVersion: settings.k8s.io/v1alpha1

View File

@ -635,7 +635,7 @@ ciliumNetworkPolicy:
#### Enabling Alerts
You can also enable alerts. Network policies with alerts are considered only if
[GitLab Kubernetes Agent](https://docs.gitlab.com/13.6/ee/user/clusters/agent/)
[GitLab Kubernetes Agent](../../user/clusters/agent/index.md)
has been integrated.
You can enable alerts as follows:

View File

@ -27,7 +27,7 @@ involves:
## Prerequisites
1. Install
[`kubectl`](https://kubernetes.io/docs/tasks/tools/install-kubectl/).
[`kubectl`](https://kubernetes.io/docs/tasks/tools/).
1. Ensure that you can access your Kubernetes cluster using `kubectl`.
This varies based on Kubernetes providers.
1. Prepare for downtime. The steps below include taking the application offline

View File

@ -510,7 +510,7 @@ ensure that it can reach your private repository. Here is an example configurati
### Referencing local dependencies using a path in JavaScript projects
The [Retire.js](https://gitlab.com/gitlab-org/security-products/analyzers/retire.js) analyzer
doesn't support dependency references made with [local paths](https://docs.npmjs.com/cli/v6/configuring-npm/package-json#local-paths)
doesn't support dependency references made with [local paths](https://docs.npmjs.com/cli/v6/configuring-npm/package-json/#local-paths)
in the `package.json` of JavaScript projects. The dependency scan outputs the following error for
such references:

View File

@ -93,11 +93,9 @@ The available `agentk` and `kas` versions can be found in
### Install the Kubernetes Agent Server
The GitLab Kubernetes Agent Server (KAS) can be deployed using [Omnibus
GitLab](https://docs.gitlab.com/omnibus/) or the [GitLab
chart](https://gitlab.com/gitlab-org/charts/gitlab). If you don't already have
GitLab installed, please refer to our [installation
documentation](https://docs.gitlab.com/ee/install/README.html).
The GitLab Kubernetes Agent Server (KAS) can be deployed using [Omnibus GitLab](https://docs.gitlab.com/omnibus/) or the
[GitLab chart](https://gitlab.com/gitlab-org/charts/gitlab). If you don't already have
GitLab installed, please refer to our [installation documentation](../../../install/index.md).
NOTE:
GitLab plans to include the KAS on [GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/3834).
@ -469,7 +467,7 @@ The following example projects can help you get started with the Kubernetes Agen
### Deploying GitLab Runner with the Agent
You can use the Kubernetes Agent to
[deploy GitLab Runner in a Kubernetes cluster](http://docs.gitlab.com/runner/install/kubernetes-agent.html).
[deploy GitLab Runner in a Kubernetes cluster](https://docs.gitlab.com/runner/install/kubernetes-agent.html).
## Kubernetes Network Security Alerts

View File

@ -86,10 +86,9 @@ is saved as a [CI job artifact](../../ci/pipelines/job_artifacts.md).
#### Usage in GitLab versions earlier than 13.5
For GitLab versions 13.5 and below, the Ingress, Fluentd, Prometheus,
and Sentry apps are fetched from the central Helm
[stable repository](https://kubernetes-charts.storage.googleapis.com/). This repository
[was deleted](https://github.com/helm/charts#deprecation-timeline)
For GitLab versions 13.5 and earlier, the Ingress, Fluentd, Prometheus, and Sentry
apps were fetched from the central Helm stable repository (`https://kubernetes-charts.storage.googleapis.com/`).
This repository [was deleted](https://github.com/helm/charts#deprecation-timeline)
on November 13, 2020. This causes the installation CI/CD pipeline to
fail. Upgrade to GitLab 13.6, or alternatively, you can
use the following `.gitlab-ci.yml`, which has been tested on GitLab 13.5:

View File

@ -79,7 +79,7 @@ The reported licenses might be incomplete or inaccurate.
| Elixir | [Mix](https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html) |
| C++/C | [Conan](https://conan.io/) |
| Scala | [sbt](https://www.scala-sbt.org/) |
| Rust | [Cargo](https://crates.io/) |
| Rust | [Cargo](https://crates.io) |
| PHP | [Composer](https://getcomposer.org/) |
## Requirements

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

@ -187,7 +187,7 @@ For more information, see our [discussion on providers](#providers).
Your identity provider may have relevant documentation. It may be generic SAML documentation, or specifically targeted for GitLab. Examples:
- [ADFS (Active Directory Federation Services)](https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust)
- [Auth0](https://auth0.com/docs/protocols/saml-configuration-options/configure-auth0-as-saml-identity-provider)
- [Auth0](https://auth0.com/docs/protocols/saml-protocol/configure-auth0-as-saml-identity-provider)
- [Google Workspace](https://support.google.com/a/answer/6087519?hl=en)
- [JumpCloud](https://support.jumpcloud.com/support/s/article/single-sign-on-sso-with-gitlab-2019-08-21-10-36-47)
- [PingOne by Ping Identity](https://docs.pingidentity.com/bundle/pingone/page/xsh1564020480660-1.html)

View File

@ -161,7 +161,7 @@ have FortiToken configured in FortiToken Cloud.
You'll also need a `client_id` and `client_secret` to configure FortiToken Cloud.
To get these, see the `REST API Guide` at
[`Fortinet Document Library`](https://docs.fortinet.com/document/fortitoken-cloud/20.4.d/rest-api).
[`Fortinet Document Library`](https://docs.fortinet.com/document/fortitoken-cloud/latest/rest-api).
First configure FortiToken Cloud in GitLab. On your GitLab server:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Some files were not shown because too many files have changed in this diff Show More