Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-10-16 18:09:04 +00:00
parent 3940f59a61
commit b58ab6c33c
152 changed files with 2560 additions and 351 deletions

View File

@ -1,14 +1,19 @@
<script>
import InstanceCounts from './instance_counts.vue';
import PipelinesChart from './pipelines_chart.vue';
export default {
name: 'InstanceStatisticsApp',
components: {
InstanceCounts,
PipelinesChart,
},
};
</script>
<template>
<instance-counts />
<div>
<instance-counts />
<pipelines-chart />
</div>
</template>

View File

@ -0,0 +1,216 @@
<script>
import { GlLineChart } from '@gitlab/ui/dist/charts';
import { GlAlert } from '@gitlab/ui';
import { mapKeys, mapValues, pick, some, sum } from 'lodash';
import ChartSkeletonLoader from '~/vue_shared/components/resizable_chart/skeleton_loader.vue';
import { s__ } from '~/locale';
import { formatDateAsMonth, getDayDifference } from '~/lib/utils/datetime_utility';
import { getAverageByMonth, sortByDate, extractValues } from '../utils';
import pipelineStatsQuery from '../graphql/queries/pipeline_stats.query.graphql';
import { TODAY, START_DATE } from '../constants';
const DATA_KEYS = [
'pipelinesTotal',
'pipelinesSucceeded',
'pipelinesFailed',
'pipelinesCanceled',
'pipelinesSkipped',
];
const PREFIX = 'pipelines';
export default {
name: 'PipelinesChart',
components: {
GlLineChart,
GlAlert,
ChartSkeletonLoader,
},
startDate: START_DATE,
endDate: TODAY,
i18n: {
loadPipelineChartError: s__(
'InstanceAnalytics|Could not load the pipelines chart. Please refresh the page to try again.',
),
noDataMessage: s__('InstanceAnalytics|There is no data available.'),
total: s__('InstanceAnalytics|Total'),
succeeded: s__('InstanceAnalytics|Succeeded'),
failed: s__('InstanceAnalytics|Failed'),
canceled: s__('InstanceAnalytics|Canceled'),
skipped: s__('InstanceAnalytics|Skipped'),
chartTitle: s__('InstanceAnalytics|Pipelines'),
yAxisTitle: s__('InstanceAnalytics|Items'),
xAxisTitle: s__('InstanceAnalytics|Month'),
},
data() {
return {
loading: true,
loadingError: null,
};
},
apollo: {
pipelineStats: {
query: pipelineStatsQuery,
variables() {
return {
firstTotal: this.totalDaysToShow,
firstSucceeded: this.totalDaysToShow,
firstFailed: this.totalDaysToShow,
firstCanceled: this.totalDaysToShow,
firstSkipped: this.totalDaysToShow,
};
},
update(data) {
const allData = extractValues(data, DATA_KEYS, PREFIX, 'nodes');
const allPageInfo = extractValues(data, DATA_KEYS, PREFIX, 'pageInfo');
return {
...mapValues(allData, sortByDate),
...allPageInfo,
};
},
result() {
if (this.hasNextPage) {
this.fetchNextPage();
}
},
error() {
this.handleError();
},
},
},
computed: {
isLoading() {
return this.$apollo.queries.pipelineStats.loading;
},
totalDaysToShow() {
return getDayDifference(this.$options.startDate, this.$options.endDate);
},
firstVariables() {
const allData = pick(this.pipelineStats, [
'nodesTotal',
'nodesSucceeded',
'nodesFailed',
'nodesCanceled',
'nodesSkipped',
]);
const allDayDiffs = mapValues(allData, data => {
const firstdataPoint = data[0];
if (!firstdataPoint) {
return 0;
}
return Math.max(
0,
getDayDifference(this.$options.startDate, new Date(firstdataPoint.recordedAt)),
);
});
return mapKeys(allDayDiffs, (value, key) => key.replace('nodes', 'first'));
},
cursorVariables() {
const pageInfoKeys = [
'pageInfoTotal',
'pageInfoSucceeded',
'pageInfoFailed',
'pageInfoCanceled',
'pageInfoSkipped',
];
return extractValues(this.pipelineStats, pageInfoKeys, 'pageInfo', 'endCursor');
},
hasNextPage() {
return (
sum(Object.values(this.firstVariables)) > 0 &&
some(this.pipelineStats, ({ hasNextPage }) => hasNextPage)
);
},
hasEmptyDataSet() {
return this.chartData.every(({ data }) => data.length === 0);
},
chartData() {
const allData = pick(this.pipelineStats, [
'nodesTotal',
'nodesSucceeded',
'nodesFailed',
'nodesCanceled',
'nodesSkipped',
]);
const options = { shouldRound: true };
return Object.keys(allData).map(key => {
const i18nName = key.slice('nodes'.length).toLowerCase();
return {
name: this.$options.i18n[i18nName],
data: getAverageByMonth(allData[key], options),
};
});
},
range() {
return {
min: this.$options.startDate,
max: this.$options.endDate,
};
},
differenceInMonths() {
const yearDiff = this.$options.endDate.getYear() - this.$options.startDate.getYear();
const monthDiff = this.$options.endDate.getMonth() - this.$options.startDate.getMonth();
return monthDiff + 12 * yearDiff;
},
chartOptions() {
return {
xAxis: {
...this.range,
name: this.$options.i18n.xAxisTitle,
type: 'time',
splitNumber: this.differenceInMonths + 1,
axisLabel: {
interval: 0,
showMinLabel: false,
showMaxLabel: false,
align: 'right',
formatter: formatDateAsMonth,
},
},
yAxis: {
name: this.$options.i18n.yAxisTitle,
},
};
},
},
methods: {
handleError() {
this.loadingError = true;
},
fetchNextPage() {
this.$apollo.queries.pipelineStats
.fetchMore({
variables: {
...this.firstVariables,
...this.cursorVariables,
},
updateQuery: (previousResult, { fetchMoreResult }) => {
return Object.keys(fetchMoreResult).reduce((memo, key) => {
const { nodes, ...rest } = fetchMoreResult[key];
const previousNodes = previousResult[key].nodes;
return { ...memo, [key]: { ...rest, nodes: [...previousNodes, ...nodes] } };
}, {});
},
})
.catch(this.handleError);
},
},
};
</script>
<template>
<div>
<h3>{{ $options.i18n.chartTitle }}</h3>
<gl-alert v-if="loadingError" variant="danger" :dismissible="false" class="gl-mt-3">
{{ this.$options.i18n.loadPipelineChartError }}
</gl-alert>
<chart-skeleton-loader v-else-if="isLoading" />
<gl-alert v-else-if="hasEmptyDataSet" variant="info" :dismissible="false" class="gl-mt-3">
{{ $options.i18n.noDataMessage }}
</gl-alert>
<gl-line-chart v-else :option="chartOptions" :include-legend-avg-max="true" :data="chartData" />
</div>
</template>

View File

@ -0,0 +1,5 @@
import { getDateInPast } from '~/lib/utils/datetime_utility';
const TOTAL_DAYS_TO_SHOW = 365;
export const TODAY = new Date();
export const START_DATE = getDateInPast(TODAY, TOTAL_DAYS_TO_SHOW);

View File

@ -0,0 +1,4 @@
fragment Count on InstanceStatisticsMeasurement {
count
recordedAt
}

View File

@ -0,0 +1,76 @@
#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
#import "./count.fragment.graphql"
query pipelineStats(
$firstTotal: Int
$firstSucceeded: Int
$firstFailed: Int
$firstCanceled: Int
$firstSkipped: Int
$endCursorTotal: String
$endCursorSucceeded: String
$endCursorFailed: String
$endCursorCanceled: String
$endCursorSkipped: String
) {
pipelinesTotal: instanceStatisticsMeasurements(
identifier: PIPELINES
first: $firstTotal
after: $endCursorTotal
) {
nodes {
...Count
}
pageInfo {
...PageInfo
}
}
pipelinesSucceeded: instanceStatisticsMeasurements(
identifier: PIPELINES_SUCCEEDED
first: $firstSucceeded
after: $endCursorSucceeded
) {
nodes {
...Count
}
pageInfo {
...PageInfo
}
}
pipelinesFailed: instanceStatisticsMeasurements(
identifier: PIPELINES_FAILED
first: $firstFailed
after: $endCursorFailed
) {
nodes {
...Count
}
pageInfo {
...PageInfo
}
}
pipelinesCanceled: instanceStatisticsMeasurements(
identifier: PIPELINES_CANCELED
first: $firstCanceled
after: $endCursorCanceled
) {
nodes {
...Count
}
pageInfo {
...PageInfo
}
}
pipelinesSkipped: instanceStatisticsMeasurements(
identifier: PIPELINES_SKIPPED
first: $firstSkipped
after: $endCursorSkipped
) {
nodes {
...Count
}
pageInfo {
...PageInfo
}
}
}

View File

@ -1,4 +1,5 @@
import { masks } from 'dateformat';
import { mapKeys, mapValues, pick, sortBy } from 'lodash';
import { formatDate } from '~/lib/utils/datetime_utility';
const { isoDate } = masks;
@ -38,3 +39,31 @@ export function getAverageByMonth(items = [], options = {}) {
return [month, avg];
});
}
/**
* Extracts values given a data set and a set of keys
* @example
* const data = { fooBar: { baz: 'quis' }, ignored: 'ignored' };
* extractValues(data, ['fooBar'], 'foo', 'baz') => { bazBar: 'quis' }
* @param {Object} data set to extract values from
* @param {Array} dataKeys keys describing where to look for values in the data set
* @param {String} replaceKey name key to be replaced in the data set
* @param {String} nestedKey key nested in the data set to be extracted,
* this is also used to rename the newly created data set
* @return {Object} the newly created data set with the extracted values
*/
export function extractValues(data, dataKeys = [], replaceKey, nestedKey) {
return mapKeys(pick(mapValues(data, nestedKey), dataKeys), (value, key) =>
key.replace(replaceKey, nestedKey),
);
}
/**
* Creates a new array of items sorted by the date string of each item
* @param {Array} items [description]
* @param {String} items[0] date string
* @return {Array} the new sorted array.
*/
export function sortByDate(items = []) {
return sortBy(items, ({ recordedAt }) => new Date(recordedAt).getTime());
}

View File

