Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-01-11 12:07:18 +00:00
parent e6b6fb6028
commit fc0afaf7da
155 changed files with 961 additions and 344 deletions

View File

@ -633,7 +633,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/api/project_statistics.md @aqualls
/doc/api/project_templates.md @aqualls
/doc/api/project_vulnerabilities.md @aqualls
/doc/api/projects.md @msedlakjakubowski
/doc/api/projects.md @lciutacu
/doc/api/protected_branches.md @aqualls
/doc/api/protected_environments.md @rdickenson
/doc/api/protected_tags.md @aqualls
@ -766,6 +766,7 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
/doc/development/gitaly.md @eread
/doc/development/gitlab_flavored_markdown/ @ashrafkhamis
/doc/development/gitlab_flavored_markdown/specification_guide/ @ashrafkhamis
/doc/development/gitlab_shell/ @aqualls
/doc/development/graphql_guide/ @ashrafkhamis
/doc/development/graphql_guide/batchloader.md @aqualls
/doc/development/i18n/ @eread

View File

@ -11,7 +11,7 @@ import { debounce } from 'lodash';
import axios from '~/lib/utils/axios_utils';
import { backOff } from '~/lib/utils/common_utils';
import csrf from '~/lib/utils/csrf';
import statusCodes from '~/lib/utils/http_status';
import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import { __, s__ } from '~/locale';
import { queryTypes, formDataValidator } from '../constants';
@ -23,7 +23,7 @@ function backOffRequest(makeRequestCallback) {
return backOff((next, stop) => {
makeRequestCallback()
.then((resp) => {
if (resp.status === statusCodes.OK) {
if (resp.status === HTTP_STATUS_OK) {
stop(resp);
} else {
next();

View File

@ -9,7 +9,7 @@ import { createAlert, VARIANT_WARNING } from '~/flash';
import { diffViewerModes } from '~/ide/constants';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes, { HTTP_STATUS_NOT_FOUND } from '~/lib/utils/http_status';
import { HTTP_STATUS_NOT_FOUND, HTTP_STATUS_OK } from '~/lib/utils/http_status';
import Poll from '~/lib/utils/poll';
import { mergeUrlParams, getLocationHash } from '~/lib/utils/url_utility';
import { __, s__ } from '~/locale';
@ -248,7 +248,7 @@ export const fetchCoverageFiles = ({ commit, state }) => {
data: state.endpointCoverage,
method: 'getCoverageReports',
successCallback: ({ status, data }) => {
if (status === httpStatusCodes.OK) {
if (status === HTTP_STATUS_OK) {
commit(types.SET_COVERAGE_DATA, data);
coveragePoll.stop();

View File

@ -1,4 +1,5 @@
export const HTTP_STATUS_ABORTED = 0;
export const HTTP_STATUS_OK = 200;
export const HTTP_STATUS_CREATED = 201;
export const HTTP_STATUS_ACCEPTED = 202;
export const HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION = 203;
@ -28,7 +29,7 @@ const httpStatusCodes = {
};
export const successCodes = [
httpStatusCodes.OK,
HTTP_STATUS_OK,
HTTP_STATUS_CREATED,
HTTP_STATUS_ACCEPTED,
HTTP_STATUS_NON_AUTHORITATIVE_INFORMATION,

View File

@ -1,5 +1,5 @@
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from './http_status';
import { HTTP_STATUS_OK } from './http_status';
import Poll from './poll';
/**
@ -30,7 +30,7 @@ export default (url, config = {}) =>
data: { url, config },
method: 'axiosGet',
successCallback: (response) => {
if (response.status === httpStatusCodes.OK) {
if (response.status === HTTP_STATUS_OK) {
resolve(response);
eTagPoll.stop();
}

View File

@ -1,6 +1,6 @@
import axios from '~/lib/utils/axios_utils';
import { backOff } from '~/lib/utils/common_utils';
import statusCodes, { HTTP_STATUS_ACCEPTED } from '~/lib/utils/http_status';
import { HTTP_STATUS_ACCEPTED, HTTP_STATUS_OK } from '~/lib/utils/http_status';
import { __, s__ } from '~/locale';
import * as types from './mutation_types';
@ -43,7 +43,7 @@ export const requestCreateProject = ({ dispatch, state, commit }) => {
export const requestCreateProjectStatus = ({ dispatch, state }, jobId) => {
backOffRequest(() => axios.get(state.createProjectStatusEndpoint, { params: { job_id: jobId } }))
.then((resp) => {
if (resp.status === statusCodes.OK) {
if (resp.status === HTTP_STATUS_OK) {
dispatch('requestCreateProjectSuccess', resp.data);
}
})
@ -95,7 +95,7 @@ export const requestDeleteProject = ({ dispatch, state, commit }) => {
export const requestDeleteProjectStatus = ({ dispatch, state }, jobId) => {
backOffRequest(() => axios.get(state.deleteProjectStatusEndpoint, { params: { job_id: jobId } }))
.then((resp) => {
if (resp.status === statusCodes.OK) {
if (resp.status === HTTP_STATUS_OK) {
dispatch('requestDeleteProjectSuccess', resp.data);
}
})

View File

@ -6,24 +6,43 @@ export default {
GlIcon,
},
props: {
count: {
type: Number,
required: true,
},
href: {
type: String,
required: false,
default: '',
},
icon: {
type: String,
required: true,
},
count: {
type: Number,
label: {
type: String,
required: true,
},
},
computed: {
ariaLabel() {
return `${this.label} ${this.count}`;
},
component() {
return this.href ? 'a' : 'button';
},
},
};
</script>
<template>
<a
href="#"
<component
:is="component"
:aria-label="ariaLabel"
:href="href"
class="counter gl-relative gl-display-inline-block gl-flex-grow-1 gl-text-center gl-py-3 gl-bg-gray-10 gl-rounded-base gl-text-black-normal gl-border gl-border-gray-a-08 gl-font-sm gl-font-weight-bold"
>
<gl-icon :name="icon" />
{{ count }}
</a>
<gl-icon aria-hidden="true" :name="icon" />
<span aria-hidden="true">{{ count }}</span>
</component>
</template>

View File

@ -1,6 +1,6 @@
<script>
import { GlCollapse } from '@gitlab/ui';
import { user, counts, context } from '../mock_data';
import { context } from '../mock_data';
import UserBar from './user_bar.vue';
import ContextSwitcherToggle from './context_switcher_toggle.vue';
import ContextSwitcher from './context_switcher.vue';
@ -8,8 +8,6 @@ import BottomBar from './bottom_bar.vue';
export default {
context,
user,
counts,
components: {
GlCollapse,
UserBar,
@ -17,6 +15,12 @@ export default {
ContextSwitcher,
BottomBar,
},
props: {
sidebarData: {
type: Object,
required: true,
},
},
data() {
return {
contextSwitcherOpened: false,
@ -30,7 +34,7 @@ export default {
class="super-sidebar gl-fixed gl-bottom-0 gl-left-0 gl-display-flex gl-flex-direction-column gl-bg-gray-10 gl-border-r gl-border-gray-a-08 gl-z-index-9999"
data-testid="super-sidebar"
>
<user-bar :user="$options.user" :counts="$options.counts" />
<user-bar :sidebar-data="sidebarData" />
<div class="gl-display-flex gl-flex-direction-column gl-flex-grow-1 gl-overflow-hidden">
<div class="gl-flex-grow-1 gl-overflow-auto">
<context-switcher-toggle :context="$options.context" :expanded="contextSwitcherOpened" />

View File

@ -1,5 +1,6 @@
<script>
import { GlAvatar, GlDropdown, GlIcon } from '@gitlab/ui';
import { __ } from '~/locale';
import SafeHtml from '~/vue_shared/directives/safe_html';
import NewNavToggle from '~/nav/components/new_nav_toggle.vue';
import logo from '../../../../views/shared/_logo.svg';
@ -14,16 +15,17 @@ export default {
NewNavToggle,
Counter,
},
i18n: {
issues: __('Issues'),
mergeRequests: __('Merge requests'),
todoList: __('To-Do list'),
},
directives: {
SafeHtml,
},
inject: ['rootPath', 'toggleNewNavEndpoint'],
props: {
user: {
type: Object,
required: true,
},
counts: {
sidebarData: {
type: Object,
required: true,
},
@ -47,15 +49,29 @@ export default {
</button>
<gl-dropdown data-testid="user-dropdown" variant="link" no-caret>
<template #button-content>
<gl-avatar :entity-name="user.name" :src="user.avatar_url" :size="32" />
<gl-avatar :entity-name="sidebarData.name" :src="sidebarData.avatar_url" :size="32" />
</template>
<new-nav-toggle :endpoint="toggleNewNavEndpoint" enabled />
</gl-dropdown>
</div>
<div class="gl-display-flex gl-justify-content-space-between gl-px-3 gl-py-2 gl-gap-2">
<counter icon="issues" :count="counts.assigned_issues" />
<counter icon="merge-request-open" :count="counts.assigned_merge_requests" />
<counter icon="todo-done" :count="counts.pending_todos" />
<counter
icon="issues"
:count="sidebarData.assigned_open_issues_count"
:href="sidebarData.issues_dashboard_path"
:label="$options.i18n.issues"
/>
<counter
icon="merge-request-open"
:count="sidebarData.assigned_open_merge_requests_count"
:label="$options.i18n.mergeRequests"
/>
<counter
icon="todo-done"
:count="sidebarData.todos_pending_count"
href="/dashboard/todos"
:label="$options.i18n.todoList"
/>
</div>
</div>
</template>

View File

@ -1,16 +1,5 @@
import { s__ } from '~/locale';
export const user = {
name: 'GitLab Bot',
avatar_url: '',
};
export const counts = {
assigned_issues: 0,
assigned_merge_requests: 4,
pending_todos: 12,
};
export const context = {
title: 'Typeahead.js',
link: '/',

View File

@ -6,7 +6,7 @@ export const initSuperSidebar = () => {
if (!el) return false;
const { rootPath, toggleNewNavEndpoint } = el.dataset;
const { rootPath, sidebar, toggleNewNavEndpoint } = el.dataset;
return new Vue({
el,
@ -16,7 +16,11 @@ export const initSuperSidebar = () => {
toggleNewNavEndpoint,
},
render(h) {
return h(SuperSidebar);
return h(SuperSidebar, {
props: {
sidebarData: JSON.parse(sidebar),
},
});
},
});
};

View File

@ -1,6 +1,6 @@
import Visibility from 'visibilityjs';
import axios from '~/lib/utils/axios_utils';
import httpStatusCodes from '~/lib/utils/http_status';
import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
import Poll from '~/lib/utils/poll';
import * as types from './mutation_types';
@ -63,7 +63,7 @@ export const fetchArtifacts = ({ state, dispatch }) => {
export const receiveArtifactsSuccess = ({ commit }, response) => {
// With 204 we keep polling and don't update the state
if (response.status === httpStatusCodes.OK) {
if (response.status === HTTP_STATUS_OK) {
commit(types.RECEIVE_ARTIFACTS_SUCCESS, response.data);
}
};

View File

@ -22,7 +22,10 @@ class Projects::ProtectedRefsController < Projects::ApplicationController
flash[:alert] = protected_ref.errors.full_messages.join(', ').html_safe
end
redirect_to_repository_settings(@project, anchor: params[:update_section])
respond_to do |format|
format.html { redirect_to_repository_settings(@project, anchor: params[:update_section]) }
format.json { head :ok }
end
end
def show

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
module ProtectedBranchesHelper
def protected_branch_can_admin_entity?(protected_branch_entity)
if protected_branch_entity.is_a?(Group)
can?(current_user, :admin_group, protected_branch_entity)
else
can?(current_user, :admin_project, protected_branch_entity)
end
end
def protected_branch_path_by_entity(protected_branch, protected_branch_entity)
if protected_branch_entity.is_a?(Group)
group_protected_branch_path(protected_branch_entity, protected_branch)
else
project_protected_branch_path(protected_branch_entity, protected_branch)
end
end
end

View File

@ -31,6 +31,18 @@ module SidebarsHelper
Sidebars::Groups::Context.new(**context_data)
end
def super_sidebar_context(user)
{
name: user.name,
username: user.username,
avatar_url: user.avatar_url,
assigned_open_issues_count: user.assigned_open_issues_count,
assigned_open_merge_requests_count: user.assigned_open_merge_requests_count,
todos_pending_count: user.todos_pending_count,
issues_dashboard_path: issues_dashboard_path(assignee_username: user.username)
}
end
private
def sidebar_attributes_for_object(object)

View File

@ -104,6 +104,10 @@ class ProtectedBranch < ApplicationRecord
name == project.default_branch
end
def entity
group || project
end
private
def validate_either_project_or_top_group
@ -111,7 +115,7 @@ class ProtectedBranch < ApplicationRecord
errors.add(:base, _('must be associated with a Group or a Project'))
elsif project && group
errors.add(:base, _('cannot be associated with both a Group and a Project'))
elsif group && group.root_ancestor != group
elsif group && group.subgroup?
errors.add(:base, _('cannot be associated with a subgroup'))
end
end

View File

@ -1,6 +1,7 @@
# frozen_string_literal: true
class ProtectedBranch::MergeAccessLevel < ApplicationRecord
include Importable
include ProtectedBranchAccess
# default value for the access_level column
GITLAB_DEFAULT_ACCESS_LEVEL = Gitlab::Access::MAINTAINER

View File

@ -1,6 +1,7 @@
# frozen_string_literal: true
class ProtectedBranch::PushAccessLevel < ApplicationRecord
include Importable
include ProtectedBranchAccess
# default value for the access_level column
GITLAB_DEFAULT_ACCESS_LEVEL = Gitlab::Access::MAINTAINER

View File

@ -1,6 +1,7 @@
# frozen_string_literal: true
class ProtectedTag::CreateAccessLevel < ApplicationRecord
include Importable
include ProtectedTagAccess
def check_access(user)

View File

@ -157,6 +157,13 @@ module Ci
duration >= LOG_MAX_CREATION_THRESHOLD
end
l.log_when do |observations|
pipeline_includes_count = observations['pipeline_includes_count']
next false unless pipeline_includes_count
pipeline_includes_count.to_i > Gitlab::Ci::Config::External::Context::MAX_INCLUDES
end
end
end
end

View File

@ -18,7 +18,7 @@ module Environments
)
end
ServiceResponse.success(message: 'Successfully scheduled stale environments to stop')
ServiceResponse.success(message: 'Successfully requested stop for all stale environments')
end
end
end

View File

@ -32,4 +32,4 @@
- kroki_available_formats.each do |format|
= f.gitlab_ui_checkbox_component format[:name], format[:label]
= f.submit _('Save changes'), class: "btn gl-button btn-confirm"
= f.submit _('Save changes'), pajamas_button: true

View File

@ -135,7 +135,7 @@
- c.header do
= s_('ProjectSettings|Transfer project')
- c.body do
= form_for @project, url: transfer_admin_project_path(@project), method: :put do |f|
= gitlab_ui_form_for @project, url: transfer_admin_project_path(@project), method: :put do |f|
.form-group.row
.col-sm-3.col-form-label
= f.label :new_namespace_id, _("Namespace")
@ -147,13 +147,13 @@
.form-group.row
.offset-sm-3.col-sm-9
= f.submit _('Transfer'), class: 'gl-button btn btn-confirm'
= f.submit _('Transfer'), pajamas_button: true
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5 repository-check' }) do |c|
- c.header do
= _("Repository check")
- c.body do
= form_for @project, url: repository_check_admin_project_path(@project), method: :post do |f|
= gitlab_ui_form_for @project, url: repository_check_admin_project_path(@project), method: :post do |f|
.form-group
- if @project.last_repository_check_at.nil?
= _("This repository has never been checked.")
@ -167,7 +167,7 @@
= link_to sprite_icon('question-o'), help_page_path('administration/repository_checks')
.form-group
= f.submit _('Trigger repository check'), class: 'gl-button btn btn-confirm'
= f.submit _('Trigger repository check'), pajamas_button: true
.col-md-6
- if @group

View File

@ -3,7 +3,7 @@
.login-box.gl-p-5
.login-body
- if @user.two_factor_otp_enabled?
= form_for(resource, as: resource_name, url: session_path(resource_name), method: :post, html: { class: "edit_user gl-show-field-errors js-2fa-form #{'hidden' if @user.two_factor_webauthn_u2f_enabled?}" }) do |f|
= gitlab_ui_form_for(resource, as: resource_name, url: session_path(resource_name), method: :post, html: { class: "edit_user gl-show-field-errors js-2fa-form #{'hidden' if @user.two_factor_webauthn_u2f_enabled?}" }) do |f|
- resource_params = params[resource_name].presence || params
= f.hidden_field :remember_me, value: resource_params.fetch(:remember_me, 0)
%div
@ -11,6 +11,6 @@
= f.text_field :otp_attempt, class: 'form-control gl-form-input', required: true, autofocus: true, autocomplete: 'off', title: _('This field is required.'), data: { qa_selector: 'two_fa_code_field' }
%p.form-text.text-muted.hint= _("Enter the code from the two-factor app on your mobile device. If you've lost your device, you may enter one of your recovery codes.")
.prepend-top-20
= f.submit _("Verify code"), class: "gl-button btn btn-confirm", data: { qa_selector: 'verify_code_button' }
= f.submit _("Verify code"), pajamas_button: true, data: { qa_selector: 'verify_code_button' }
- if @user.two_factor_webauthn_u2f_enabled?
= render "authentication/authenticate", params: params, resource: resource, resource_name: resource_name, render_remember_me: true, target_path: new_user_session_path

View File

@ -6,7 +6,7 @@
- if show_omniauth_providers && omniauth_providers_placement == :top
= render 'devise/shared/signup_omniauth_providers_top'
= form_for(resource, as: "new_#{resource_name}", url: url, html: { class: 'new_user gl-show-field-errors js-arkose-labs-form', 'aria-live' => 'assertive' }, data: { testid: 'signup-form' }) do |f|
= gitlab_ui_form_for(resource, as: "new_#{resource_name}", url: url, html: { class: 'new_user gl-show-field-errors js-arkose-labs-form', 'aria-live' => 'assertive' }, data: { testid: 'signup-form' }) do |f|
.devise-errors
= render 'devise/shared/error_messages', resource: resource
- if Gitlab::CurrentSettings.invisible_captcha_enabled
@ -72,7 +72,7 @@
= recaptcha_tags nonce: content_security_policy_nonce
.submit-container.gl-mt-5
= f.submit button_text, class: 'btn gl-button btn-confirm gl-display-block gl-w-full', data: { qa_selector: 'new_user_register_button' }
= f.submit button_text, pajamas_button: true, class: 'gl-w-full', data: { qa_selector: 'new_user_register_button' }
- if Gitlab::CurrentSettings.sign_in_text.present? && Feature.enabled?(:restyle_login_page, @project)
.gl-pt-5
= markdown_field(Gitlab::CurrentSettings.current_application_settings, :sign_in_text)

View File

@ -8,5 +8,7 @@
= render "shared/deploy_tokens/index", group_or_project: @group, description: deploy_token_description
= render "default_branch", group: @group
= render_if_exists "protected_branches/protected_branches", protected_branch_entity: @group
- if can?(current_user, :change_push_rules, @group)
= render "push_rules"

View File

@ -2,7 +2,8 @@
- @left_sidebar = true
.layout-page.hide-when-top-nav-responsive-open{ class: page_with_sidebar_class }
- if show_super_sidebar?
%aside.js-super-sidebar.nav-sidebar{ data: { root_path: root_path, toggle_new_nav_endpoint: profile_preferences_url } }
- sidebar_data = super_sidebar_context(current_user).to_json
%aside.js-super-sidebar.nav-sidebar{ data: { root_path: root_path, sidebar: sidebar_data, toggle_new_nav_endpoint: profile_preferences_url } }
- elsif defined?(nav) && nav
= render "layouts/nav/sidebar/#{nav}"
.content-wrapper.content-wrapper-margin{ class: "#{@content_wrapper_class}" }

View File

@ -16,4 +16,4 @@
= render 'shared/import_form', f: f
.form-actions
= f.submit 'Start import', class: 'gl-button btn btn-confirm', data: { disable_with: false }
= f.submit 'Start import', pajamas_button: true, data: { disable_with: false }

View File

@ -1,2 +1,2 @@
= render "protected_branches/index"
= render "protected_branches/index", protected_branch_entity: protected_branch_entity
= render "projects/protected_tags/index"

View File

@ -13,7 +13,7 @@
-# The shared parts of the views can be found in the `shared` directory.
-# Those are used throughout the actual views. These `shared` views are then
-# reused in EE.
= render "projects/settings/repository/protected_branches"
= render "projects/settings/repository/protected_branches", protected_branch_entity: @project
= render "shared/deploy_tokens/index", group_or_project: @project, description: deploy_token_description
= render @deploy_keys
= render "projects/cleanup/show"

View File

@ -1,4 +1,4 @@
- can_admin_project = can?(current_user, :admin_project, @project)
- can_admin_entity = protected_branch_can_admin_entity?(protected_branch_entity)
= render layout: 'protected_branches/shared/branches_list', locals: { can_admin_project: can_admin_project } do
= render partial: 'protected_branches/protected_branch', collection: @protected_branches
= render layout: 'protected_branches/shared/branches_list', locals: { can_admin_entity: can_admin_entity, protected_branch_entity: protected_branch_entity } do
= render partial: 'protected_branches/protected_branch', collection: @protected_branches, locals: { protected_branch_entity: protected_branch_entity }

View File

@ -11,4 +11,4 @@
dropdown_class: 'dropdown-menu-selectable capitalize-header', dropdown_qa_selector: 'allowed_to_push_dropdown_content' , dropdown_testid: 'allowed-to-push-dropdown',
data: { field_name: 'protected_branch[push_access_levels_attributes][0][access_level]', input_id: 'push_access_levels_attributes', qa_selector: 'allowed_to_push_dropdown' }})
= render 'protected_branches/shared/create_protected_branch'
= render 'protected_branches/shared/create_protected_branch', protected_branch_entity: protected_branch_entity

View File

@ -1,7 +1,7 @@
- content_for :create_protected_branch do
= render 'protected_branches/create_protected_branch'
= render 'protected_branches/create_protected_branch', protected_branch_entity: protected_branch_entity
- content_for :branches_list do
= render "protected_branches/branches_list"
= render "protected_branches/branches_list", protected_branch_entity: protected_branch_entity
= render 'protected_branches/shared/index'
= render 'protected_branches/shared/index', protected_branch_entity: protected_branch_entity

View File

@ -1,2 +1,2 @@
= render layout: 'protected_branches/shared/protected_branch', locals: { protected_branch: protected_branch } do
= render layout: 'protected_branches/shared/protected_branch', locals: { protected_branch: protected_branch, protected_branch_entity: protected_branch_entity } do
= render_if_exists 'protected_branches/update_protected_branch', protected_branch: protected_branch

View File

@ -13,7 +13,7 @@
%col{ width: "20%" }
%col{ width: "10%" }
%col{ width: "10%" }
- if can_admin_project
- if can_admin_entity
%col
%thead
%tr
@ -28,9 +28,9 @@
%span.has-tooltip{ data: { container: 'body' }, title: s_('ProtectedBranch|Allow all users with push access to force push.'), 'aria-hidden': 'true' }
= sprite_icon('question', size: 16, css_class: 'gl-text-gray-500')
= render_if_exists 'protected_branches/ee/code_owner_approval_table_head'
= render_if_exists 'protected_branches/ee/code_owner_approval_table_head', protected_branch_entity: protected_branch_entity
- if can_admin_project
- if can_admin_entity
%th
%tbody
= yield

View File

@ -1,4 +1,4 @@
= gitlab_ui_form_for [@project, @protected_branch], html: { class: 'new-protected-branch js-new-protected-branch' } do |f|
= gitlab_ui_form_for [protected_branch_entity, @protected_branch], html: { class: 'new-protected-branch js-new-protected-branch' } do |f|
%input{ type: 'hidden', name: 'update_section', value: 'js-protected-branches-settings' }
= render Pajamas::CardComponent.new(card_options: { class: "gl-mb-5" }) do |c|
- c.header do
@ -8,11 +8,18 @@
.form-group.row
= f.label :name, s_('ProtectedBranch|Branch:'), class: 'col-sm-12'
.col-sm-12
= render partial: "protected_branches/shared/dropdown", locals: { f: f, toggle_classes: 'gl-w-full! gl-form-input-lg' }
- if protected_branch_entity.is_a?(Group)
= f.text_field :name, placeholder: 'prod*', class: 'form-control gl-w-full! gl-form-input-lg'
- else
= render partial: "protected_branches/shared/dropdown", locals: { f: f, toggle_classes: 'gl-w-full! gl-form-input-lg' }
.form-text.text-muted
- wildcards_url = help_page_url('user/project/protected_branches', anchor: 'configure-multiple-protected-branches-by-using-a-wildcard')
- wildcards_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: wildcards_url }
= (s_("ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported.") % { wildcards_link_start: wildcards_link_start, wildcards_link_end: '</a>', code_tag_start: '<code>', code_tag_end: '</code>' }).html_safe
- placeholders = { wildcards_link_start: wildcards_link_start, wildcards_link_end: '</a>', code_tag_start: '<code>', code_tag_end: '</code>' }
- if protected_branch_entity.is_a?(Group)
= (s_("ProtectedBranch|Only %{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported.") % placeholders).html_safe
- else
= (s_("ProtectedBranch|%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}*-stable%{code_tag_end} or %{code_tag_start}production/*%{code_tag_end} are supported.") % placeholders).html_safe
.form-group.row
= f.label :merge_access_levels_attributes, s_("ProtectedBranch|Allowed to merge:"), class: 'col-sm-12'
.col-sm-12
@ -30,6 +37,6 @@
- force_push_docs_url = help_page_url('topics/git/git_rebase', anchor: 'force-push')
- force_push_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: force_push_docs_url }
= (s_("ProtectedBranch|Allow all users with push access to %{tag_start}force push%{tag_end}.") % { tag_start: force_push_link_start, tag_end: '</a>' }).html_safe
= render_if_exists 'protected_branches/ee/code_owner_approval_form', f: f
= render_if_exists 'protected_branches/ee/code_owner_approval_form', f: f, protected_branch_entity: protected_branch_entity
- c.footer do
= f.submit s_('ProtectedBranch|Protect'), disabled: true, data: { qa_selector: 'protect_button' }, pajamas_button: true

View File

@ -1,3 +1,4 @@
- can_admin_entity = protected_branch_can_admin_entity?(protected_branch_entity)
- expanded = expanded_by_default?
%section.settings.no-animate#js-protected-branches-settings{ class: ('expanded' if expanded), data: { qa_selector: 'protected_branches_settings_content' } }
@ -14,7 +15,7 @@
= s_("ProtectedBranch|By default, protected branches restrict who can modify the branch.")
= link_to s_("ProtectedBranch|Learn more."), help_page_path("user/project/protected_branches", anchor: "who-can-modify-a-protected-branch")
- if can? current_user, :admin_project, @project
- if can_admin_entity
= content_for :create_protected_branch
= content_for :branches_list

View File

@ -1,23 +1,25 @@
- can_admin_project = can?(current_user, :admin_project, @project)
- can_admin_entity = protected_branch_can_admin_entity?(protected_branch_entity)
- url = protected_branch_path_by_entity(protected_branch, protected_branch_entity)
%tr.js-protected-branch-edit-form{ data: { url: namespace_project_protected_branch_path(@project.namespace, @project, protected_branch), testid: 'protected-branch' } }
%tr.js-protected-branch-edit-form{ data: { url: url, testid: 'protected-branch' } }
%td
%span.ref-name= protected_branch.name
- if @project.root_ref?(protected_branch.name)
- if protected_branch_entity.is_a?(Project) && protected_branch_entity.root_ref?(protected_branch.name)
= gl_badge_tag s_('ProtectedBranch|default'), variant: :info
%div
- if protected_branch.wildcard?
- matching_branches = protected_branch.matching(repository.branch_names)
= link_to pluralize(matching_branches.count, "matching branch"), namespace_project_protected_branch_path(@project.namespace, @project, protected_branch)
- elsif !protected_branch.commit
%span.text-muted Branch was deleted.
- if protected_branch_entity.is_a?(Project)
%div
- if protected_branch.wildcard?
- matching_branches = protected_branch.matching(repository.branch_names)
= link_to pluralize(matching_branches.count, "matching branch"), namespace_project_protected_branch_path(@project.namespace, @project, protected_branch)
- elsif !protected_branch.commit
%span.text-muted= s_('ProtectedBranch|Branch does not exist.')
= yield
= render_if_exists 'protected_branches/ee/code_owner_approval_table', protected_branch: protected_branch
= render_if_exists 'protected_branches/ee/code_owner_approval_table', protected_branch: protected_branch, protected_branch_entity: protected_branch_entity
- if can_admin_project
- if can_admin_entity
%td
= link_to s_('ProtectedBranch|Unprotect'), [@project, protected_branch, { update_section: 'js-protected-branches-settings' }], disabled: local_assigns[:disabled], aria: { label: s_('ProtectedBranch|Unprotect branch') }, data: { confirm: s_('ProtectedBranch|Branch will be writable for developers. Are you sure?'), confirm_btn_variant: 'danger' }, method: :delete, class: "btn gl-button btn-danger btn-sm"
= link_to s_('ProtectedBranch|Unprotect'), [protected_branch_entity, protected_branch, { update_section: 'js-protected-branches-settings' }], disabled: local_assigns[:disabled], aria: { label: s_('ProtectedBranch|Unprotect branch') }, data: { confirm: s_('ProtectedBranch|Branch will be writable for developers. Are you sure?'), confirm_btn_variant: 'danger' }, method: :delete, class: "btn gl-button btn-danger btn-sm"

View File

@ -6,19 +6,52 @@ class PipelineScheduleWorker # rubocop:disable Scalability/IdempotentWorker
data_consistency :always
include CronjobQueue
include ::Gitlab::ExclusiveLeaseHelpers
LOCK_RETRY = 3
LOCK_TTL = 5.minutes
feature_category :continuous_integration
worker_resource_boundary :cpu
def perform
Ci::PipelineSchedule.runnable_schedules.preloaded.find_in_batches do |schedules|
schedules.each do |schedule|
next unless schedule.project
if Feature.enabled?(:ci_use_run_pipeline_schedule_worker)
in_lock(lock_key, **lock_params) do
Ci::PipelineSchedule
.select(:id, :owner_id, :project_id) # Minimize the selected columns
.runnable_schedules
.preloaded
.find_in_batches do |schedules|
RunPipelineScheduleWorker.bulk_perform_async_with_contexts(
schedules,
arguments_proc: ->(schedule) { [schedule.id, schedule.owner_id] },
context_proc: ->(schedule) { { project: schedule.project, user: schedule.owner } }
)
end
end
else
Ci::PipelineSchedule.runnable_schedules.preloaded.find_in_batches do |schedules|
schedules.each do |schedule|
next unless schedule.project
with_context(project: schedule.project, user: schedule.owner) do
Ci::PipelineScheduleService.new(schedule.project, schedule.owner).execute(schedule)
with_context(project: schedule.project, user: schedule.owner) do
Ci::PipelineScheduleService.new(schedule.project, schedule.owner).execute(schedule)
end
end
end
end
end
private
def lock_key
self.class.name.underscore
end
def lock_params
{
ttl: LOCK_TTL,
retries: LOCK_RETRY
}
end
end

View File

@ -19,6 +19,12 @@ class RunPipelineScheduleWorker # rubocop:disable Scalability/IdempotentWorker
return unless schedule && schedule.project && user
if Feature.enabled?(:ci_use_run_pipeline_schedule_worker)
return if schedule.next_run_at > Time.current
update_next_run_at_for(schedule)
end
run_pipeline_schedule(schedule, user)
end
@ -37,6 +43,12 @@ class RunPipelineScheduleWorker # rubocop:disable Scalability/IdempotentWorker
private
def update_next_run_at_for(schedule)
# Ensure `next_run_at` is set properly before creating a pipeline.
# Otherwise, multiple pipelines could be created in a short interval.
schedule.schedule_next_run!
end
def error(schedule, error)
failed_creation_counter.increment
log_error(schedule, error)

View File

@ -0,0 +1,8 @@
---
name: ci_use_run_pipeline_schedule_worker
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106661
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/378361
milestone: '15.8'
type: development
group: group::pipeline execution
default_enabled: false

View File

@ -0,0 +1,18 @@
# frozen_string_literal: true
class AddQueryIndexForCiPipelineSchedules < Gitlab::Database::Migration[2.1]
TABLE_NAME = :ci_pipeline_schedules
INDEX_NAME = :index_ci_pipeline_schedules_on_id_and_next_run_at_and_active
COLUMNS = %i[id next_run_at].freeze
INDEX_CONDITION = 'active = TRUE'
disable_ddl_transaction!
def up
add_concurrent_index(TABLE_NAME, COLUMNS, name: INDEX_NAME, where: INDEX_CONDITION)
end
def down
remove_concurrent_index(TABLE_NAME, COLUMNS, name: INDEX_NAME)
end
end

View File

@ -0,0 +1 @@
43f0493091c58f1573613d5672a999bf07994ced2b7172a7aef9148f4d8b8dbe

View File

@ -28907,6 +28907,8 @@ CREATE INDEX index_ci_pipeline_metadata_on_project_id ON ci_pipeline_metadata US
CREATE UNIQUE INDEX index_ci_pipeline_schedule_variables_on_schedule_id_and_key ON ci_pipeline_schedule_variables USING btree (pipeline_schedule_id, key);
CREATE INDEX index_ci_pipeline_schedules_on_id_and_next_run_at_and_active ON ci_pipeline_schedules USING btree (id, next_run_at) WHERE (active = true);
CREATE INDEX index_ci_pipeline_schedules_on_next_run_at_and_active ON ci_pipeline_schedules USING btree (next_run_at, active);
CREATE INDEX index_ci_pipeline_schedules_on_owner_id ON ci_pipeline_schedules USING btree (owner_id);

View File

@ -412,3 +412,28 @@ Example response:
"updated_at": "2019-05-27T18:55:13.252Z"
}
```
## Stop stale environments
Issue stop request to all environments that were last modified or deployed to before a specified date. Excludes protected environments. Returns `200` if stop request was successful and `400` if the before date is invalid. For details of exactly when the environment is stopped, see [Stop an environment](../ci/environments/index.md#stop-an-environment).
```plaintext
POST /projects/:id/environments/stop_stale
```
| Attribute | Type | Required | Description |
|-----------|----------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `before` | date | yes | Stop environments that have been modified or deployed to before the specified date. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). Valid inputs are between 10 years ago and 1 week ago |
```shell
curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/environments/stop_stale?before=10%2F10%2F2021"
```
Example response:
```json
{
"message": "Successfully requested stop for all stale environments"
}
```

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -436,6 +436,8 @@ There are multiple ways to clean up [dynamic environments](#create-a-dynamic-env
- If you do _NOT_ use [merge request pipelines](../pipelines/merge_request_pipelines.md), GitLab stops an environment [when the associated feature branch is deleted](#stop-an-environment-when-a-branch-is-deleted).
- If you set [an expiry period to an environment](../yaml/index.md#environmentauto_stop_in), GitLab stops an environment [when it's expired](#stop-an-environment-after-a-certain-time-period).
To stop stale environments, you can [use the API](../../api/environments.md#stop-stale-environments).
#### Stop an environment when a branch is deleted
You can configure environments to stop when a branch is deleted.

View File

@ -4,7 +4,7 @@ group: Code Review
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Approval Rules development guide **(FREE)**
# Approval Rules development guide
This document explains the backend design and flow of all related functionality
about [merge request approval rules](../user/project/merge_requests/approvals/index.md).

View File

@ -4,7 +4,7 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Auto DevOps development guide **(FREE)**
# Auto DevOps development guide
This document provides a development guide for contributors to
[Auto DevOps](../topics/autodevops/index.md).

View File

@ -4,7 +4,7 @@ group: Pipeline Authoring
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Documenting the `.gitlab-ci.yml` keywords **(FREE)**
# Documenting the `.gitlab-ci.yml` keywords
The [CI/CD YAML reference](../../ci/yaml/index.md) uses a standard style to make it easier to use and update.

View File

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: index, concepts, howto
---
# CI/CD development documentation **(FREE)**
# CI/CD development documentation
Development guides that are specific to CI/CD are listed here:

View File

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: index, howto
---
# Contribute to the CI/CD Schema **(FREE)**
# Contribute to the CI/CD Schema
The [pipeline editor](../../ci/pipeline_editor/index.md) uses a CI/CD schema to enhance
the authoring experience of our CI/CD configuration files. With the CI/CD schema, the editor can:

View File

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: index, concepts, howto
---
# Development guide for GitLab CI/CD templates **(FREE)**
# Development guide for GitLab CI/CD templates
This document explains how to develop [GitLab CI/CD templates](../../ci/examples/index.md#cicd-templates).

View File

@ -4,7 +4,7 @@ group: Code Review
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Code Intelligence **(FREE)**
# Code Intelligence
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/1576) in GitLab 13.1.

View File

@ -4,7 +4,7 @@ group: Respond
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Distributed Tracing - development guidelines **(FREE)**
# Distributed Tracing - development guidelines
GitLab is instrumented for distributed tracing. Distributed Tracing in GitLab is currently considered **experimental**, as it has not yet been tested at scale on GitLab.com.

View File

@ -4,7 +4,7 @@ group: Global Search
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Elasticsearch knowledge **(PREMIUM SELF)**
# Elasticsearch knowledge
This area is to maintain a compendium of useful information when working with Elasticsearch.

View File

@ -4,7 +4,7 @@ group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Content Editor development guidelines **(FREE)**
# Content Editor development guidelines
The Content Editor is a UI component that provides a WYSIWYG editing
experience for [GitLab Flavored Markdown](../../user/markdown.md) in the GitLab application.

View File

@ -4,7 +4,7 @@ group: Product Analytics
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Customizable dashboards **(PREMIUM)**
# Customizable dashboards
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98610) in GitLab 15.5 as an [Alpha feature](../../policy/alpha-beta-support.md#alpha-features).

View File

@ -4,7 +4,7 @@ group: Code Review
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Merge request widget extensions **(FREE)**
# Merge request widget extensions
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44616) in GitLab 13.6.

View File

@ -4,7 +4,7 @@ group: Editor
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Source Editor **(FREE)**
# Source Editor
**Source Editor** provides the editing experience at GitLab. This thin wrapper around
[the Monaco editor](https://microsoft.github.io/monaco-editor/) provides necessary

View File

@ -4,7 +4,7 @@ group: Geo
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Geo (development) **(PREMIUM SELF)**
# Geo (development)
Geo connects GitLab instances together. One GitLab instance is
designated as a **primary** site and can be run with multiple

View File

@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
<!-- vale gitlab.GitLabFlavoredMarkdown = NO -->
# GitLab Flavored Markdown (GLFM) developer documentation **(FREE)**
# GitLab Flavored Markdown (GLFM) developer documentation
This page contains the MVC for the developer documentation for GitLab Flavored Markdown (GLFM).
For the user documentation about Markdown in GitLab, refer to

View File

@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
<!-- vale gitlab.GitLabFlavoredMarkdown = NO -->
# GitLab Flavored Markdown (GLFM) Specification Guide **(FREE)**
# GitLab Flavored Markdown (GLFM) Specification Guide
## Summary

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
description: "GitLab's development guidelines for Integrations"
---
# Integrations development guide **(FREE)**
# Integrations development guide
This page provides development guidelines for implementing [GitLab integrations](../../user/project/integrations/index.md),
which are part of our [main Rails project](https://gitlab.com/gitlab-org/gitlab).

View File

@ -4,7 +4,7 @@ group: Integrations
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# How to run Jenkins in development environment (on macOS) **(FREE)**
# How to run Jenkins in development environment (on macOS)
This is a step by step guide on how to set up [Jenkins](https://www.jenkins.io/) on your local machine and connect to it from your GitLab instance. GitLab triggers webhooks on Jenkins, and Jenkins connects to GitLab using the API. By running both applications on the same machine, we can make sure they are able to access each other.

View File

@ -4,7 +4,7 @@ group: Integrations
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Set up a development environment **(FREE)**
# Set up a development environment
The following are required to install and test the app:

View File

@ -5,7 +5,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, api
---
# Internal API **(FREE)**
# Internal API
The internal API is used by different GitLab components, it cannot be
used by other consumers. This documentation is intended for people

View File

@ -4,7 +4,7 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Kubernetes integration - development guidelines **(FREE)**
# Kubernetes integration - development guidelines
This document provides various guidelines when developing for the GitLab
[Kubernetes integration](../user/infrastructure/clusters/index.md).

View File

@ -4,7 +4,7 @@ group: Source Code
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Git LFS developer information **(FREE)**
# Git LFS developer information
This page contains developer-centric information for GitLab team members. For the
user documentation, see [Git Large File Storage](../topics/git/lfs/index.md).

View File

@ -4,7 +4,7 @@ group: Respond
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# GitLab Developers Guide to Logging **(FREE)**
# GitLab Developers Guide to Logging
[GitLab Logs](../administration/logs/index.md) play a critical role for both
administrators and GitLab team members to diagnose problems in the field.

View File

@ -4,7 +4,7 @@ group: Geo
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Internal workings of GitLab Maintenance Mode **(PREMIUM SELF)**
# Internal workings of GitLab Maintenance Mode
## Where is Maintenance Mode enforced?

View File

@ -4,7 +4,7 @@ group: Code Review
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Merge request diffs development guide **(FREE)**
# Merge request diffs development guide
This document explains the backend design and flow of merge request diffs.
It should help contributors:

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
---

View File

@ -4,7 +4,7 @@ group: Respond
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Working with Prometheus Metrics **(FREE)**
# Working with Prometheus Metrics
## Adding to the library

View File

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
type: index, concepts, howto
---
# Sec section development **(FREE)**
# Sec section development
The Sec section is responsible for GitLab application security features, the "Sec" part of
DevSecOps. Development guides that are specific to the Sec section are listed here.

View File

@ -4,7 +4,7 @@ group: Product Intelligence
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Service Ping Guide **(FREE SELF)**
# Service Ping Guide
> - Introduced in GitLab Ultimate 11.2, more statistics.
> - In GitLab 14.1, [renamed from Usage Ping to Service Ping](https://gitlab.com/groups/gitlab-org/-/epics/5990). In 14.0 and earlier, use the Usage Ping documentation for the Rails commands appropriate to your version.

View File

@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
description: "GitLab's development guidelines for Wikis"
---
# Wikis development guide **(FREE)**
# Wikis development guide
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/227027) in GitLab 13.5.

View File

@ -142,7 +142,7 @@ A deactivated user:
- Cannot access Git repositories or the API.
- Does not receive any notifications from GitLab.
- Does not be able to use [slash commands](../../integration/slash_commands.md).
- Cannot use [slash commands](../../integration/slash_commands.md).
- Does not consume a [seat](../../subscriptions/self_managed/index.md#billable-users).
Personal projects, and group and user history of the deactivated user are left intact.

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: concepts, howto
---

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: 'To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments'
type: reference, index, howto
---

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments"
---

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference
---

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,6 +1,6 @@
---
stage: Manage
group: Workspace
group: Organization
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -188,6 +188,35 @@ module API
present environment, with: Entities::Environment, current_user: current_user
end
desc 'Stop stale environments' do
detail 'It returns `200` if stale environment check was scheduled successfully'
failure [
{ code: 400, message: 'Bad request' },
{ code: 401, message: 'Unauthorized' }
]
tags %w[environments]
end
params do
requires :before,
type: DateTime,
desc: 'Stop all environments that were last modified or deployed to before this date.'
end
post ':id/environments/stop_stale' do
authorize! :stop_environment, user_project
bad_request!('Invalid Date') if params[:before] < 10.years.ago || params[:before] > 1.week.ago
service_response = ::Environments::StopStaleService.new(user_project, current_user, params.slice(:before)).execute
if service_response.error?
status 400
else
status 200
end
present message: service_response.message
end
desc 'Get a specific environment' do
success Entities::Environment
failure [

View File

@ -90,14 +90,14 @@ module Banzai
end
def get_uri(html_attr)
uri = URI(html_attr.value)
uri = Addressable::URI.parse(html_attr.value)
uri if uri.relative? && uri.path.present?
rescue URI::Error, Addressable::URI::InvalidURIError
end
def process_link_to_repository_attr(html_attr)
uri = URI(html_attr.value)
uri = Addressable::URI.parse(html_attr.value)
if uri.relative? && uri.path.present?
html_attr.value = rebuild_relative_uri(uri).to_s

View File

@ -127,6 +127,10 @@ module Gitlab
.observe({ plan: project.actual_plan_name }, jobs_count)
end
def observe_pipeline_includes_count(pipeline)
logger.observe(:pipeline_includes_count, pipeline.config_metadata&.[](:includes)&.count, once: true)
end
def increment_pipeline_failure_reason_counter(reason)
metrics.pipeline_failure_reason_counter
.increment(reason: (reason || :unknown_failure).to_s)

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