@ -4,6 +4,7 @@ import { __ } from '~/locale';
import { deprecatedCreateFlash as Flash } from '~/flash';
import axios from '~/lib/utils/axios_utils';
import SSHMirror from './ssh_mirror';
import { hide } from '~/tooltips';
export default class MirrorRepos {
constructor(container) {
@ -115,7 +116,7 @@ export default class MirrorRepos {
/* eslint-disable class-methods-use-this */
removeRow($target) {
const row = $target.closest('tr');
$('.js-delete-mirror', row).tooltip('hide');
hide($('.js-delete-mirror', row));
row.remove();
}
/* eslint-enable class-methods-use-this */

View File

@ -1,3 +1,3 @@
import initEnviroments from '~/environments/';
import initEnvironments from '~/environments/';
document.addEventListener('DOMContentLoaded', initEnviroments);
document.addEventListener('DOMContentLoaded', initEnvironments);

View File

@ -7,16 +7,15 @@ import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered
import { FILTERED_SEARCH } from '~/pages/constants';
import { ISSUABLE_INDEX } from '~/pages/projects/constants';
document.addEventListener('DOMContentLoaded', () => {
addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys);
new IssuableIndex(ISSUABLE_INDEX.MERGE_REQUEST); // eslint-disable-line no-new
initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS,
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
useDefaultState: true,
});
addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys);
new IssuableIndex(ISSUABLE_INDEX.MERGE_REQUEST); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new
new UsersSelect(); // eslint-disable-line no-new
initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS,
filteredSearchTokenKeys: IssuableFilteredSearchTokenKeys,
useDefaultState: true,
});
new UsersSelect(); // eslint-disable-line no-new
new ShortcutsNavigation(); // eslint-disable-line no-new

View File

@ -5,12 +5,10 @@ import initShow from '../init_merge_request_show';
import initIssuableHeaderWarning from '~/vue_shared/components/issuable/init_issuable_header_warning';
import store from '~/mr_notes/stores';
document.addEventListener('DOMContentLoaded', () => {
initShow();
if (gon.features && !gon.features.vueIssuableSidebar) {
initSidebarBundle();
}
initMrNotes();
initReviewBar();
initIssuableHeaderWarning(store);
});
initShow();
if (gon.features && !gon.features.vueIssuableSidebar) {
initSidebarBundle();
}
initMrNotes();
initReviewBar();
initIssuableHeaderWarning(store);

View File

@ -392,6 +392,7 @@ export default {
type="submit"
category="primary"
variant="success"
class="js-no-auto-disable"
data-qa-selector="run_pipeline_button"
>{{ s__('Pipeline|Run Pipeline') }}</gl-button
>

View File

@ -0,0 +1,12 @@
import { s__ } from '~/locale';
export default {
basic: {
text: s__('ProjectTemplates|Basic'),
icon: '.template-option .icon-basic',
},
serenity_valley: {
text: s__('ProjectTemplates|Serenity Valley'),
icon: '.template-option .icon-serenity_valley',
},
};

View File

@ -1,5 +1,6 @@
import $ from 'jquery';
import DEFAULT_PROJECT_TEMPLATES from 'ee_else_ce/projects/default_project_templates';
import DEFAULT_SAMPLE_DATA_TEMPLATES from '~/projects/default_sample_data_templates';
import { addSelectOnFocusBehaviour } from '../lib/utils/common_utils';
import {
convertToTitleCase,
@ -146,7 +147,8 @@ const bindEvents = () => {
$selectedIcon.empty();
const value = $(this).val();
const selectedTemplate = DEFAULT_PROJECT_TEMPLATES[value];
const selectedTemplate =
DEFAULT_PROJECT_TEMPLATES[value] || DEFAULT_SAMPLE_DATA_TEMPLATES[value];
$selectedTemplateText.text(selectedTemplate.text);
$(selectedTemplate.icon)
.clone()

View File

@ -67,7 +67,10 @@ class Admin::SessionsController < ApplicationController
end
def valid_otp_attempt?(user)
valid_otp_attempt = user.validate_and_consume_otp!(user_params[:otp_attempt])
otp_validation_result =
::Users::ValidateOtpService.new(user).execute(user_params[:otp_attempt])
valid_otp_attempt = otp_validation_result[:status] == :success
return valid_otp_attempt if Gitlab::Database.read_only?
valid_otp_attempt || user.invalidate_otp_backup_code!(user_params[:otp_attempt])

View File

@ -47,7 +47,10 @@ class Profiles::TwoFactorAuthsController < Profiles::ApplicationController
end
def create
if current_user.validate_and_consume_otp!(params[:pin_code])
otp_validation_result =
::Users::ValidateOtpService.new(current_user).execute(params[:pin_code])
if otp_validation_result[:status] == :success
ActiveSession.destroy_all_but_current(current_user, session)
Users::UpdateService.new(current_user, user: current_user, otp_required_for_login: true).execute! do |user|

View File

@ -217,7 +217,7 @@ class Projects::IssuesController < Projects::ApplicationController
end
def export_csv
ExportCsvWorker.perform_async(current_user.id, project.id, finder_options.to_h) # rubocop:disable CodeReuse/Worker
IssuableExportCsvWorker.perform_async(:issue, current_user.id, project.id, finder_options.to_h) # rubocop:disable CodeReuse/Worker
index_path = project_issues_path(project)
message = _('Your CSV export has started. It will be emailed to %{email} when complete.') % { email: current_user.notification_email }
@ -326,7 +326,7 @@ class Projects::IssuesController < Projects::ApplicationController
end
def store_uri
if request.get? && !request.xhr?
if request.get? && request.format.html?
store_location_for :user, request.fullpath
end
end

View File

@ -264,8 +264,11 @@ class SessionsController < Devise::SessionsController
end
def valid_otp_attempt?(user)
user.validate_and_consume_otp!(user_params[:otp_attempt]) ||
user.invalidate_otp_backup_code!(user_params[:otp_attempt])
otp_validation_result =
::Users::ValidateOtpService.new(user).execute(user_params[:otp_attempt])
return true if otp_validation_result[:status] == :success
user.invalidate_otp_backup_code!(user_params[:otp_attempt])
end
def log_audit_event(user, resource, options = {})

View File

@ -153,8 +153,10 @@ class IssuableFinder
end
def row_count
fast_fail = Feature.enabled?(:soft_fail_count_by_state, params.group || params.project)
Gitlab::IssuablesCountForState
.new(self, nil, fast_fail: Feature.enabled?(:soft_fail_count_by_state, parent))
.new(self, nil, fast_fail: fast_fail)
.for_state_or_opened(params[:state])
end

View File

@ -82,6 +82,7 @@ module IssuablesHelper
when Issue
IssueSerializer
when MergeRequest
opts[:experiment_enabled] = :suggest_pipeline if experiment_enabled?(:suggest_pipeline) && opts[:serializer] == 'widget'
MergeRequestSerializer
end

View File

@ -93,7 +93,7 @@ module Emails
def issues_csv_email(user, project, csv_data, export_status)
@project = project
@issues_count = export_status.fetch(:rows_expected)
@count = export_status.fetch(:rows_expected)
@written_count = export_status.fetch(:rows_written)
@truncated = export_status.fetch(:truncated)

View File

@ -110,6 +110,20 @@ module Emails
mail_answer_thread(@merge_request, merge_request_thread_options(mwps_set_by_user_id, recipient_id, reason))
end
def merge_requests_csv_email(user, project, csv_data, export_status)
@project = project
@count = export_status.fetch(:rows_expected)
@written_count = export_status.fetch(:rows_written)
@truncated = export_status.fetch(:truncated)
filename = "#{project.full_path.parameterize}_merge_requests_#{Date.current.iso8601}.csv"
attachments[filename] = { content: csv_data, mime_type: 'text/csv' }
mail(to: user.notification_email_for(@project.group), subject: subject("Exported merge requests")) do |format|
format.html { render layout: 'mailer' }
format.text { render layout: 'mailer' }
end
end
private
def setup_merge_request_mail(merge_request_id, recipient_id, present: false)

View File

@ -14,7 +14,7 @@ module BlobViewer
{}.tap do |h|
h[:rendered] = blob.rendered_markup if blob.respond_to?(:rendered_markup)
if Feature.enabled?(:cached_markdown_blob, blob.project)
if Feature.enabled?(:cached_markdown_blob, blob.project, default_enabled: true)
h[:cache_key] = ['blob', blob.id, 'commit', blob.commit_id]
end
end

View File

@ -793,7 +793,7 @@ class User < ApplicationRecord
end
def two_factor_otp_enabled?
otp_required_for_login?
otp_required_for_login? || Feature.enabled?(:forti_authenticator, self)
end
def two_factor_u2f_enabled?

View File

@ -67,15 +67,15 @@ class MergeRequestWidgetEntity < Grape::Entity
)
end
expose :user_callouts_path, if: -> (*) { Gitlab::Experimentation.enabled?(:suggest_pipeline) } do |_merge_request|
expose :user_callouts_path, if: -> (_, opts) { opts[:experiment_enabled] == :suggest_pipeline } do |_merge_request|
user_callouts_path
end
expose :suggest_pipeline_feature_id, if: -> (*) { Gitlab::Experimentation.enabled?(:suggest_pipeline) } do |_merge_request|
expose :suggest_pipeline_feature_id, if: -> (_, opts) { opts[:experiment_enabled] == :suggest_pipeline } do |_merge_request|
SUGGEST_PIPELINE
end
expose :is_dismissed_suggest_pipeline, if: -> (*) { Gitlab::Experimentation.enabled?(:suggest_pipeline) } do |_merge_request|
expose :is_dismissed_suggest_pipeline, if: -> (_, opts) { opts[:experiment_enabled] == :suggest_pipeline } do |_merge_request|
current_user && current_user.dismissed_callout?(feature_name: SUGGEST_PIPELINE)
end

View File

@ -8,7 +8,8 @@ module MergeRequests
# Target attachment size before base64 encoding
TARGET_FILESIZE = 15.megabytes
def initialize(merge_requests)
def initialize(merge_requests, project)
@project = project
@merge_requests = merge_requests
end
@ -16,6 +17,10 @@ module MergeRequests
csv_builder.render(TARGET_FILESIZE)
end
def email(user)
Notify.merge_requests_csv_email(user, @project, csv_data, csv_builder.status).deliver_now
end
private
def csv_builder

View File

@ -14,10 +14,16 @@ module Projects
def execute
return project unless validate_template!
file = built_in_template&.file
file = built_in_template&.file || sample_data_template&.file
override_params = params.dup
params[:file] = file
if built_in_template
params[:file] = built_in_template.file
elsif sample_data_template
params[:file] = sample_data_template.file
params[:sample_data] = true
end
GitlabProjectsImportService.new(current_user, params, override_params).execute
ensure
@ -27,7 +33,7 @@ module Projects
private
def validate_template!
return true if built_in_template
return true if built_in_template || sample_data_template
project.errors.add(:template_name, _("'%{template_name}' is unknown or invalid" % { template_name: template_name }))
false
@ -39,6 +45,12 @@ module Projects
end
end
def sample_data_template
strong_memoize(:sample_data_template) do
Gitlab::SampleDataTemplate.find(template_name)
end
end
def project
@project ||= ::Project.new(namespace_id: params[:namespace_id])
end

View File

@ -66,6 +66,7 @@ module Projects
end
if template_file
data[:sample_data] = params.delete(:sample_data) if params.key?(:sample_data)
params[:import_type] = 'gitlab_project'
end

View File

@ -0,0 +1,25 @@
# frozen_string_literal: true
module Users
class ValidateOtpService < BaseService
def initialize(current_user)
@current_user = current_user
@strategy = if Feature.enabled?(:forti_authenticator, current_user)
::Gitlab::Auth::Otp::Strategies::FortiAuthenticator.new(current_user)
else
::Gitlab::Auth::Otp::Strategies::Devise.new(current_user)
end
end
def execute(otp_code)
strategy.validate(otp_code)
rescue StandardError => ex
Gitlab::ErrorTracking.log_exception(ex)
error(message: ex.message)
end
private
attr_reader :strategy
end
end

View File

@ -92,7 +92,7 @@
%li.nav-item
%div
- sign_in_text = allow_signup? ? _('Sign in / Register') : _('Sign in')
= link_to sign_in_text, new_session_path(:user, redirect_to_referer: 'yes'), class: 'btn btn-sign-in'
= link_to sign_in_text, new_session_path(:user, redirect_to_referer: 'yes'), class: 'gl-button btn btn-sign-in'
%button.navbar-toggler.d-block.d-sm-none{ type: 'button' }
%span.sr-only= _('Toggle navigation')

View File

@ -0,0 +1,6 @@
%p{ style: 'font-size:18px; text-align:center; line-height:30px;' }
- project_link = link_to(@project.full_name, project_url(@project), style: "color:#3777b0; text-decoration:none; display:block;")
= _('Your CSV export of %{count} from project %{project_link} has been added to this email as an attachment.').html_safe % { count: pluralize(@written_count, type.to_s), project_link: project_link }
- if @truncated
%p
= _('This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{count} issues have been included. Consider re-exporting with a narrower selection of issues.') % { written_count: @written_count, count: @count }

View File

@ -1,6 +1 @@
%p{ style: 'font-size:18px; text-align:center; line-height:30px;' }
- project_link = link_to(@project.full_name, project_url(@project), style: "color:#3777b0; text-decoration:none; display:block;")
= _('Your CSV export of %{issues_count} from project %{project_link} has been added to this email as an attachment.').html_safe % { issues_count: pluralize(@written_count, 'issue'), project_link: project_link }
- if @truncated
%p
= _('This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{issues_count} issues have been included. Consider re-exporting with a narrower selection of issues.') % { written_count: @written_count, issues_count: @issues_count }
= render 'issuable_csv_export', type: :issue

View File

@ -0,0 +1 @@
= render 'issuable_csv_export', type: :merge_request

View File

@ -0,0 +1,5 @@
<%= _('Your CSV export of %{written_count} from project %{project_name} (%{project_url}) has been added to this email as an attachment.') % { written_count: pluralize(@written_count, 'merge request'), project_name: @project.full_name, project_url: project_url(@project) } %>
<% if @truncated %>
<%= _('This attachment has been truncated to avoid exceeding the maximum allowed attachment size of 15MB. %{written_count} of %{merge_requests_count} issues have been included. Consider re-exporting with a narrower selection of issues.') % { written_count: @written_count, merge_requests_count: @merge_requests_count} %>
<% end %>

View File

@ -1,7 +1,21 @@
- f ||= local_assigns[:f]
.project-templates-buttons.import-buttons.col-sm-12
= render 'projects/project_templates/built_in_templates'
.project-templates-buttons.col-sm-12
%ul.nav-tabs.nav-links.nav.scrolling-tabs
%li.built-in-tab
%a.nav-link.active{ href: "#built-in", data: { toggle: 'tab'} }
= _('Built-in')
%span.badge.badge-pill= Gitlab::ProjectTemplate.all.count
%li.sample-data-templates-tab
%a.nav-link{ href: "#sample-data-templates", data: { toggle: 'tab'} }
= _('Sample Data')
%span.badge.badge-pill= Gitlab::SampleDataTemplate.all.count
.tab-content
.project-templates-buttons.import-buttons.tab-pane.active#built-in
= render partial: 'projects/project_templates/template', collection: Gitlab::ProjectTemplate.all
.project-templates-buttons.import-buttons.tab-pane#sample-data-templates
= render partial: 'projects/project_templates/template', collection: Gitlab::SampleDataTemplate.all
.project-fields-form
= render 'projects/project_templates/project_fields_form'

View File

@ -1,17 +0,0 @@
- Gitlab::ProjectTemplate.all.each do |template|
.template-option.d-flex.align-items-center{ data: { qa_selector: 'template_option_row' } }
.logo.gl-mr-3.px-1
= image_tag template.logo, size: 32, class: "btn-template-icon icon-#{template.name}"
.description
%strong
= template.title
%br
.text-muted
= template.description
.controls.d-flex.align-items-center
%a.btn.btn-default.gl-mr-3{ href: template.preview, rel: 'noopener noreferrer', target: '_blank', data: { track_label: "template_preview", track_property: template.name, track_event: "click_button", track_value: "" } }
= _("Preview")
%label.btn.btn-success.template-button.choose-template.gl-mb-0{ for: template.name }
%input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: template.name, value: template.name, data: { track_label: "template_use", track_property: template.name, track_event: "click_button", track_value: "" } }
%span{ data: { qa_selector: 'use_template_button' } }
= _("Use template")

View File

@ -0,0 +1,16 @@
.template-option.d-flex.align-items-center{ data: { qa_selector: 'template_option_row' } }
.logo.gl-mr-3.px-1
= image_tag template.logo, size: 32, class: "btn-template-icon icon-#{template.name}"
.description
%strong
= template.title
%br
.text-muted
= template.description
.controls.d-flex.align-items-center
%a.btn.gl-button.btn-default.gl-mr-3{ href: template.preview, rel: 'noopener noreferrer', target: '_blank', data: { track_label: "template_preview", track_property: template.name, track_event: "click_button", track_value: "" } }
= _("Preview")
%label.btn.gl-button.btn-success.template-button.choose-template.gl-mb-0{ for: template.name }
%input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: template.name, value: template.name, data: { track_label: "template_use", track_property: template.name, track_event: "click_button", track_value: "" } }
%span{ data: { qa_selector: 'use_template_button' } }
= _("Use template")

View File

@ -1,13 +1,13 @@
- if show_auto_devops_implicitly_enabled_banner?(project, current_user)
.qa-auto-devops-banner.auto-devops-implicitly-enabled-banner.alert.alert-info
- more_information_link = link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank', class: 'alert-link'
- auto_devops_message = s_("AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found. %{more_information_link}") % { more_information_link: more_information_link }
= auto_devops_message.html_safe
.alert-link-group
= link_to _('Settings'), project_settings_ci_cd_path(project), class: 'alert-link'
|
= link_to _('Dismiss'), '#', class: 'hide-auto-devops-implicitly-enabled-banner alert-link', data: { project_id: project.id }
.qa-auto-devops-banner.auto-devops-implicitly-enabled-banner.gl-alert.gl-alert-info
= sprite_icon('information-o', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
%button.js-close.gl-alert-dismiss{ type: 'button', 'aria-label' => _('Dismiss'), class: 'hide-auto-devops-implicitly-enabled-banner alert-link', data: { project_id: project.id } }
= sprite_icon('close', css_class: 'gl-icon')
.gl-alert-body
= s_("AutoDevOps|The Auto DevOps pipeline has been enabled and will be used if no alternative CI configuration file is found.")
- unless Gitlab.config.registry.enabled
%div
= icon('exclamation-triangle')
= _('Container registry is not enabled on this GitLab instance. Ask an administrator to enable it in order for Auto DevOps to work.')
.gl-alert-actions.gl-mt-3
= link_to _('Settings'), project_settings_ci_cd_path(project), class: 'alert-link btn gl-button btn-info'
= link_to _('More information'), help_page_path('topics/autodevops/index.md'), target: '_blank', class: 'alert-link btn gl-button btn-default gl-ml-2'

View File

@ -1571,6 +1571,14 @@
:weight: 1
:idempotent:
:tags: []
- :name: issuable_export_csv
:feature_category: :issue_tracking
:has_external_dependencies:
:urgency: :low
:resource_boundary: :cpu
:weight: 1
:idempotent:
:tags: []
- :name: issue_placement
:feature_category: :issue_tracking
:has_external_dependencies:

View File

@ -15,8 +15,6 @@ class ExportCsvWorker # rubocop:disable Scalability/IdempotentWorker
params[:project_id] = project_id
params.delete(:sort)
issues = IssuesFinder.new(@current_user, params).execute
Issues::ExportCsvService.new(issues, @project).email(@current_user)
IssuableExportCsvWorker.perform_async(:issue, @current_user.id, @project.id, params)
end
end

View File

@ -0,0 +1,53 @@
# frozen_string_literal: true
class IssuableExportCsvWorker # rubocop:disable Scalability/IdempotentWorker
include ApplicationWorker
feature_category :issue_tracking
worker_resource_boundary :cpu
loggable_arguments 2
PERMITTED_TYPES = [:merge_request, :issue].freeze
def perform(type, current_user_id, project_id, params)
@type = type.to_sym
check_permitted_type!
process_params!(params, project_id)
@current_user = User.find(current_user_id)
@project = Project.find(project_id)
@service = service(find_objects(params))
@service.email(@current_user)
end
private
def find_objects(params)
case @type
when :issue
IssuesFinder.new(@current_user, params).execute
when :merge_request
MergeRequestsFinder.new(@current_user, params).execute
end
end
def service(issuables)
case @type
when :issue
Issues::ExportCsvService.new(issuables, @project)
when :merge_request
MergeRequests::ExportCsvService.new(issuables, @project)
end
end
def process_params!(params, project_id)
params.symbolize_keys!
params[:project_id] = project_id
params.delete(:sort)
end
def check_permitted_type!
raise ArgumentError, "type parameter must be :issue or :merge_request, it was #{@type}" unless PERMITTED_TYPES.include?(@type)
end
end

View File

@ -0,0 +1,5 @@
---
title: Migrate auto devops message from bootstrap
merge_request: 45221
author:
type: other

View File

@ -0,0 +1,5 @@
---
title: Add undo helpers for change_column_type_concurrently and cleanup_concurrent_column_type_change
merge_request: 44155
author:
type: other

View File

@ -0,0 +1,5 @@
---
title: Enable caching of markdown when viewing blob
merge_request: 45367
author:
type: performance

View File

@ -0,0 +1,5 @@
---
title: Fix redirects to issue sidebar JSON when visiting the login page
merge_request: 45194
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Add Sample Data
merge_request: 41699
author:
type: added

View File

@ -4,4 +4,4 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44300
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/263406
type: development
group: group::source code
default_enabled: false
default_enabled: true

View File

@ -0,0 +1,7 @@
---
name: forti_authenticator
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45055
rollout_issue_url:
type: development
group: group::access
default_enabled: false

View File

@ -1,7 +0,0 @@
---
name: push_rules_supersede_code_owners
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44126
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/262019
type: development
group: group::source code
default_enabled: false

View File

@ -4,4 +4,4 @@ introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33277
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/233895
group: group::package
type: development
default_enabled: false
default_enabled: true

View File

@ -1022,6 +1022,21 @@ production: &base
# cas3:
# session_duration: 28800
# FortiAuthenticator settings
forti_authenticator:
# Allow using FortiAuthenticator as OTP provider
enabled: false
# Host and port of FortiAuthenticator instance
# host: forti_authenticator.example.com
# port: 443
# Username for accessing FortiAuthenticator API
# username: john
# Access token for FortiAuthenticator API
# access_token: 123s3cr3t456
# Shared file storage settings
shared:
# path: /mnt/gitlab # Default: shared

View File

@ -766,6 +766,13 @@ Gitlab.ee do
Settings.smartcard['san_extensions'] = false if Settings.smartcard['san_extensions'].nil?
end
#
# FortiAuthenticator
#
Settings['forti_authenticator'] ||= Settingslogic.new({})
Settings.forti_authenticator['enabled'] = false if Settings.forti_authenticator['enabled'].nil?
Settings.forti_authenticator['port'] = 443 if Settings.forti_authenticator['port'].to_i == 0
#
# Extra customization
#

View File

@ -152,6 +152,8 @@
- 2
- - irker
- 1
- - issuable_export_csv
- 1
- - issue_placement
- 2
- - issue_rebalancing

View File

@ -146,6 +146,7 @@ failsafe
Falco
fastlane
favicon
Figma
Filebeat
Fio
firewalled
@ -312,6 +313,7 @@ passwordless
Patroni
performant
PgBouncer
Phabricator
phaser
phasers
Pipfile
@ -352,6 +354,7 @@ Python
Qualys
Rackspace
Raspbian
Rdoc
reachability
rebase
rebased
@ -433,7 +436,10 @@ smartcard
smartcards
SMTP
Sobelow
Solarized
Sourcegraph
sparkline
sparklines
spidering
Splunk
SpotBugs
@ -449,6 +455,8 @@ subfolder
subfolders
subgraph
subgraphs
subkey
subkeys
sublicense
sublicensed
sublicenses
@ -468,6 +476,7 @@ subtrees
sudo
syslog
tcpdump
Thanos
Tiller
timecop
todos
@ -490,6 +499,7 @@ unarchived
unarchives
unarchiving
unassign
unassigning
unassigns
uncheck
unchecked

View File

@ -2,6 +2,35 @@
Uploads represent all user data that may be sent to GitLab as a single file. As an example, avatars and notes' attachments are uploads. Uploads are integral to GitLab functionality, and therefore cannot be disabled.
## Upload parameters
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/214785) in GitLab 13.5.
> - It's [deployed behind a feature flag](../user/feature_flags.md), enabled by default.
> - It's enabled on GitLab.com.
> - It's recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can opt to disable it. **(CORE ONLY)**
In 13.5 and later, upload parameters are passed [between Workhorse and GitLab Rails](../development/architecture.md#simplified-component-overview) differently than they
were before.
This change is deployed behind a feature flag that is **enabled by default**.
If you experience any issues with upload,
[GitLab administrators with access to the GitLab Rails console](./feature_flags.md)
can opt to disable it.
To enable it:
```ruby
Feature.enable(:upload_middleware_jwt_params_handler)
```
To disable it:
```ruby
Feature.disable(:upload_middleware_jwt_params_handler)
```
## Using local storage
NOTE: **Note:**

40
doc/api/experiments.md Normal file
View File

@ -0,0 +1,40 @@
---
stage: Growth
group: Expansion
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/#designated-technical-writers
---
# Experiments API
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/262725) in GitLab 13.5.
This API is for listing Experiments [experiment use in development of GitLab](../development/experiment_guide/index.md).
All methods require user be a [GitLab team member](https://gitlab.com/groups/gitlab-com/-/group_members) for authorization.
## List all experiments
Get a list of all experiments, with its enabled status.
```plaintext
GET /experiments
```
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/experiments"
```
Example response:
```json
[
{
"key": "experiment_1",
"enabled": true
},
{
"key": "experiment_2",
"enabled": false
}
]
```

View File

@ -87,10 +87,12 @@ the `plan` parameter associated with a namespace:
]
```
Users on GitLab.com will also see a `max_seats_used` parameter. `max_seats_used`
is the highest number of users the group had.
Users on GitLab.com will also see `max_seats_used` and `seats_in_use` parameters.
`max_seats_used` is the highest number of users the group had. `seats_in_use` is
the number of license seats currently being used. Both values are updated
once a day.
`max_seats_used` will be non-zero only for namespaces on paid plans.
`max_seats_used` and `seats_in_use` will be non-zero only for namespaces on paid plans.
```json
[
@ -99,6 +101,7 @@ is the highest number of users the group had.
"name": "user1",
"billable_members_count": 2,
"max_seats_used": 3,
"seats_in_use": 2,
...
}
]
@ -141,6 +144,7 @@ Example response:
"members_count_with_descendants": 2,
"billable_members_count": 2,
"max_seats_used": 0,
"seats_in_use": 0,
"plan": "default",
"trial_ends_on": null,
"trial": false
@ -181,6 +185,7 @@ Example response:
"members_count_with_descendants": 2,
"billable_members_count": 2,
"max_seats_used": 0,
"seats_in_use": 0,
"plan": "default",
"trial_ends_on": null,
"trial": false
@ -208,6 +213,7 @@ Example response:
"members_count_with_descendants": 2,
"billable_members_count": 2,
"max_seats_used": 0,
"seats_in_use": 0,
"plan": "default",
"trial_ends_on": null,
"trial": false

View File

@ -83,12 +83,17 @@ POST /projects/:id/snippets
Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `title` (required) - The title of a snippet
- `file_name` (required) - The name of a snippet file
- `description` (optional) - The description of a snippet
- `content` (required) - The content of a snippet
- `visibility` (required) - The snippet's visibility
| Attribute | Type | Required | Description |
|:------------------|:----------------|:---------|:----------------------------------------------------------------------------------------------------------------|
| `id` | integer | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `title` | string | yes | Title of a snippet |
| `file_name` | string | no | Deprecated: Use `files` instead. Name of a snippet file |
| `content` | string | no | Deprecated: Use `files` instead. Content of a snippet |
| `description` | string | no | Description of a snippet |
| `visibility` | string | no | Snippet's [visibility](#snippet-visibility-level) |
| `files` | array of hashes | no | An array of snippet files |
| `files:file_path` | string | yes | File path of the snippet file |
| `files:content` | string | yes | Content of the snippet file |
Example request:
@ -105,9 +110,13 @@ curl --request POST "https://gitlab.com/api/v4/projects/:id/snippets" \
{
"title" : "Example Snippet Title",
"description" : "More verbose snippet description",
"file_name" : "example.txt",
"content" : "source code \n with multiple lines\n",
"visibility" : "private"
"visibility" : "private",
"files": [
{
"file_path": "example.txt",
"content" : "source code \n with multiple lines\n",
}
]
}
```
@ -121,13 +130,22 @@ PUT /projects/:id/snippets/:snippet_id
Parameters:
- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user
- `snippet_id` (required) - The ID of a project's snippet
- `title` (optional) - The title of a snippet
- `file_name` (optional) - The name of a snippet file
- `description` (optional) - The description of a snippet
- `content` (optional) - The content of a snippet
- `visibility` (optional) - The snippet's visibility
| Attribute | Type | Required | Description |
|:----------------------|:----------------|:---------|:----------------------------------------------------------------------------------------------------------------|
| `id` | integer | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user |
| `snippet_id` | integer | yes | The ID of a project's snippet |
| `title` | string | no | Title of a snippet |
| `file_name` | string | no | Deprecated: Use `files` instead. Name of a snippet file |
| `content` | string | no | Deprecated: Use `files` instead. Content of a snippet |
| `description` | string | no | Description of a snippet |
| `visibility` | string | no | Snippet's [visibility](#snippet-visibility-level) |
| `files` | array of hashes | no | An array of snippet files |
| `files:action` | string | yes | Type of action to perform on the file, one of: 'create', 'update', 'delete', 'move' |
| `files:file_path` | string | no | File path of the snippet file |
| `files:previous_path` | string | no | Previous path of the snippet file |
| `files:content` | string | no | Content of the snippet file |
Updates to snippets with multiple files *must* use the `files` attribute.
Example request:
@ -144,9 +162,14 @@ curl --request PUT "https://gitlab.com/api/v4/projects/:id/snippets/:snippet_id"
{
"title" : "Updated Snippet Title",
"description" : "More verbose snippet description",
"file_name" : "new_filename.txt",
"content" : "updated source code \n with multiple lines\n",
"visibility" : "private"
"visibility" : "private",
"files": [
{
"action": "update",
"file_path": "example.txt",
"content" : "updated source code \n with multiple lines\n"
}
]
}
```

View File

@ -2241,6 +2241,113 @@ PUT /projects/:id/transfer
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) |
| `namespace` | integer/string | yes | The ID or path of the namespace to transfer to project to |
Example request:
```shell
curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/transfer?namespace=14"
```
Example response:
```json
{
"id": 7,
"description": "",
"name": "hello-world",
"name_with_namespace": "cute-cats / hello-world",
"path": "hello-world",
"path_with_namespace": "cute-cats/hello-world",
"created_at": "2020-10-15T16:25:22.415Z",
"default_branch": "master",
"tag_list": [],
"ssh_url_to_repo": "git@gitlab.example.com:cute-cats/hello-world.git",
"http_url_to_repo": "https://gitlab.example.com/cute-cats/hello-world.git",
"web_url": "https://gitlab.example.com/cute-cats/hello-world",
"readme_url": "https://gitlab.example.com/cute-cats/hello-world/-/blob/master/README.md",
"avatar_url": null,
"forks_count": 0,
"star_count": 0,
"last_activity_at": "2020-10-15T16:25:22.415Z",
"namespace": {
"id": 18,
"name": "cute-cats",
"path": "cute-cats",
"kind": "group",
"full_path": "cute-cats",
"parent_id": null,
"avatar_url": null,
"web_url": "https://gitlab.example.com/groups/cute-cats"
},
"_links": {
"self": "https://gitlab.example.com/api/v4/projects/7",
"issues": "https://gitlab.example.com/api/v4/projects/7/issues",
"merge_requests": "https://gitlab.example.com/api/v4/projects/7/merge_requests",
"repo_branches": "https://gitlab.example.com/api/v4/projects/7/repository/branches",
"labels": "https://gitlab.example.com/api/v4/projects/7/labels",
"events": "https://gitlab.example.com/api/v4/projects/7/events",
"members": "https://gitlab.example.com/api/v4/projects/7/members"
},
"packages_enabled": true,
"empty_repo": false,
"archived": false,
"visibility": "private",
"resolve_outdated_diff_discussions": false,
"container_registry_enabled": true,
"container_expiration_policy": {
"cadence": "7d",
"enabled": false,
"keep_n": null,
"older_than": null,
"name_regex": null,
"name_regex_keep": null,
"next_run_at": "2020-10-22T16:25:22.746Z"
},
"issues_enabled": true,
"merge_requests_enabled": true,
"wiki_enabled": true,
"jobs_enabled": true,
"snippets_enabled": true,
"service_desk_enabled": false,
"service_desk_address": null,
"can_create_merge_request_in": true,
"issues_access_level": "enabled",
"repository_access_level": "enabled",
"merge_requests_access_level": "enabled",
"forking_access_level": "enabled",
"wiki_access_level": "enabled",
"builds_access_level": "enabled",
"snippets_access_level": "enabled",
"pages_access_level": "enabled",
"emails_disabled": null,
"shared_runners_enabled": true,
"lfs_enabled": true,
"creator_id": 2,
"import_status": "none",
"open_issues_count": 0,
"ci_default_git_depth": 50,
"public_jobs": true,
"build_timeout": 3600,
"auto_cancel_pending_pipelines": "enabled",
"build_coverage_regex": null,
"ci_config_path": null,
"shared_with_groups": [],
"only_allow_merge_if_pipeline_succeeds": false,
"allow_merge_on_skipped_pipeline": null,
"request_access_enabled": true,
"only_allow_merge_if_all_discussions_are_resolved": false,
"remove_source_branch_after_merge": true,
"printing_merge_request_link_enabled": true,
"merge_method": "merge",
"suggestion_commit_message": null,
"auto_devops_enabled": true,
"auto_devops_deploy_strategy": "continuous",
"autoclose_referenced_issues": true,
"approvals_before_merge": 0,
"mirror": false,
"compliance_frameworks": []
}
```
## Branches
Read more in the [Branches](branches.md) documentation.

View File

@ -198,22 +198,40 @@ POST /snippets
Parameters:
| Attribute | Type | Required | Description |
|:--------------|:-------|:---------|:---------------------------------------------------|
| `title` | string | yes | Title of a snippet. |
| `file_name` | string | yes | Name of a snippet file. |
| `content` | string | yes | Content of a snippet. |
| `description` | string | no | Description of a snippet. |
| `visibility` | string | no | Snippet's [visibility](#snippet-visibility-level). |
| Attribute | Type | Required | Description |
|:------------------|:----------------|:---------|:--------------------------------------------------------|
| `title` | string | yes | Title of a snippet |
| `file_name` | string | no | Deprecated: Use `files` instead. Name of a snippet file |
| `content` | string | no | Deprecated: Use `files` instead. Content of a snippet |
| `description` | string | no | Description of a snippet |
| `visibility` | string | no | Snippet's [visibility](#snippet-visibility-level) |
| `files` | array of hashes | no | An array of snippet files |
| `files:file_path` | string | yes | File path of the snippet file |
| `files:content` | string | yes | Content of the snippet file |
Example request:
```shell
curl --request POST \
--data '{"title": "This is a snippet", "content": "Hello world", "description": "Hello World snippet", "file_name": "test.txt", "visibility": "internal" }' \
curl --request POST "https://gitlab.example.com/api/v4/snippets" \
--header 'Content-Type: application/json' \
--header "PRIVATE-TOKEN: <your_access_token>" \
"https://gitlab.example.com/api/v4/snippets"
-d @snippet.json
```
`snippet.json` used in the above example request:
```json
{
"title": "This is a snippet",
"description": "Hello World snippet",
"visibility": "internal",
"files": [
{
"content": "Hello world",
"file_path": "test.txt"
}
]
}
```
Example response:
@ -222,7 +240,6 @@ Example response:
{
"id": 1,
"title": "This is a snippet",
"file_name": "test.txt",
"description": "Hello World snippet",
"visibility": "internal",
"author": {
@ -238,7 +255,16 @@ Example response:
"created_at": "2012-06-28T10:52:04Z",
"project_id": null,
"web_url": "http://example.com/snippets/1",
"raw_url": "http://example.com/snippets/1/raw"
"raw_url": "http://example.com/snippets/1/raw",
"ssh_url_to_repo": "ssh://git@gitlab.example.com:snippets/1.git",
"http_url_to_repo": "https://gitlab.example.com/snippets/1.git",
"file_name": "test.txt",
"files": [
{
"path": "text.txt",
"raw_url": "https://gitlab.example.com/-/snippets/1/raw/master/renamed.md"
}
]
}
```
@ -255,23 +281,44 @@ PUT /snippets/:id
Parameters:
| Attribute | Type | Required | Description |
|:--------------|:--------|:---------|:---------------------------------------------------|
| `id` | integer | yes | ID of snippet to update. |
| `title` | string | no | Title of a snippet. |
| `file_name` | string | no | Name of a snippet file. |
| `description` | string | no | Description of a snippet. |
| `content` | string | no | Content of a snippet. |
| `visibility` | string | no | Snippet's [visibility](#snippet-visibility-level). |
| Attribute | Type | Required | Description |
|:----------------------|:----------------|:---------|:------------------------------------------------------------------------------------|
| `id` | integer | yes | ID of snippet to update |
| `title` | string | no | Title of a snippet |
| `file_name` | string | no | Deprecated: Use `files` instead. Name of a snippet file |
| `content` | string | no | Deprecated: Use `files` instead. Content of a snippet |
| `description` | string | no | Description of a snippet |
| `visibility` | string | no | Snippet's [visibility](#snippet-visibility-level) |
| `files` | array of hashes | no | An array of snippet files |
| `files:action` | string | yes | Type of action to perform on the file, one of: 'create', 'update', 'delete', 'move' |
| `files:file_path` | string | no | File path of the snippet file |
| `files:previous_path` | string | no | Previous path of the snippet file |
| `files:content` | string | no | Content of the snippet file |
Updates to snippets with multiple files *must* use the `files` attribute.
Example request:
```shell
curl --request PUT \
--data '{"title": "foo", "content": "bar"}' \
curl --request PUT "https://gitlab.example.com/api/v4/snippets/1" \
--header 'Content-Type: application/json' \
--header "PRIVATE-TOKEN: <your_access_token>" \
"https://gitlab.example.com/api/v4/snippets/1"
-d @snippet.json
```
`snippet.json` used in the above example request:
```json
{
"title": "foo",
"files": [
{
"action": "move",
"previous_path": "test.txt",
"file_path": "renamed.md"
}
]
}
```
Example response:
@ -280,7 +327,6 @@ Example response:
{
"id": 1,
"title": "test",
"file_name": "add.rb",
"description": "description of snippet",
"visibility": "internal",
"author": {
@ -296,7 +342,16 @@ Example response:
"created_at": "2012-06-28T10:52:04Z",
"project_id": null,
"web_url": "http://example.com/snippets/1",
"raw_url": "http://example.com/snippets/1/raw"
"raw_url": "http://example.com/snippets/1/raw",
"ssh_url_to_repo": "ssh://git@gitlab.example.com:snippets/1.git",
"http_url_to_repo": "https://gitlab.example.com/snippets/1.git",
"file_name": "renamed.md",
"files": [
{
"path": "renamed.md",
"raw_url": "https://gitlab.example.com/-/snippets/1/raw/master/renamed.md"
}
]
}
```

View File

@ -176,7 +176,7 @@ class ChangeUsersUsernameStringToText < ActiveRecord::Migration[4.2]
end
def down
cleanup_concurrent_column_type_change :users, :username
undo_change_column_type_concurrently :users, :username
end
end
```
@ -197,7 +197,7 @@ class ChangeUsersUsernameStringToTextCleanup < ActiveRecord::Migration[4.2]
end
def down
change_column_type_concurrently :users, :username, :string
undo_cleanup_concurrent_column_type_change :users, :username, :string
end
end
```

View File

@ -58,7 +58,7 @@ To create a new blank project on the **New project** page:
Project templates can pre-populate a new project with the necessary files to get you
started quickly.
There are two types of project templates:
There are two main types of project templates:
- [Built-in templates](#built-in-templates), sourced from the following groups:
- [`project-templates`](https://gitlab.com/gitlab-org/project-templates)

View File

@ -204,6 +204,19 @@ Select the **To-Do List** **{todo-done}** in the navigation bar to view your cur
![Alert Details Added to do](./img/alert_detail_added_todo_v13_1.png)
## Link runbooks to alerts
> Runbook URLs [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/39315) in GitLab 13.3.
When creating alerts from the metrics dashboard for
[managed Prometheus instances](../metrics/alerts.md#managed-prometheus-instances),
you can link a runbook. When the alert triggers, you can access the runbook through
the [chart context menu](../metrics/dashboards/index.md#chart-context-menu) in the
upper-right corner of the metrics chart, making it easy for you to locate and access
the correct runbook:
![Linked Runbook in charts](img/link_runbooks_to_alerts_v13_5.png)
## View the environment that generated the alert
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232492) in GitLab 13.5.

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

View File

@ -6,74 +6,53 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Project integration management
Project integrations can be configured and enabled by project administrators. As a GitLab instance administrator, you can set default configuration parameters for a given integration that all projects can inherit and use, enabling the integration for all projects that are not already using custom settings.
Project integrations can be configured and enabled by project administrators. As a GitLab instance
administrator, you can set default configuration parameters for a given integration that all projects
can inherit and use. This enables the integration for all projects that are not already using custom
settings.
You can update these default settings at any time, changing the settings used for all
projects that are set to use instance-level or group-level defaults. Updating the
default settings also enables the integration for all projects that didn't have it
already enabled.
You can update these default settings at any time, changing the settings used for all projects that
are set to use instance-level defaults. Updating the default settings also enables the integration
for all projects that didn't have it already enabled.
Only the complete settings for an integration can be inherited. Per-field inheritance is [planned](https://gitlab.com/groups/gitlab-org/-/epics/2137).
Only the complete settings for an integration can be inherited. Per-field inheritance is
[planned](https://gitlab.com/groups/gitlab-org/-/epics/2137) as is
[group-level management](https://gitlab.com/groups/gitlab-org/-/epics/2543) of integration settings.
## Manage instance-level default settings for a project integration **(CORE ONLY)**
> [Introduced in](https://gitlab.com/groups/gitlab-org/-/epics/2137) GitLab 13.3.
1. Navigate to **Admin Area > Settings > Integrations**.
1. Select an integration.
1. Select a project integration.
1. Enter configuration details and click **Save changes**.
CAUTION: **Caution:**
This may affect all or most of the groups and projects on your GitLab instance. Please review the details below.
This may affect all or most of the projects on your GitLab instance. Please review the details
below.
If this is the first time you are setting up instance-level settings for an integration:
- The integration is enabled for all groups and projects that do not already have this integration configured if you have the **Enable integration** toggle turned on in the instance-level settings.
- Groups and projects that already have the integration configured are not affected, but can choose to use the inherited settings at any time.
- The integration is enabled for all projects that don't already have this integration configured,
if you have the **Enable integration** toggle turned on in the instance-level settings.
- Projects that already have the integration configured are not affected, but can choose to use the
inherited settings at any time.
When you make further changes to the instance defaults:
- They are immediately applied to all groups and projects that have the integration set to use default settings.
- They are immediately applied to newer groups and projects, created since you last
saved defaults for the integration. If your instance-level default setting has the
**Enable integration** toggle turned on, the integration is automatically enabled for
all such groups and projects.
- Groups and projects with custom settings selected for the integration are not immediately affected and may choose to use the latest defaults at any time.
- They are immediately applied to all projects that have the integration set to use default settings.
- They are immediately applied to newer projects, created since you last saved defaults for the
integration. If your instance-level default setting has the **Enable integration** toggle turned
on, the integration is automatically enabled for all such projects.
- Projects with custom settings selected for the integration are not immediately affected and may
choose to use the latest defaults at any time.
Only the complete settings for an integration can be inherited. Per-field inheritance
is [planned](https://gitlab.com/groups/gitlab-org/-/epics/2137). This would allow
administrators to update settings inherited by groups and projects without enabling the
integration on all non-configured groups and projects by default.
administrators to update settings inherited by projects without enabling the
integration on all non-configured projects by default.
## Manage group-level default settings for a project integration
> [Introduced in](https://gitlab.com/groups/gitlab-org/-/epics/2543) GitLab 13.5.
1. Navigate to the group's **Settings > Integrations**.
1. Select an integration.
1. Enter configuration details and click **Save changes**.
CAUTION: **Caution:**
This may affect all or most of the subgroups and projects belonging to the group. Please review the details below.
If this is the first time you are setting up group-level settings for an integration:
- The integration is enabled for all subgroups and projects belonging to the group that do not already have this integration configured if you have the **Enable integration** toggle turned on in the group-level settings.
- Subgroups and projects that already have the integration configured are not affected, but can choose to use the inherited settings at any time.
When you make further changes to the group defaults:
- They are immediately applied to all subgroups and projects belonging to the group that have the integration set to use default settings.
- They are immediately applied to newer subgroups and projects, created since you last saved defaults for the integration.
- If your group-level default setting has the **Enable integration** toggle turned on, the integration is automatically enabled for all such subgroups and projects.
- Subgroups and projects with custom settings selected for the integration are not immediately affected and may choose to use the latest defaults at any time.
Only the complete settings for an integration can be inherited. Per-field inheritance
is [planned](https://gitlab.com/groups/gitlab-org/-/epics/2137). This would allow
administrators to update settings inherited by subgroups and projects without enabling the
integration on all non-configured groups and projects by default.
## Use instance-level or group-level default settings for a project integration
## Use instance-level default settings for a project integration
1. Navigate to **Project > Settings > Integrations**.
1. Choose the integration you want to enable or update.
@ -81,9 +60,9 @@ integration on all non-configured groups and projects by default.
1. Ensure the toggle is set to **Enable integration**.
1. Click **Save changes**.
## Use custom settings for a group or project integration
## Use custom settings for a project integration
1. Navigate to project or group's **Settings > Integrations**.
1. Navigate to project's **Settings > Integrations**.
1. Choose the integration you want to enable or update.
1. From the drop-down, select **Use custom settings**.
1. Ensure the toggle is set to **Enable integration** and enter all required settings.

View File

@ -742,7 +742,6 @@ To enable prevent project forking:
- **Audit Events**: View [Audit Events](../../administration/audit_events.md)
for the group. **(STARTER ONLY)**
- **Pipelines quota**: Keep track of the [pipeline quota](../admin_area/settings/continuous_integration.md) for the group.
- **Integrations**: Configure [integrations](../admin_area/settings/project_integration_management.md) for your group.
#### Storage usage quota **(STARTER)**

View File

@ -82,7 +82,7 @@ We flag any significant differences between Redcarpet and CommonMark Markdown in
If you have a large volume of Markdown files, it can be tedious to determine
if they display correctly or not. You can use the
[diff_redcarpet_cmark](https://gitlab.com/digitalmoksha/diff_redcarpet_cmark)
[`diff_redcarpet_cmark`](https://gitlab.com/digitalmoksha/diff_redcarpet_cmark)
tool (not an officially supported product) to generate a list of files and the
differences between how RedCarpet and CommonMark render the files. It gives
an indication if anything needs to be changed - often nothing needs

View File

@ -67,7 +67,7 @@ Images follow this naming convention:
```
If your project is `gitlab.example.com/mynamespace/myproject`, for example,
then your image must be named `gitlab.example.com/mynamespace/myproject/my-app` at a mimimum.
then your image must be named `gitlab.example.com/mynamespace/myproject/my-app` at a minimum.
You can append additional names to the end of an image name, up to three levels deep.

View File

@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Monorepo package management workflows
Oftentimes, one project or Git repository may contain multiple different
subprojects or submodules that all get packaged and published individually.
sub-projects or submodules that all get packaged and published individually.
## Publishing different packages to the parent project
@ -36,9 +36,9 @@ as well as `Foo`.
Following the instructions in the
[GitLab NPM registry documentation](../npm_registry/index.md),
publishing `MyProject` consists of modifying the `package.json` file with a
`publishConfig` section, as well as either modifying your local NPM config with
`publishConfig` section, as well as either modifying your local NPM configuration with
CLI commands like `npm config set`, or saving a `.npmrc` file in the root of the
project specifying these config settings.
project specifying these configuration settings.
If you follow the instructions you can publish `MyProject` by running
`npm publish` from the root directory.
@ -65,7 +65,7 @@ A package is associated with a project on GitLab, but the package does not
need to be associated with the code in that project. Notice when configuring
NPM or Maven, you only use the `Project ID` to set the registry URL that the
package is to be uploaded to. If you set this to any project that you have
access to and update any other config similarly depending on the package type,
access to and update any other configuration similarly depending on the package type,
your packages are published to that project. This means you can publish
multiple packages to one project, even if their code does not exist in the same
place. See the [project registry workflow documentation](./project_registry.md)

View File

@ -399,7 +399,7 @@ Administrators can add members with a "minimal access" role to a parent group. S
automatically have access to projects and subgroups underneath. To support such access, administrators must explicitly add these "minimal access" users to the specific subgroups/projects.
Users with minimal access can list the group in the UI and through the API. However, they cannot see
details such as projects or subgroups. They do not have access to the group's page or list any of itssubgroups or projects.
details such as projects or subgroups. They do not have access to the group's page or list any of its subgroups or projects.
## Project features

View File

@ -84,7 +84,7 @@ The default syntax theme is White, and you can choose among 5 different themes:
[Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2389) in 13.0, the theme
you choose also applies to the [Web IDE](../project/web_ide/index.md)'s code editor and [Snippets](../snippets.md).
The themes are available only in the Web IDE file editor, except for the [dark theme](https://gitlab.com/gitlab-org/gitlab/-/issues/209808) and
the [solarized dark theme](https://gitlab.com/gitlab-org/gitlab/-/issues/219228),
the [Solarized dark theme](https://gitlab.com/gitlab-org/gitlab/-/issues/219228),
which apply to the entire Web IDE screen.
## Behavior
@ -131,15 +131,9 @@ You can choose between 2 options:
### Project overview content
The project overview content setting allows you to choose what content you want to
The **Project overview content** setting allows you to choose what content you want to
see on a projects home page.
You can choose between 3 options:
- Files and Readme (default)
- Readme
- Activity
### Tab width
You can set the displayed width of tab characters across various parts of

View File

@ -252,7 +252,7 @@ GitLab CI/CD build environment.
| `KUBE_NAMESPACE` | The namespace associated with the project's deployment service account. In the format `<project_name>-<project_id>-<environment>`. For GitLab-managed clusters, a matching namespace is automatically created by GitLab in the cluster. If your cluster was created before GitLab 12.2, the default `KUBE_NAMESPACE` is set to `<project_name>-<project_id>`. |
| `KUBE_CA_PEM_FILE` | Path to a file containing PEM data. Only present if a custom CA bundle was specified. |
| `KUBE_CA_PEM` | (**deprecated**) Raw PEM data. Only if a custom CA bundle was specified. |
| `KUBECONFIG` | Path to a file containing `kubeconfig` for this deployment. CA bundle would be embedded if specified. This config also embeds the same token defined in `KUBE_TOKEN` so you likely will only need this variable. This variable name is also automatically picked up by `kubectl` so you won't actually need to reference it explicitly if using `kubectl`. |
| `KUBECONFIG` | Path to a file containing `kubeconfig` for this deployment. CA bundle would be embedded if specified. This configuration also embeds the same token defined in `KUBE_TOKEN` so you likely will only need this variable. This variable name is also automatically picked up by `kubectl` so you won't actually need to reference it explicitly if using `kubectl`. |
| `KUBE_INGRESS_BASE_DOMAIN` | From GitLab 11.8, this variable can be used to set a domain per cluster. See [cluster domains](#base-domain) for more information. |
### Custom namespace

View File

@ -789,7 +789,7 @@ or with other versions of Python.
kubectl edit gateway knative-ingress-gateway --namespace knative-serving
```
Update the gateway to include the following tls: section and configuration:
Update the gateway to include the following `tls:` section and configuration:
```shell
tls:

View File

@ -58,9 +58,9 @@ relevant language.
| Language | Implementation |
|---|---|
| Go | [sourcegraph/lsif-go](https://github.com/sourcegraph/lsif-go) |
| JavaScript | [sourcegraph/lsif-node](https://github.com/sourcegraph/lsif-node) |
| TypeScript | [sourcegraph/lsif-node](https://github.com/sourcegraph/lsif-node) |
| Go | [`sourcegraph/lsif-go`](https://github.com/sourcegraph/lsif-go) |
| JavaScript | [`sourcegraph/lsif-node`](https://github.com/sourcegraph/lsif-node) |
| TypeScript | [`sourcegraph/lsif-node`](https://github.com/sourcegraph/lsif-node) |
View a complete list of [available LSIF indexers](https://lsif.dev/#implementations-server) on their website and
refer to their documentation to see how to generate an LSIF file for your specific language.

View File

@ -75,7 +75,6 @@ be used for merge request approvals:
- As [merge request eligible approvers](merge_requests/merge_request_approvals.md#code-owners-as-eligible-approvers).
- As required approvers for [protected branches](protected_branches.md#protected-branches-approval-by-code-owners). **(PREMIUM)**
NOTE: **Note:**
Developer or higher [permissions](../permissions.md) are required in order to
approve a merge request.
@ -93,12 +92,14 @@ to specify the actual owners and granular permissions.
Using Code Owners in conjunction with [Protected Branches](protected_branches.md#protected-branches-approval-by-code-owners)
will prevent any user who is not specified in the `CODEOWNERS` file from pushing
changes for the specified files/paths, even if their role is included in the
changes for the specified files/paths, except those included in the
**Allowed to push** column. This allows for a more inclusive push strategy, as
administrators don't have to restrict developers from pushing directly to the
protected branch, but can restrict pushing to certain files where a review by
Code Owners is required.
[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35097) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.5, users and groups who are allowed to push to protected branches do not require a merge request to merge their feature branches. Thus, they can skip merge request approval rules, Code Owners included.
## The syntax of Code Owners files
Files can be specified using the same kind of patterns you would use

View File

@ -85,7 +85,7 @@ To display the Deploy Boards for a specific [environment](../../ci/environments/
[`kubernetes`](https://docs.gitlab.com/runner/executors/kubernetes.html) executor.
1. Configure the [Kubernetes integration](clusters/index.md) in your project for the
cluster. The Kubernetes namespace is of particular note as you will need it
for your deployment scripts (exposed by the `KUBE_NAMESPACE` env variable).
for your deployment scripts (exposed by the `KUBE_NAMESPACE` environment variable).
1. Ensure Kubernetes annotations of `app.gitlab.com/env: $CI_ENVIRONMENT_SLUG`
and `app.gitlab.com/app: $CI_PROJECT_PATH_SLUG` are applied to the
deployments, replica sets, and pods, where `$CI_ENVIRONMENT_SLUG` and

View File

@ -69,7 +69,7 @@ brew install git-lfs
```
Once installed, **open your local repository in a terminal window** and
install Git LFS in your repo. If you're sure that LFS is already installed,
install Git LFS in your repository. If you're sure that LFS is already installed,
you can skip this step. If you're unsure, re-installing it won't do any harm:
```shell
@ -159,7 +159,7 @@ command line interface, file locks can be created for any file.
### View exclusively-locked files
To list all the files locked with LFS locally, open a terminal window in your
repo and run:
repository and run:
```shell
git lfs locks
@ -189,7 +189,7 @@ Suggested workflow for shared projects:
1. Lock the file.
1. Edit the file.
1. Commit your changes.
1. Push to the repo.
1. Push to the repository.
1. Get your changes reviewed, approved, and merged.
1. Unlock the file.

View File

@ -96,7 +96,7 @@ back to both GitLab and GitHub when completed.
The mirroring is pull-only by default, so you may create or update the file on
GitHub:
![Edit gitlab-ci.yml file](img/gemnasium/edit_gitlab-ci.png)
![Edit YAML file](img/gemnasium/edit_gitlab-ci.png)
1. Once your file has been committed, a new pipeline will be automatically
triggered if your file is valid:

View File

@ -101,7 +101,7 @@ If you are using a self-managed GitLab instance or if you are importing from Git
1. From the top navigation bar, click **+** and select **New project**.
1. Select the **Import project** tab and then select **GitHub**.
1. Select the first button to **List your GitHub repositories**. You are redirected to a page on [GitHub](https://github.com) to authorize the GitLab application.
1. Click **Authorize gitlabhq**. You are redirected back to GitLab's Import page and all of your GitHub repositories are listed.
1. Click **Authorize GitlabHQ**. You are redirected back to GitLab's Import page and all of your GitHub repositories are listed.
1. Continue on to [selecting which repositories to import](#selecting-which-repositories-to-import).
### Using a GitHub token
@ -119,7 +119,7 @@ If you are not using the GitHub integration, you can still perform an authorizat
1. Go to <https://github.com/settings/tokens/new>
1. Enter a token description.
1. Select the repo scope.
1. Select the repository scope.
1. Click **Generate token**.
1. Copy the token hash.
1. Go back to GitLab and provide the token to the GitHub importer.
@ -136,10 +136,10 @@ your GitHub repositories are listed.
1. Select the **Import** button next to any number of repositories, or select **Import all repositories**. Additionally,
you can filter projects by name. If filter is applied, **Import all repositories** only imports matched repositories.
1. The **Status** column shows the import status of each repository. You can choose to leave the page open and it will
update in realtime or you can return to it later.
update in real-time or you can return to it later.
1. Once a repository has been imported, click its GitLab path to open its GitLab URL.
![Github importer page](img/import_projects_from_github_importer_v12_3.png)
![GitHub importer page](img/import_projects_from_github_importer_v12_3.png)
## Mirroring and pipeline status sharing
@ -149,7 +149,7 @@ your imported repository in sync with its GitHub copy.
Additionally, you can configure GitLab to send pipeline status updates back GitHub with the
[GitHub Project Integration](../integrations/github.md). **(PREMIUM)**
If you import your project using [CI/CD for external repo](../../../ci/ci_cd_for_external_repos/index.md), then both
If you import your project using [CI/CD for external repository](../../../ci/ci_cd_for_external_repos/index.md), then both
of the above are automatically configured. **(PREMIUM)**
## Improving the speed of imports on self-managed instances

View File

@ -18,7 +18,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
1. [From Perforce](perforce.md)
1. [From SVN](svn.md)
1. [From TFVC](tfvc.md)
1. [From repo by URL](repo_by_url.md)
1. [From repository by URL](repo_by_url.md)
1. [By uploading a manifest file (AOSP)](manifest.md)
1. [From Gemnasium](gemnasium.md)
1. [From Phabricator](phabricator.md)
@ -32,7 +32,7 @@ There is also the option of [connecting your external repository to get CI/CD be
## Migrating from self-managed GitLab to GitLab.com
If you only need to migrate Git repos, you can [import each project by URL](repo_by_url.md). Issues and merge requests can't be imported.
If you only need to migrate Git repositories, you can [import each project by URL](repo_by_url.md). Issues and merge requests can't be imported.
If you want to retain all metadata like issues and merge requests, you can use
the [import/export feature](../settings/import_export.md) to export projects from self-managed GitLab and import those projects into GitLab.com.

View File

@ -56,7 +56,7 @@ You can start the import with:
1. From your GitLab dashboard click **New project**
1. Switch to the **Import project** tab
1. Click on the **Manifest file** button
1. Provide GitLab with a manifest xml file
1. Provide GitLab with a manifest XML file
1. Select a group you want to import to (you need to create a group first if you don't have one)
1. Click **List available repositories**. At this point, you will be redirected
to the import status page with projects list based on the manifest file.

View File

@ -20,7 +20,7 @@ Git:
it creates an integration record in their proprietary database for every file
in the branch, regardless how many were actually changed. Whereas Git was
implemented with a different architecture so that a single SHA acts as a pointer
to the state of the whole repo after the changes, making it very easy to branch.
to the state of the whole repository after the changes, making it very easy to branch.
This is what made feature branching workflows so easy to adopt with Git.
1. Also, context switching between branches is much easier in Git. If your manager
said 'You need to stop work on that new feature and fix this security

View File

@ -5,7 +5,7 @@ group: Import
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/#designated-technical-writers
---
# Import project from repo by URL
# Import project from repository by URL
You can import your existing repositories by providing the Git URL:
@ -16,4 +16,4 @@ You can import your existing repositories by providing the Git URL:
1. Click **Create project** to begin the import process
1. Once complete, you will be redirected to your newly created project
![Import project by repo URL](img/import_projects_from_repo_url.png)
![Import project by repository URL](img/import_projects_from_repo_url.png)

View File

@ -14,8 +14,8 @@ See the project homepage for further information: <https://gitlab.com/esr/irker>
## Needed setup
You will first need an Irker daemon. You can download the Irker code from its
repository on <https://gitlab.com/esr/irker>:
You will first need an Irker daemon. You can download the Irker code
[from its repository](https://gitlab.com/esr/irker):
```shell
git clone https://gitlab.com/esr/irker.git
@ -55,6 +55,6 @@ case, `Aorimn` is treated as a nick and no more as a channel name.
Irker can also join password-protected channels. Users need to append
`?key=thesecretpassword` to the channel name. When using this feature remember to
**not** put the `#` sign in front of the channel name; failing to do so will
result on irker joining a channel literally named `#chan?key=password` henceforth
result on Irker joining a channel literally named `#chan?key=password` henceforth
leaking the channel key through the `/whois` IRC command (depending on IRC server
configuration). This is due to a long standing irker bug.
configuration). This is due to a long standing Irker bug.

View File

@ -368,7 +368,7 @@ If you're not able to do some of the things above, make sure you have the right
### First time using an issue board
> The automatic creation of the **To Do** and **Doing** lists was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202144) in GitLab 13.4.
> The automatic creation of the **To Do** and **Doing** lists was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/202144) in GitLab 13.5.
The first time you open an issue board, you are presented with the default lists
(**Open**, **To Do**, **Doing**, and **Closed**).

View File

@ -55,7 +55,7 @@ include:
```
creates an `a11y` job in your CI/CD pipeline, runs
Pa11y against the webpages defined in `a11y_urls`, and builds an HTML report for each.
Pa11y against the web pages defined in `a11y_urls`, and builds an HTML report for each.
The report for each URL is saved as an artifact that can be [viewed directly in your browser](../../../ci/pipelines/job_artifacts.md#browsing-artifacts).

View File

@ -164,8 +164,8 @@ For example:
1. Capture the dynamic URL and save it into a `.env` file, e.g. `echo "ENVIRONMENT_URL=$CI_ENVIRONMENT_URL" >> review.env`.
1. Set the `.env` file to be a [job artifact](../../../ci/pipelines/job_artifacts.md#job-artifacts).
1. In the `load_performance` job:
1. Set it to depend on the review job, so it inherits the env file.
1. Set the `K6_DOCKER_OPTIONS` variable with the [Docker cli option for env files](https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file), for example `--env-file review.env`.
1. Set it to depend on the review job, so it inherits the environment file.
1. Set the `K6_DOCKER_OPTIONS` variable with the [Docker CLI option for environment files](https://docs.docker.com/engine/reference/commandline/run/#set-environment-variables--e---env---env-file), for example `--env-file review.env`.
1. Configure the k6 test script to use the environment variable in it's steps.
Your `.gitlab-ci.yml` file might be similar to:

View File

@ -84,7 +84,7 @@ Click **Expand file** on any file to view the changes for that file.
> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-file-by-file-diff-navigation).
For larger merge requests it might sometimes be useful to review single files at a time. To enable,
from your avatar on the top-right navbar, click **Settings**, and go to **Preferences** on the left
from your avatar on the top-right navigation bar, click **Settings**, and go to **Preferences** on the left
sidebar. Scroll down to the **Behavior** section and select **Show one file at a time on merge request's Changes tab**.
Click **Save changes** to apply.

View File

@ -65,8 +65,8 @@ meaningful commit messages and:
## Enabling squash for a merge request
Anyone who can create or edit a merge request can choose for it to be squashed
on the merge request form. Users can select or unselect the checkbox at the moment
they are creating the merge request:
on the merge request form. Users can select or clear the check box when they
create the merge request:
![Squash commits checkbox on edit form](img/squash_edit_form.png)

View File

@ -30,6 +30,8 @@ to do it for you.
To help you out, we've gathered some instructions on how to do that
for the most popular hosting services:
<!-- vale gitlab.Spelling = NO -->
- [Amazon](https://docs.aws.amazon.com/AmazonS3/latest/dev/website-hosting-custom-domain-walkthrough.html)
- [Bluehost](https://www.bluehost.com/help/article/dns-management-add-edit-or-delete-dns-entries)
- [Cloudflare](https://support.cloudflare.com/hc/en-us/articles/201720164-Creating-a-Cloudflare-account-and-adding-a-website)
@ -41,6 +43,8 @@ for the most popular hosting services:
- [Media Temple](https://mediatemple.net/community/products/dv/204403794/how-can-i-change-the-dns-records-for-my-domain)
- [Microsoft](https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/bb727018(v=technet.10))
<!-- vale gitlab.Spelling = YES -->
If your hosting service is not listed above, you can just try to
search the web for `how to add dns record on <my hosting service>`.

View File

@ -2,4 +2,4 @@
redirect_to: 'pages_ci_cd_template.md'
---
This document was moved to [pages_ci_cd_template.md](pages_ci_cd_template.md).
This document was moved to [another location](pages_ci_cd_template.md).

View File

@ -53,4 +53,4 @@ You can take some **optional** further steps:
![Change repo's path](../img/change_path_v12_10.png)
- Now go to your SSG's configuration file and change the [base URL](../getting_started_part_one.md#urls-and-baseurls)
from `"project-name"` to `""`. The project name setting varies by SSG and may not be in the config file.
from `"project-name"` to `""`. The project name setting varies by SSG and may not be in the configuration file.

View File

@ -185,6 +185,8 @@ When enabled, all merge requests targeting these branches will require approval
by a Code Owner per matched rule before they can be merged.
Additionally, direct pushes to the protected branch are denied if a rule is matched.
[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/35097) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.5, users and groups who are allowed to push to protected branches do not require a merge request to merge their feature branches. Thus, they can skip merge request approval rules.
## Running pipelines on protected branches
The permission to merge or push to protected branches is used to define if a user can

View File

@ -86,7 +86,7 @@ according to the markup language.
| [reStructuredText](https://docutils.sourceforge.io/rst.html) | `rst` |
| [AsciiDoc](../../asciidoc.md) | `adoc`, `ad`, `asciidoc` |
| [Textile](https://textile-lang.com/) | `textile` |
| [rdoc](http://rdoc.sourceforge.net/doc/index.html) | `rdoc` |
| [Rdoc](http://rdoc.sourceforge.net/doc/index.html) | `rdoc` |
| [Org mode](https://orgmode.org/) | `org` |
| [creole](http://www.wikicreole.org/) | `creole` |
| [MediaWiki](https://www.mediawiki.org/wiki/MediaWiki) | `wiki`, `mediawiki` |
@ -234,7 +234,7 @@ lock your files to prevent any conflicting changes.
## Repository's API
You can access your repos via [repository API](../../../api/repositories.md).
You can access your repositories via [repository API](../../../api/repositories.md).
## Clone in Apple Xcode

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

View File

@ -7,7 +7,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Requirements Management **(ULTIMATE)**
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2703) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10.
> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2703) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.10.
> - The ability to add and edit a requirement's long description [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/224622) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.5.
With requirements, you can set criteria to check your products against. They can be based on users,
stakeholders, system, software, or anything else you find important to capture.
@ -22,7 +23,7 @@ When a feature is no longer necessary, you can [archive the related requirement]
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an overview, see [GitLab 12.10 Introduces Requirements Management](https://www.youtube.com/watch?v=uSS7oUNSEoU).
![requirements list view](img/requirements_list_v13_1.png)
![requirements list view](img/requirements_list_v13_5.png)
## Create a requirement
@ -32,31 +33,43 @@ can create a new requirement.
To create a requirement:
1. From your project page, go to **{requirements}** **Requirements**.
1. Click **New requirement**.
1. Enter a descriptive title and click **Create requirement**.
1. Select **New requirement**.
1. Enter a title and description and select **Create requirement**.
You will see the newly created requirement on the top of the list, as the requirements
list is sorted by creation date in descending order.
![requirement create view](img/requirement_create_v13_5.png)
You can see the newly created requirement on the top of the list, with the requirements
list being sorted by creation date, in descending order.
## View a requirement
You can view a requirement from the list by selecting it.
![requirement view](img/requirement_view_v13_5.png)
To edit a requirement while viewing it, select the **Edit** icon (**{pencil}**)
next to the requirement title.
## Edit a requirement
> - [Added](https://gitlab.com/gitlab-org/gitlab/-/issues/218607) ability to mark a requirement as Satisfied in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.5.
> The ability to mark a requirement as Satisfied [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218607) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.5.
You can edit a requirement (if you have the necessary privileges) from the requirements
list page.
To edit a requirement:
1. From the requirements list, click **Edit** (**{pencil}**).
1. Update the title in text input field. You can also mark a requirement as satisfied in the edit form by using the checkbox labeled "Satisfied".
1. Click **Save changes**.
1. From the requirements list, select the **Edit** icon (**{pencil}**).
1. Update the title and description in text input field. You can also mark a
requirement as satisfied in the edit form by using the check box **Satisfied**.
1. Select **Save changes**.
## Archive a requirement
You can archive an open requirement (if you have the necessary privileges) while
you're in the **Open** tab.
To archive a requirement, click **Archive** (**{archive}**).
To archive a requirement, select **Archive** (**{archive}**).
As soon as a requirement is archived, it no longer appears in the **Open** tab.
@ -66,7 +79,7 @@ You can view the list of archived requirements in the **Archived** tab.
![archived requirements list](img/requirements_archived_list_view_v13_1.png)
To reopen an archived requirement, click **Reopen**.
To reopen an archived requirement, select **Reopen**.
As soon as a requirement is reopened, it no longer appears in the **Archived** tab.
@ -82,7 +95,7 @@ You can search for a requirement from the requirements list page based on the fo
To search for a requirement:
1. In a project, go to **{requirements}** **Requirements > List**.
1. Click the **Search or filter results** field. A dropdown menu appears.
1. Select the **Search or filter results** field. A dropdown menu appears.
1. Select the requirement author from the dropdown or enter plain text to search by requirement title.
1. Press <kbd>Enter</kbd> on your keyboard to filter the list.

View File

@ -2,6 +2,8 @@
module Banzai
module ReferenceParser
InvalidReferenceType = Class.new(StandardError)
# Returns the reference parser class for the given type
#
# Example:
@ -11,6 +13,8 @@ module Banzai
# This would return the `Banzai::ReferenceParser::IssueParser` class.
def self.[](name)
const_get("#{name.to_s.camelize}Parser", false)
rescue NameError
raise InvalidReferenceType
end
end
end

View File

@ -111,6 +111,7 @@ module Banzai
parser = Banzai::ReferenceParser[type].new(context)
visible.merge(parser.nodes_visible_to_user(user, nodes))
rescue Banzai::ReferenceParser::InvalidReferenceType
end
visible

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