Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-04-06 18:09:02 +00:00
parent 2e1b10493f
commit 0c4a28ded2
82 changed files with 778 additions and 557 deletions

View File

@ -802,7 +802,7 @@ fail-pipeline-early:
GIT_DEPTH: 1
before_script:
- source scripts/utils.sh
- install_api_client_dependencies_with_apt
- install_gitlab_gem
script:
- fail_pipeline_early
# EE: Canonical MR pipelines

View File

@ -29,7 +29,6 @@ review-build-cng:
stage: review-prepare
before_script:
- source ./scripts/utils.sh
- install_api_client_dependencies_with_apk
- install_gitlab_gem
needs:
- job: compile-production-assets

View File

@ -97,26 +97,6 @@ Rails/SaveBang:
- 'ee/spec/models/visible_approvable_spec.rb'
- 'ee/spec/models/vulnerabilities/feedback_spec.rb'
- 'ee/spec/models/vulnerabilities/issue_link_spec.rb'
- 'ee/spec/requests/api/boards_spec.rb'
- 'ee/spec/requests/api/epic_issues_spec.rb'
- 'ee/spec/requests/api/epic_links_spec.rb'
- 'ee/spec/requests/api/epics_spec.rb'
- 'ee/spec/requests/api/geo_nodes_spec.rb'
- 'ee/spec/requests/api/geo_spec.rb'
- 'ee/spec/requests/api/graphql/group/epics_spec.rb'
- 'ee/spec/requests/api/graphql/mutations/epic_tree/reorder_spec.rb'
- 'ee/spec/requests/api/groups_spec.rb'
- 'ee/spec/requests/api/issues_spec.rb'
- 'ee/spec/requests/api/ldap_group_links_spec.rb'
- 'ee/spec/requests/api/merge_request_approval_rules_spec.rb'
- 'ee/spec/requests/api/merge_request_approvals_spec.rb'
- 'ee/spec/requests/api/merge_requests_spec.rb'
- 'ee/spec/requests/api/project_approvals_spec.rb'
- 'ee/spec/requests/api/projects_spec.rb'
- 'ee/spec/requests/api/protected_branches_spec.rb'
- 'ee/spec/requests/api/scim_spec.rb'
- 'ee/spec/requests/api/todos_spec.rb'
- 'ee/spec/requests/lfs_http_spec.rb'
- 'ee/spec/services/approval_rules/finalize_service_spec.rb'
- 'ee/spec/services/approval_rules/update_service_spec.rb'
- 'ee/spec/services/ee/boards/issues/create_service_spec.rb'
@ -566,7 +546,6 @@ RSpec/EmptyLineAfterFinalLetItBe:
- ee/spec/lib/gitlab/graphql/aggregations/vulnerability_statistics/lazy_aggregate_spec.rb
- ee/spec/lib/gitlab/insights/project_insights_config_spec.rb
- ee/spec/lib/gitlab/sitemaps/url_extractor_spec.rb
- ee/spec/migrations/backfill_version_author_and_created_at_spec.rb
- ee/spec/models/analytics/cycle_analytics/group_level_spec.rb
- ee/spec/models/burndown_spec.rb
- ee/spec/models/ci/build_spec.rb
@ -805,9 +784,6 @@ RSpec/EmptyLineAfterFinalLetItBe:
- spec/features/cycle_analytics_spec.rb
- spec/features/dashboard/datetime_on_tooltips_spec.rb
- spec/features/dashboard/merge_requests_spec.rb
- spec/features/error_tracking/user_filters_errors_by_status_spec.rb
- spec/features/error_tracking/user_searches_sentry_errors_spec.rb
- spec/features/error_tracking/user_sees_error_index_spec.rb
- spec/features/file_uploads/group_import_spec.rb
- spec/features/file_uploads/project_import_spec.rb
- spec/features/file_uploads/user_avatar_spec.rb
@ -1017,13 +993,6 @@ RSpec/EmptyLineAfterFinalLetItBe:
- spec/models/blob_viewer/metrics_dashboard_yml_spec.rb
- spec/models/chat_name_spec.rb
- spec/models/chat_team_spec.rb
- spec/models/ci/artifact_blob_spec.rb
- spec/models/ci/build_spec.rb
- spec/models/ci/build_trace_chunk_spec.rb
- spec/models/ci/daily_build_group_report_result_spec.rb
- spec/models/ci/pipeline_spec.rb
- spec/models/ci/runner_spec.rb
- spec/models/ci/stage_spec.rb
- spec/models/clusters/kubernetes_namespace_spec.rb
- spec/models/commit_spec.rb
- spec/models/deploy_token_spec.rb

View File

@ -2,14 +2,20 @@
import $ from 'jquery';
import Cookies from 'js-cookie';
import createFlash from '~/flash';
import { s__ } from '~/locale';
import { localTimeAgo } from './lib/utils/datetime_utility';
import Pager from './pager';
export default class Activities {
constructor(container = '') {
this.container = container;
constructor(containerSelector = '') {
this.containerSelector = containerSelector;
this.containerEl = this.containerSelector
? document.querySelector(this.containerSelector)
: undefined;
this.$contentList = $('.content_list');
Pager.init(20, true, false, (data) => data, this.updateTooltips, this.container);
this.loadActivities();
$('.event-filter-link').on('click', (e) => {
e.preventDefault();
@ -18,13 +24,30 @@ export default class Activities {
});
}
loadActivities() {
Pager.init({
limit: 20,
preload: true,
prepareData: (data) => data,
successCallback: () => this.updateTooltips(),
errorCallback: () =>
createFlash({
message: s__(
'Activity|An error occured while retrieving activity. Reload the page to try again.',
),
parent: this.containerEl,
}),
container: this.containerSelector,
});
}
updateTooltips() {
localTimeAgo($('.js-timeago', '.content_list'));
}
reloadActivities() {
$('.content_list').html('');
Pager.init(20, true, false, (data) => data, this.updateTooltips, this.container);
this.$contentList.html('');
this.loadActivities();
}
toggleFilter(sender) {

View File

@ -10,7 +10,7 @@ export default class CommitsList {
this.$contentList = $('.content_list');
Pager.init(parseInt(limit, 10), false, false, this.processCommits.bind(this));
Pager.init({ limit: parseInt(limit, 10), prepareData: this.processCommits.bind(this) });
this.content = $('#commits-list');
this.searchField = $('#commits-search');

View File

@ -11,7 +11,7 @@ const typeWithPlaceholder = {
const placeholderForType = {
[typeWithPlaceholder.SLACK]: __('Slack channels (e.g. general, development)'),
[typeWithPlaceholder.MATTERMOST]: __('Channel handle (e.g. town-square)'),
[typeWithPlaceholder.MATTERMOST]: __('my-channel'),
};
export default {

View File

@ -8,19 +8,21 @@ const ENDLESS_SCROLL_BOTTOM_PX = 400;
const ENDLESS_SCROLL_FIRE_DELAY_MS = 1000;
export default {
init(
init({
limit = 0,
preload = false,
disable = false,
prepareData = $.noop,
callback = $.noop,
successCallback = $.noop,
errorCallback = $.noop,
container = '',
) {
} = {}) {
this.limit = limit;
this.offset = parseInt(getParameterByName('offset'), 10) || this.limit;
this.disable = disable;
this.prepareData = prepareData;
this.callback = callback;
this.successCallback = successCallback;
this.errorCallback = errorCallback;
this.loading = $(`${container} .loading`).first();
if (preload) {
this.offset = 0;
@ -42,7 +44,7 @@ export default {
})
.then(({ data }) => {
this.append(data.count, this.prepareData(data.html));
this.callback();
this.successCallback();
// keep loading until we've filled the viewport height
if (!this.disable && !this.isScrollable()) {
@ -51,7 +53,8 @@ export default {
this.loading.hide();
}
})
.catch(() => this.loading.hide());
.catch((err) => this.errorCallback(err))
.finally(() => this.loading.hide());
},
append(count, html) {

View File

@ -1,3 +1,4 @@
import Activities from '~/activities';
document.addEventListener('DOMContentLoaded', () => new Activities());
// eslint-disable-next-line no-new
new Activities();

View File

@ -104,12 +104,7 @@ export default {
const firstJobDefined = Boolean(group.jobs?.[0]);
if (!firstJobDefined) {
const currentGroup = this.groups.find((element) => element.name === group.name);
const serializedGroup = Object.entries(currentGroup).join(' ');
reportToSentry(
'stage_column_component',
`undefined_job_hunt, serialized group: ${serializedGroup}`,
);
reportToSentry('stage_column_component', 'undefined_job_hunt');
}
return group.size === 1 && firstJobDefined;

View File

@ -1,3 +1,5 @@
import { reportToSentry } from '../utils';
const unwrapGroups = (stages) => {
return stages.map((stage) => {
const {
@ -8,6 +10,10 @@ const unwrapGroups = (stages) => {
};
const unwrapNodesWithName = (jobArray, prop, field = 'name') => {
if (jobArray.length < 1) {
reportToSentry('unwrapping_utils', 'undefined_job_hunt, array empty from backend');
}
return jobArray.map((job) => {
return { ...job, [prop]: job[prop].nodes.map((item) => item[field] || '') };
});

View File

@ -27,22 +27,33 @@ const DEFAULT_SNOWPLOW_OPTIONS = {
pageUnloadTimer: 10,
};
const addExperimentContext = (opts) => {
const { experiment, ...options } = opts;
if (experiment) {
const data = getExperimentData(experiment);
if (data) {
const context = { schema: TRACKING_CONTEXT_SCHEMA, data };
return { ...options, context };
}
}
return options;
};
const createEventPayload = (el, { suffix = '' } = {}) => {
const action = (el.dataset.trackAction || el.dataset.trackEvent) + (suffix || '');
let value = el.dataset.trackValue || el.value || undefined;
if (el.type === 'checkbox' && !el.checked) value = false;
let context = el.dataset.trackContext;
if (el.dataset.trackExperiment) {
const data = getExperimentData(el.dataset.trackExperiment);
if (data) context = { schema: TRACKING_CONTEXT_SCHEMA, data };
}
const context = addExperimentContext({
experiment: el.dataset.trackExperiment,
context: el.dataset.trackContext,
});
const data = {
label: el.dataset.trackLabel,
property: el.dataset.trackProperty,
value,
context,
...context,
};
return {
@ -150,7 +161,8 @@ export default class Tracking {
return localCategory || opts.category;
},
trackingOptions() {
return { ...opts, ...this.tracking };
const options = addExperimentContext(opts);
return { ...options, ...this.tracking };
},
},
methods: {

View File

@ -4,7 +4,6 @@ class Projects::NetworkController < Projects::ApplicationController
include ExtractsPath
include ApplicationHelper
before_action :disable_query_limiting
before_action :require_non_empty_project
before_action :assign_ref_vars
before_action :authorize_download_code!
@ -41,8 +40,4 @@ class Projects::NetworkController < Projects::ApplicationController
@commit = @repo.commit(@options[:extended_sha1])
end
def disable_query_limiting
Gitlab::QueryLimiting.disable!('https://gitlab.com/gitlab-org/gitlab/-/issues/20782')
end
end

View File

@ -4,29 +4,29 @@ module ServicesHelper
def service_event_description(event)
case event
when "push", "push_events"
s_("ProjectService|Event triggered when someone pushes to the repository.")
s_("ProjectService|Trigger event for pushes to the repository.")
when "tag_push", "tag_push_events"
s_("ProjectService|Event triggered when a new tag is pushed to the repository.")
s_("ProjectService|Trigger event for new tags pushed to the repository.")
when "note", "note_events"
s_("ProjectService|Event triggered when someone adds a comment.")
s_("ProjectService|Trigger event for new comments.")
when "confidential_note", "confidential_note_events"
s_("ProjectService|Event triggered when someone adds a comment on a confidential issue.")
s_("ProjectService|Trigger event for new comments on confidential issues.")
when "issue", "issue_events"
s_("ProjectService|Event triggered when an issue is created, updated, or closed.")
s_("ProjectService|Trigger event when an issue is created, updated, or closed.")
when "confidential_issue", "confidential_issue_events"
s_("ProjectService|Event triggered when a confidential issue is created, updated, or closed.")
s_("ProjectService|Trigger event when a confidential issue is created, updated, or closed.")
when "merge_request", "merge_request_events"
s_("ProjectService|Event triggered when a merge request is created, updated, or merged.")
s_("ProjectService|Trigger event when a merge request is created, updated, or merged.")
when "pipeline", "pipeline_events"
s_("ProjectService|Event triggered when a pipeline status changes.")
s_("ProjectService|Trigger event when a pipeline status changes.")
when "wiki_page", "wiki_page_events"
s_("ProjectService|Event triggered when a wiki page is created or updated.")
s_("ProjectService|Trigger event when a wiki page is created or updated.")
when "commit", "commit_events"
s_("ProjectService|Event triggered when a commit is created or updated.")
s_("ProjectService|Trigger event when a commit is created or updated.")
when "deployment"
s_("ProjectService|Event triggered when a deployment starts or finishes.")
s_("ProjectService|Trigger event when a deployment starts or finishes.")
when "alert"
s_("ProjectService|Event triggered when a new, unique alert is recorded.")
s_("ProjectService|Trigger event when a new, unique alert is recorded.")
end
end

View File

@ -61,11 +61,11 @@ class ChatNotificationService < Service
def default_fields
[
{ type: 'text', name: 'webhook', placeholder: "e.g. #{webhook_placeholder}", required: true }.freeze,
{ type: 'text', name: 'username', placeholder: 'e.g. GitLab' }.freeze,
{ type: 'checkbox', name: 'notify_only_broken_pipelines' }.freeze,
{ type: 'text', name: 'webhook', placeholder: "#{webhook_placeholder}", required: true }.freeze,
{ type: 'text', name: 'username', placeholder: 'GitLab-integration' }.freeze,
{ type: 'checkbox', name: 'notify_only_broken_pipelines', help: 'Do not send notifications for successful pipelines.' }.freeze,
{ type: 'select', name: 'branches_to_be_notified', choices: branch_choices }.freeze,
{ type: 'text', name: 'labels_to_be_notified', placeholder: 'e.g. ~backend', help: 'Only supported for issue, merge request and note events.' }.freeze
{ type: 'text', name: 'labels_to_be_notified', placeholder: '~backend,~frontend', help: 'Send notifications for issue, merge request, and comment events with the listed labels only. Leave blank to receive notifications for all events.' }.freeze
].freeze
end

View File

@ -2,13 +2,14 @@
class MattermostService < ChatNotificationService
include SlackMattermost::Notifier
include ActionView::Helpers::UrlHelper
def title
'Mattermost notifications'
s_('Mattermost notifications')
end
def description
'Receive event notifications in Mattermost'
s_('Send notifications about project events to Mattermost channels.')
end
def self.to_param
@ -16,21 +17,15 @@ class MattermostService < ChatNotificationService
end
def help
'This service sends notifications about projects events to Mattermost channels.<br />
To set up this service:
<ol>
<li><a href="https://docs.mattermost.com/developer/webhooks-incoming.html#enabling-incoming-webhooks">Enable incoming webhooks</a> in your Mattermost installation.</li>
<li><a href="https://docs.mattermost.com/developer/webhooks-incoming.html#creating-integrations-using-incoming-webhooks">Add an incoming webhook</a> in your Mattermost team. The default channel can be overridden for each event.</li>
<li>Paste the webhook <strong>URL</strong> into the field below.</li>
<li>Select events below to enable notifications. The <strong>Channel handle</strong> and <strong>Username</strong> fields are optional.</li>
</ol>'
docs_link = link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/integrations/mattermost'), target: '_blank', rel: 'noopener noreferrer'
s_('Send notifications about project events to Mattermost channels. %{docs_link}').html_safe % { docs_link: docs_link.html_safe }
end
def default_channel_placeholder
"Channel handle (e.g. town-square)"
'my-channel'
end
def webhook_placeholder
'http://mattermost.example.com/hooks/'
'http://mattermost.example.com/hooks/'
end
end

View File

@ -15,14 +15,18 @@ module IssuableLinks
return error(not_found_message, 404) unless permission_to_remove_relation?
remove_relation
create_notes
track_event
after_destroy
success(message: 'Relation was removed')
end
private
def after_destroy
create_notes
track_event
end
def remove_relation
link.destroy!
end

View File

@ -110,7 +110,12 @@ module Projects
setup_authorizations
current_user.invalidate_personal_projects_count
create_prometheus_service
if Feature.enabled?(:projects_post_creation_worker, current_user, default_enabled: :yaml)
Projects::PostCreationWorker.perform_async(@project.id)
else
create_prometheus_service
end
create_readme if @initialize_with_readme
end
@ -193,6 +198,7 @@ module Projects
@project
end
# Deprecated: https://gitlab.com/gitlab-org/gitlab/-/issues/326665
def create_prometheus_service
service = @project.find_or_initialize_service(::PrometheusService.to_param)

View File

@ -163,6 +163,7 @@
- if profile_tab?(:activity)
#activity.tab-pane
.flash-container
- if can?(current_user, :read_cross_project)
%h4.prepend-top-20
= s_('UserProfile|Most Recent Activity')

View File

@ -2112,6 +2112,14 @@
:weight: 1
:idempotent:
:tags: []
- :name: projects_post_creation
:feature_category: :source_code_management
:has_external_dependencies:
:urgency: :low
:resource_boundary: :unknown
:weight: 1
:idempotent: true
:tags: []
- :name: projects_schedule_bulk_repository_shard_moves
:feature_category: :gitaly
:has_external_dependencies:

View File

@ -0,0 +1,34 @@
# frozen_string_literal: true
module Projects
class PostCreationWorker
include ApplicationWorker
feature_category :source_code_management
idempotent!
def perform(project_id)
project = Project.find_by_id(project_id)
return unless project
create_prometheus_service(project)
end
private
def create_prometheus_service(project)
service = project.find_or_initialize_service(::PrometheusService.to_param)
# If the service has already been inserted in the database, that
# means it came from a template, and there's nothing more to do.
return if service.persisted?
return unless service.prometheus_available?
service.save!
rescue ActiveRecord::RecordInvalid => e
Gitlab::ErrorTracking.track_exception(e, extra: { project_id: project.id })
end
end
end

View File

@ -0,0 +1,5 @@
---
title: Extract creation of prometheus service from Projects::CreateService
merge_request:
author:
type: added

View File

@ -0,0 +1,5 @@
---
title: Remove unused feature flag checks
merge_request: 58469
author:
type: removed

View File

@ -0,0 +1,5 @@
---
title: Display error message when dashboard activity fetch fails
merge_request: 57935
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Add btn-default class for toggle button in admin templates
merge_request: 58041
author: Yogi (@yo)
type: changed

View File

@ -0,0 +1,5 @@
---
title: Fix EmptyLineAfterFinalLetItBe offenses for error tracking module
merge_request: 58182
author: Huzaifa Iftikhar @huzaifaiftikhar
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Fix EmptyLineAfterFinalLetItBe offenses in spec/models/ci
merge_request: 58327
author: Huzaifa Iftikhar @huzaifaiftikhar
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Remove On-call Edit feature flag
merge_request: 56445
author:
type: other

View File

@ -0,0 +1,5 @@
---
title: Update mattermost integration UI text
merge_request: 58570
author:
type: other

View File

@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/322599
milestone: '13.10'
type: development
group: group::continuous integration
default_enabled: false
default_enabled: true

View File

@ -1,8 +1,8 @@
---
name: usage_data_i_analytics_dev_ops_adoption
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57104
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326450
name: projects_post_creation_worker
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/58119
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/326665
milestone: '13.11'
type: development
group: group::optimize
default_enabled: true
group: group::source code
default_enabled: false

View File

@ -1,8 +0,0 @@
---
name: usage_data_g_compliance_dashboard
introduced_by_url:
rollout_issue_url:
milestone:
type: development
group: group::compliance
default_enabled: true

View File

@ -1,8 +0,0 @@
---
name: usage_data_i_analytics_cohorts
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/54329
rollout_issue_url:
milestone: '13.9'
type: development
group: group::optimize
default_enabled: true

View File

@ -298,6 +298,8 @@
- 1
- - projects_git_garbage_collect
- 1
- - projects_post_creation
- 1
- - projects_schedule_bulk_repository_shard_moves
- 1
- - projects_update_repository_storage

View File

@ -393,8 +393,8 @@ Additional information:
GitLab recommends:
- Creating a [Gitaly Cluster](#gitaly-cluster) as soon as possible.
- [Moving your projects](praefect.md#migrate-existing-repositories-to-gitaly-cluster) from NFS-based
storage to the Gitaly Cluster.
- [Moving your repositories](praefect.md#migrate-to-gitaly-cluster) from NFS-based storage to Gitaly
Cluster.
We welcome your feedback on this process: raise a support ticket, or [comment on the epic](https://gitlab.com/groups/gitlab-org/-/epics/4916).

View File

@ -319,7 +319,7 @@ application server, or a Gitaly node.
WARNING:
If you have data on an already existing storage called
`default`, you should configure the virtual storage with another name and
[migrate the data to the Gitaly Cluster storage](#migrate-existing-repositories-to-gitaly-cluster)
[migrate the data to the Gitaly Cluster storage](#migrate-to-gitaly-cluster)
afterwards.
Replace `PRAEFECT_INTERNAL_TOKEN` with a strong secret, which is used by
@ -760,7 +760,7 @@ Particular attention should be shown to:
WARNING:
If you have existing data stored on the default Gitaly storage,
you should [migrate the data your Gitaly Cluster storage](#migrate-existing-repositories-to-gitaly-cluster)
you should [migrate the data your Gitaly Cluster storage](#migrate-to-gitaly-cluster)
first.
```ruby
@ -1294,7 +1294,7 @@ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.t
- Replace the placeholder `<up-to-date-storage>` with the Gitaly storage name containing up to date repositories.
- Replace the placeholder `<outdated-storage>` with the Gitaly storage name containing outdated repositories.
## Migrate existing repositories to Gitaly Cluster
## Migrate to Gitaly Cluster
To migrate to Gitaly Cluster, existing repositories stored outside Gitaly Cluster must be
moved. There is no automatic migration but the moves can be scheduled with the GitLab API.
@ -1308,8 +1308,8 @@ until the move has completed.
After creating and configuring Gitaly Cluster:
1. Ensure all storages are accessible to the GitLab instance. In this example, these
are `<original_storage_name>` and `<cluster_storage_name>`.
1. Ensure all storages are accessible to the GitLab instance. In this example, these are
`<original_storage_name>` and `<cluster_storage_name>`.
1. [Configure repository storage weights](../repository_storage_paths.md#configure-where-new-repositories-are-stored)
so that the Gitaly Cluster receives all new projects. This stops new projects being created
on existing Gitaly nodes while the migration is in progress.

View File

@ -28,7 +28,7 @@ For more information, see:
querying and scheduling snippet repository moves.
- [The API documentation](../../api/group_repository_storage_moves.md) details the endpoints for
querying and scheduling group repository moves **(PREMIUM SELF)**.
- [Migrate existing repositories to Gitaly Cluster](../gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster).
- [Migrate to Gitaly Cluster](../gitaly/praefect.md#migrate-to-gitaly-cluster).
## Migrating to another GitLab instance

View File

@ -15,25 +15,29 @@ full list of reference architectures, see
> - **High Availability:** Yes ([Praefect](#configure-praefect-postgresql) needs a third-party PostgreSQL solution for HA)
> - **Test requests per second (RPS) rates:** API: 200 RPS, Web: 20 RPS, Git (Pull): 20 RPS, Git (Push): 4 RPS
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-------------------------|-----------------|-------------|----------|
| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
| Consul | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
| PostgreSQL | 3 | 8 vCPU, 30 GB memory | n1-standard-8 | `m5.2xlarge` | D8s v3 |
| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
| Redis - Cache | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
| Redis - Queues / Shared State | 3 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
| Redis Sentinel - Cache | 3 | 1 vCPU, 1.7 GB memory | g1-small | `t3.small` | B1MS |
| Redis Sentinel - Queues / Shared State | 3 | 1 vCPU, 1.7 GB memory | g1-small | `t3.small` | B1MS |
| Gitaly | 3 | 16 vCPU, 60 GB memory | n1-standard-16 | `m5.4xlarge` | D16s v3 |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
| Praefect PostgreSQL | 1+* | 2 vCPU, 1.8 GB memory | n1-highcpu-2 | `c5.large` | F2s v2 |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | n1-standard-4 | `m5.xlarge` | D4s v3 |
| GitLab Rails | 3 | 32 vCPU, 28.8 GB memory | n1-highcpu-32 | `c5.9xlarge` | F32s v2 |
| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
| Object storage | n/a | n/a | n/a | n/a | n/a |
| NFS server | 1 | 4 vCPU, 3.6 GB memory | n1-highcpu-4 | `c5.xlarge` | F4s v2 |
| Service | Nodes | Configuration | GCP | AWS | Azure |
|--------------------------------------------|-------------|-------------------------|------------------|--------------|-----------|
| External load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Consul | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| PostgreSQL | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` | `m5.2xlarge` | `D8s v3` |
| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Redis - Cache* | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| Redis - Queues / Shared State* | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| Redis Sentinel - Cache* | 3 | 1 vCPU, 1.7 GB memory | `g1-small` | `t3.small` | `B1MS` |
| Redis Sentinel - Queues / Shared State* | 3 | 1 vCPU, 1.7 GB memory | `g1-small` | `t3.small` | `B1MS` |
| Gitaly | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` | `m5.4xlarge` | `D16s v3` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Praefect PostgreSQL* | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` | `c5.large` | `F2s v2` |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | `m5.xlarge` | `D4s v3` |
| GitLab Rails | 3 | 32 vCPU, 28.8 GB memory | `n1-highcpu-32` | `c5.9xlarge` | `F32s v2` |
| Monitoring node | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
| Object storage | n/a | n/a | n/a | n/a | n/a |
| NFS server | 1 | 4 vCPU, 3.6 GB memory | `n1-highcpu-4` | `c5.xlarge` | `F4s v2` |
NOTE:
Components marked with * can be optionally run on reputable
third party external PaaS solutions such as Google Cloud SQL or Memorystore.
```plantuml
@startuml 10k
@ -2349,29 +2353,142 @@ considered and customer technical support will be considered out of scope.
</a>
</div>
## Cloud Native Deployment (optional)
## Cloud Native Hybrid reference architecture with Helm Charts (alternative)
As an alternative approach, you can also run select components of GitLab as Cloud Native
in Kubernetes via our official [Helm Charts](https://docs.gitlab.com/charts/).
In this setup, we support running the equivalent of GitLab Rails and Sidekiq nodes
in a Kubernetes cluster, named Webservice and Sidekiq respectively. In addition,
the following other supporting services are supported: NGINX, Task Runner, Migrations,
Prometheus and Grafana.
Hybrid installations leverage the benefits of both cloud native and traditional
deployments. We recommend shifting the Sidekiq and Webservice components into
Kubernetes to reap cloud native workload management benefits while the others
are deployed using the traditional server method already described.
Kubernetes, you can reap certain cloud native workload management benefits while
the others are deployed in compute VMs with Omnibus as described above in this
page.
The following sections detail this hybrid approach.
It should be noted though that this is an advanced setup as running services in
Kubernetes is well known to be complex. **This setup is only recommended** if
you have strong working knowledge and experience in Kubernetes. The rest of this
section will assume this.
### Cluster topology
The following table provides a starting point for hybrid
deployment infrastructure. The recommendations use Google Cloud's Kubernetes Engine (GKE)
and associated machine types, but the memory and CPU requirements should
translate to most other providers.
The following tables and diagram details the hybrid environment using the same formats
as the normal environment above.
Machine count | Machine type | Allocatable vCPUs | Allocatable memory (GB) | Purpose
-|-|-|-|-
2 | `n1-standard-4` | 7.75 | 25 | Non-GitLab resources, including Grafana, NGINX, and Prometheus
4 | `n1-standard-4` | 15.5 | 50 | GitLab Sidekiq pods
4 | `n1-highcpu-32` | 127.5 | 118 | GitLab Webservice pods
First starting with the components that run in Kubernetes. The recommendations at this
time use Google Clouds Kubernetes Engine (GKE) and associated machine types, but the memory
and CPU requirements should translate to most other providers. We hope to update this in the
future with further specific cloud provider details.
"Allocatable" in this table refers to the amount of resources available to workloads deployed in Kubernetes _after_ accounting for the overhead of running Kubernetes itself.
| Service | Nodes | Configuration | GCP | Allocatable CPUs and Memory |
|-------------------------------------------------------|-------|-------------------------|------------------|-----------------------------|
| Webservice | 4 | 32 vCPU, 28.8 GB memory | `n1-standard-32` | 127.5 vCPU, 118 GB memory |
| Sidekiq | 4 | 4 vCPU, 15 GB memory | `n1-standard-4` | 15.5 vCPU, 50 GB memory |
| Supporting services such as NGINX, Prometheus, etc... | 2 | 4 vCPU, 15 GB memory | `n1-standard-4` | 7.75 vCPU, 25 GB memory |
Next are the backend components that run on static compute VMs via Omnibus (or External PaaS
services where applicable):
| Service | Nodes | Configuration | GCP |
|--------------------------------------------|-------|-------------------------|------------------|
| Consul | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| PostgreSQL* | 3 | 8 vCPU, 30 GB memory | `n1-standard-8` |
| PgBouncer | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Internal load balancing node | 1 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Redis - Cache* | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
| Redis - Queues / Shared State* | 3 | 4 vCPU, 15 GB memory | `n1-standard-4` |
| Redis Sentinel - Cache* | 3 | 1 vCPU, 1.7 GB memory | `g1-small` |
| Redis Sentinel - Queues / Shared State* | 3 | 1 vCPU, 1.7 GB memory | `g1-small` |
| Gitaly | 3 | 16 vCPU, 60 GB memory | `n1-standard-16` |
| Praefect | 3 | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Praefect PostgreSQL* | 1+ | 2 vCPU, 1.8 GB memory | `n1-highcpu-2` |
| Object storage | n/a | n/a | n/a |
NOTE:
Components marked with * can be optionally run on reputable
third party external PaaS solutions such as Google Cloud SQL or Memorystore.
```plantuml
@startuml 10k
card "Kubernetes via Helm Charts" as kubernetes {
card "**External Load Balancer**" as elb #6a9be7
together {
collections "**Webservice** x4" as gitlab #32CD32
collections "**Sidekiq** x4" as sidekiq #ff8dd1
}
card "**Prometheus + Grafana**" as monitor #7FFFD4
card "**Supporting Services**" as support
}
card "**Internal Load Balancer**" as ilb #9370DB
collections "**Consul** x3" as consul #e76a9b
card "Gitaly Cluster" as gitaly_cluster {
collections "**Praefect** x3" as praefect #FF8C00
collections "**Gitaly** x3" as gitaly #FF8C00
card "**Praefect PostgreSQL***\n//Non fault-tolerant//" as praefect_postgres #FF8C00
praefect -[#FF8C00]-> gitaly
praefect -[#FF8C00]> praefect_postgres
}
card "Database" as database {
collections "**PGBouncer** x3" as pgbouncer #4EA7FF
card "**PostgreSQL** (Primary)" as postgres_primary #4EA7FF
collections "**PostgreSQL** (Secondary) x2" as postgres_secondary #4EA7FF
pgbouncer -[#4EA7FF]-> postgres_primary
postgres_primary .[#4EA7FF]> postgres_secondary
}
card "redis" as redis {
collections "**Redis Persistent** x3" as redis_persistent #FF6347
collections "**Redis Cache** x3" as redis_cache #FF6347
collections "**Redis Persistent Sentinel** x3" as redis_persistent_sentinel #FF6347
collections "**Redis Cache Sentinel** x3"as redis_cache_sentinel #FF6347
redis_persistent <.[#FF6347]- redis_persistent_sentinel
redis_cache <.[#FF6347]- redis_cache_sentinel
}
cloud "**Object Storage**" as object_storage #white
elb -[#6a9be7]-> gitlab
elb -[#6a9be7]-> monitor
elb -[hidden]-> support
gitlab -[#32CD32]> sidekiq
gitlab -[#32CD32]--> ilb
gitlab -[#32CD32]-> object_storage
gitlab -[#32CD32]---> redis
gitlab -[hidden]--> consul
sidekiq -[#ff8dd1]--> ilb
sidekiq -[#ff8dd1]-> object_storage
sidekiq -[#ff8dd1]---> redis
sidekiq -[hidden]--> consul
ilb -[#9370DB]-> gitaly_cluster
ilb -[#9370DB]-> database
consul .[#e76a9b]-> database
consul .[#e76a9b]-> gitaly_cluster
consul .[#e76a9b,norank]--> redis
monitor .[#7FFFD4]> consul
monitor .[#7FFFD4]-> database
monitor .[#7FFFD4]-> gitaly_cluster
monitor .[#7FFFD4,norank]--> redis
monitor .[#7FFFD4]> ilb
monitor .[#7FFFD4,norank]u--> elb
@enduml
```
### Resource usage settings
@ -2379,29 +2496,31 @@ The following formulas help when calculating how many pods may be deployed withi
The [10k reference architecture example values file](https://gitlab.com/gitlab-org/charts/gitlab/-/blob/master/examples/ref/10k.yaml)
documents how to apply the calculated configuration to the Helm Chart.
#### Webservice
Webservice pods typically need about 1 vCPU and 1.25 GB of memory _per worker_.
Each Webservice pod will consume roughly 4 vCPUs and 5 GB of memory using
the [recommended topology](#cluster-topology) because four worker processes
are created by default and each pod has other small processes running.
For 10k users we recommend a total Puma worker count of around 80.
With the [provided recommendations](#cluster-topology) this allows the deployment of up to 20
Webservice pods with 4 workers per pod and 5 pods per node. Expand available resources using
the ratio of 1 vCPU to 1.25 GB of memory _per each worker process_ for each additional
Webservice pod.
For further information on resource usage, see the [Webservice resources](https://docs.gitlab.com/charts/charts/gitlab/webservice/#resources).
#### Sidekiq
Sidekiq pods should generally have 1 vCPU and 2 GB of memory.
[The provided starting point](#cluster-topology) allows the deployment of up to
16 Sidekiq pods. Expand available resources using the 1vCPU to 2GB memory
16 Sidekiq pods. Expand available resources using the 1 vCPU to 2GB memory
ratio for each additional pod.
For further information on resource usage, see the [Sidekiq resources](https://docs.gitlab.com/charts/charts/gitlab/sidekiq/#resources).
#### Webservice
Webservice pods typically need about 1 vCPU and 1.25 GB of memory _per worker_.
Each Webservice pod will consume roughly 2 vCPUs and 2.5 GB of memory using
the [recommended topology](#cluster-topology) because two worker processes
are created by default.
The [provided recommendations](#cluster-topology) allow the deployment of up to 28
Webservice pods. Expand available resources using the ratio of 1 vCPU to 1.25 GB of memory
_per each worker process_ for each additional Webservice pod.
For further information on resource usage, see the [Webservice resources](https://docs.gitlab.com/charts/charts/gitlab/webservice/#resources).
<div align="right">
<a type="button" class="btn btn-default" href="#setup-components">
Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i>

View File

@ -156,5 +156,5 @@ often it is chosen. That is, `(storage weight) / (sum of all weights) * 100 = ch
## Move repositories
To move a repository to a different repository path, use
the same process as [migrating existing repositories to Gitaly Cluster](gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster).
To move a repository to a different repository path, use the same process as
[migrating to Gitaly Cluster](gitaly/praefect.md#migrate-to-gitaly-cluster).

View File

@ -10,8 +10,8 @@ type: reference
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53016) in GitLab 13.9.
Group repositories can be moved between storages. This can be useful when
[migrating to Gitaly Cluster](../administration/gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster),
for example, or to migrate a Group Wiki.
[migrating to Gitaly Cluster](../administration/gitaly/praefect.md#migrate-to-gitaly-cluster), for
example, or to migrate a Group Wiki.
As group repository storage moves are processed, they transition through different states. Values
of `state` are:

View File

@ -10,7 +10,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
## List issue relations
Get a list of a given issue's [related issues](../user/project/issues/related_issues.md),
Get a list of a given issue's [linked issues](../user/project/issues/related_issues.md),
sorted by the relationship creation datetime (ascending).
Issues are filtered according to the user authorizations.

View File

@ -10,7 +10,7 @@ type: reference
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31285) in GitLab 13.0.
Project repositories including wiki and design repositories can be moved between storages. This can be useful when
[migrating to Gitaly Cluster](../administration/gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster),
[migrating to Gitaly Cluster](../administration/gitaly/praefect.md#migrate-to-gitaly-cluster),
for example.
As project repository storage moves are processed, they transition through different states. Values

View File

@ -10,8 +10,8 @@ type: reference
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49228) in GitLab 13.8.
Snippet repositories can be moved between storages. This can be useful when
[migrating to Gitaly Cluster](../administration/gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster),
for example.
[migrating to Gitaly Cluster](../administration/gitaly/praefect.md#migrate-to-gitaly-cluster), for
example.
As snippet repository storage moves are processed, they transition through different states. Values
of `state` are:

View File

@ -38,7 +38,7 @@ Depending on the areas your merge request touches, it must be **approved** by on
or more [maintainers](https://about.gitlab.com/handbook/engineering/workflow/code-review/#maintainer):
For approvals, we use the approval functionality found in the merge request
widget. For reviewers, we use the [reviewer functionality](../user/project/merge_requests/getting_started.md#reviewer) in the sidebar.
widget. For reviewers, we use the [reviewer functionality](../user/project/merge_requests/getting_started.md#reviewer) in the sidebar.
Reviewers can add their approval by [approving additionally](../user/project/merge_requests/merge_request_approvals.md#adding-or-removing-an-approval).
Getting your merge request **merged** also requires a maintainer. If it requires
@ -365,7 +365,7 @@ experience, refactors the existing code). Then:
- For non-mandatory suggestions, decorate with (non-blocking) so the author knows they can
optionally resolve within the merge request or follow-up at a later stage.
- There's a [Chrome/Firefox add-on](https://gitlab.com/conventionalcomments/conventional-comments-button) which you can use to apply [Conventional Comment](https://conventionalcomments.org/) prefixes.
- Ensure there are no open dependencies. Check [related issues](../user/project/issues/related_issues.md) for blockers. Clarify with the author(s)
- Ensure there are no open dependencies. Check [linked issues](../user/project/issues/related_issues.md) for blockers. Clarify with the author(s)
if necessary. If blocked by one or more open MRs, set an [MR dependency](../user/project/merge_requests/merge_request_dependencies.md).
- After a round of line notes, it can be helpful to post a summary note such as
"Looks good to me", or "Just a couple things to address."

View File

@ -10,6 +10,7 @@ description: "Learn how GitLab docs' global navigation works and how to add new
> - [Introduced](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/362) in GitLab 11.6.
> - [Updated](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/482) in GitLab 12.1.
> - [Per-project](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/498) navigation added in GitLab 12.2.
> - [Unified global navigation](https://gitlab.com/gitlab-org/gitlab-docs/-/merge_requests/1482) added in GitLab 13.11.
Global navigation (the left-most pane in our three pane documentation) provides:
@ -19,24 +20,12 @@ Global navigation (the left-most pane in our three pane documentation) provides:
- The ability to refine landing pages, so they don't have to do all the work of surfacing
every page contained within the documentation.
## Quick start
To add a topic to the global nav, go to the directory that contains
[navigation files](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/content/_data/)
and edit the `yaml` file for your product area. You can copy an existing nav entry and
edit it to point to your topic.
The files are:
| File | Document | Location |
|-----------------------|--------------------------------------------------------------------|-------------------------------------------------------|
| `charts-nav.yaml` | GitLab cloud native Helm Chart | `https://docs.gitlab.com/charts/` |
| `default-nav.yaml` | GitLab Docs | `https://docs.gitlab.com/ee/` |
| `omnibus-nav.yaml` | Omnibus GitLab Docs | `https://docs.gitlab.com/omnibus/` |
| `runner-nav.yaml` | GitLab Runner Docs | `https://docs.gitlab.com/runner/` |
## Adding new items
To add a topic to the global nav, edit
[`navigation.yaml`](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/content/_data/navigation.yaml)
and add your item.
All new pages need a new navigation item. Without a navigation, the page becomes "orphaned". That
is:
@ -84,12 +73,6 @@ mechanics of what is required is [documented below](#data-file) but, in principl
- Avoid jargon or terms of art, unless ubiquitous. For example, **CI** is an acceptable
substitution for **Continuous Integration**.
- Navigation links must follow the rules documented in the [data file](#data-file).
- EE badging is subject to the following:
- Required when linking to an EE-only page.
- Not required when linking to a page that is a mix of CE and EE-only content.
- Required when all sub-items are EE-only. In this case, no sub-items are EE badged.
- Not required when sub-items are a mix of CE and EE-only items. In this case, each item is
badged appropriately.
## How it works
@ -101,14 +84,6 @@ The global nav has five levels:
- Doc
- Doc
The available sections are described on the table below:
| Section | Description |
| ------------- | ------------------------------------ |
| User | Documentation for the GitLab UI. |
| Administrator | Documentation for the Admin Area. |
| Contributor | Documentation for developing GitLab. |
The majority of the links available on the nav were added according to the UI.
The match is not perfect, as for some UI nav items the documentation doesn't
apply, and there are also other links to help the new users to discover the
@ -116,7 +91,7 @@ documentation. The docs under **Administration** are ordered alphabetically
for clarity.
To see the improvements planned, check the
[global nav epic](https://gitlab.com/groups/gitlab-com/-/epics/21).
[global nav epic](https://gitlab.com/groups/gitlab-org/-/epics/1599).
**Do not** [add items](#adding-new-items) to the global nav without
the consent of one of the technical writers.
@ -133,9 +108,9 @@ the data among the nav in containers properly [styled](#css-classes).
### Data file
The data file describes the structure of the navigation for the applicable project. All data files
are stored at <https://gitlab.com/gitlab-org/gitlab-docs/blob/master/content/_data/> and comprise
three components:
The data file describes the structure of the navigation for the applicable project.
It is stored at <https://gitlab.com/gitlab-org/gitlab-docs/blob/master/content/_data/navigation.yaml>
and comprises of three main components:
- Sections
- Categories
@ -185,24 +160,6 @@ Example of section with two stand-alone categories:
For clarity, **always** add a blank line between categories.
If a category URL is not present in CE (it's an EE-only document), add the
attribute `ee_only: true` below the category link. Example:
```yaml
- category_title: Category title
category_url: 'category-link'
ee_only: true
```
If the category links to an external URL, e.g., [GitLab Design System](https://design.gitlab.com),
add the attribute `external_url: true` below the category title. Example:
```yaml
- category_title: GitLab Design System
category_url: 'https://design.gitlab.com'
external_url: true
```
#### Docs
Each doc represents the third, fourth, and fifth level of nav links. They must be always
@ -225,7 +182,8 @@ Example with three doc links, one at each level:
```
A category supports as many docs as necessary, but, for clarity, try to not
overpopulate a category. Also, do not use more than three levels of docs.
overpopulate a category. Also, do not use more than three levels of docs, it
is not supported.
Example with multiple docs:
@ -239,15 +197,6 @@ Example with multiple docs:
doc_url: 'doc-2-link'
```
Whenever a document is only present in EE, add the attribute `ee-only: true`
below the doc link. Example:
```yaml
- doc_title: Document 2 title
doc_url: 'doc-2-link'
ee_only: true
```
If you need to add a document in an external URL, add the attribute `external_url`
below the doc link:
@ -266,12 +215,12 @@ Example:
```yaml
- category_title: Operations
category_url: 'user/project/integrations/prometheus_library/'
category_url: 'ee/user/project/integrations/prometheus_library/'
# until we have a link to operations, the first doc link is
# repeated in the category link
docs:
- doc_title: Metrics
doc_url: 'user/project/integrations/prometheus_library/'
doc_url: 'ee/user/project/integrations/prometheus_library/'
```
#### Syntax
@ -282,43 +231,39 @@ and the following syntax rules.
##### Titles
- Use sentence case, capitalizing feature names.
- There's no need to wrap the titles, unless there's a special char in it. E.g.,
- There's no need to wrap the titles, unless there's a special char in it. For example,
in `GitLab CI/CD`, there's a `/` present, therefore, it must be wrapped in quotes.
As convention, wrap the titles in double quotes: `category_title: "GitLab CI/CD"`.
##### URLs
URLs can be either relative or external, and the following apply:
- All links in the data file must end with `.html` (with the exception
of `index.html` files), and not `.md`.
- For `index.html` files, use the clean (canonical) URL: `path/to/`. For example, `https://docs.gitlab.com/ee/install/index.html` becomes `ee/install/`.
- Do not start any relative link with a forward slash `/`.
- As convention, always wrap URLs in single quotes `'url'`.
- Always use relative paths against the home of CE and EE. Examples:
- For `https://docs.gitlab.com/ee/README.html`, the relative URL is `README.html`.
- For `https://docs.gitlab.com/ee/user/analytics/value_stream_analytics.md`, the relative
URL is `user/analytics/value_stream_analytics.html`.
- For `README.html` files, add the complete path `path/to/README.html`.
- For `index.html` files, use the clean (canonical) URL: `path/to/`.
- For EE-only docs, use the same relative path, but add the attribute `ee_only: true` below
the `doc_url` or `category_url`, as explained above. This displays
an "information" icon on the nav to make the user aware that the feature is
EE-only.
- Always use the project prefix depending on which project the link you add
lives in. To find the global nav link, from the full URL remove `https://docs.gitlab.com/`.
- If a URL links to an external URL, like the [GitLab Design System](https://design.gitlab.com),
add the attribute `external_url: true`, for example:
WARNING:
All links present on the data file must end in `.html`, not `.md`. Do not
start any relative link with a forward slash `/`.
```yaml
- category_title: GitLab Design System
category_url: 'https://design.gitlab.com'
external_url: true
```
Examples:
Examples of relative URLs:
```yaml
- category_title: Issues
category_url: 'user/project/issues/'
# note that the above URL does not start with a slash and
# does not include index.html at the end
docs:
- doc_title: Container Scanning
doc_url: 'user/application_security/container_scanning/'
ee_only: true
# note that the URL above ends in html and, as the
# document is EE-only, the attribute ee_only is set to true.
```
| Full URL | Global nav URL |
| -------------------------------------------------------------- | ------------------------------------- |
| `https://docs.gitlab.com/ee/api/avatar.html` | `ee/api/avatar.html` |
| `https://docs.gitlab.com/ee/install/index.html` | `ee/install/` |
| `https://docs.gitlab.com/omnibus/settings/database.html` | `omnibus/settings/database.html` |
| `https://docs.gitlab.com/charts/installation/deployment.html` | `charts/installation/deployment.html` |
| `https://docs.gitlab.com/runner/install/docker.html` | `runner/install/docker.html` |
### Layout file (logic)
@ -326,74 +271,15 @@ The [layout](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/globa
is fed by the [data file](#data-file), builds the global nav, and is rendered by the
[default](https://gitlab.com/gitlab-org/gitlab-docs/blob/master/layouts/default.html) layout.
There are three main considerations on the logic built for the nav:
The global nav contains links from all [four upstream projects](index.md#architecture).
The [global nav URL](#urls) has a different prefix depending on the documentation file you change.
- [Path](#path): first-level directories underneath `docs.gitlab.com/`:
- `https://docs.gitlab.com/ce/`
- `https://docs.gitlab.com/ee/`
- `https://docs.gitlab.com/omnibus/`
- `https://docs.gitlab.com/runner/`
- `https://docs.gitlab.com/*`
- [EE-only](#ee-only-docs): documentation only available in `/ee/`, not on `/ce/`, e.g.:
- `https://docs.gitlab.com/ee/user/group/epics/`
- `https://docs.gitlab.com/ee/user/application_security/security_dashboard/index.html`
- [Default URL](#default-url): between CE and EE docs, the default is `ee`, therefore, all docs
should link to `/ee/` unless if on `/ce/` linking internally to `ce`.
#### Path
To use relative paths in the data file, we defined the variable `dir`
from the root's first-child directory, which defines the path to build
all the nav links to other pages:
```html
<% dir = @item.identifier.to_s[%r{(?<=/)[^/]+}] %>
```
For instance, for `https://docs.gitlab.com/ee/user/index.html`,
`dir` == `ee`, and for `https://docs.gitlab.com/omnibus/README.html`,
`dir` == `omnibus`.
#### Default URL
The default and canonical URL for GitLab documentation is
`https://docs.gitlab.com/ee/`, thus, all links
in the docs site should link to `/ee/` except when linking
among `/ce/` docs themselves.
Therefore, if the user is looking at `/ee/`, `/omnibus/`,
`/runner/`, or any other highest-level dir, the nav should
point to `/ee/` docs.
On the other hand, if the user is looking at `/ce/` docs,
all the links in the CE nav should link internally to `/ce/`
files.
```html
<% if dir != 'ce' %>
<a href="/ee/<%= sec[:section_url] %>">...</a>
<% else %>
<a href="/<%= dir %>/<%= sec[:section_url] %>">...</a>
<% end %>
...
<% end %>
```
This also allows the nav to be displayed on other
highest-level directories (`/omnibus/`, `/runner/`, etc),
linking them back to `/ee/`.
The same logic is applied to all sections (`sec[:section_url]`),
categories (`cat[:category_url]`), and docs (`doc[:doc_url]`) URLs.
#### `ee-only` docs
Docs for features present only in GitLab EE are tagged
in the data file by `ee-only` and an icon is displayed on the nav
link indicating that the `ee-only` feature is not available in CE.
The `ee-only` attribute is available for `categories` (`<% if cat[:ee_only] %>`)
and `docs` (`<% if doc[:ee_only] %>`), but not for `sections`.
| Repository | Link prefix | Final URL |
|----------------------------------------------------------------|-------------|-----------|
| <https://gitlab.com/gitlab-org/gitlab/tree/master/doc> | `ee/` |`https://docs.gitlab.com/ee/` |
| <https://gitlab.com/gitlab-org/omnibus-gitlab/tree/master/doc> | `omnibus/` |`https://docs.gitlab.com/omnibus/` |
| <https://gitlab.com/gitlab-org/gitlab-runner/tree/master/docs> | `runner/` |`https://docs.gitlab.com/runner/` |
| <https://gitlab.com/charts/gitlab/tree/master/doc> | `charts/` |`https://docs.gitlab.com/charts/` |
### CSS classes

View File

@ -608,7 +608,7 @@ Follow these guidelines for punctuation:
| Do not use tabs for indentation. Use spaces instead. You can configure your code editor to output spaces instead of tabs when pressing the tab key. | --- |
| Use serial commas (_Oxford commas_) before the final _and_ or _or_ in a list of three or more items. (Tested in [`OxfordComma.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/OxfordComma.yml).) | _You can create new issues, merge requests, and milestones._ |
| Always add a space before and after dashes when using it in a sentence (for replacing a comma, for example). | _You should try this - or not._ |
| Always use lowercase after a colon. | _Related Issues: a way to create a relationship between issues._ |
| Always use lowercase after a colon. | Linked issues: a way to create a relationship between issues._ |
<!-- vale gitlab.Repetition = YES -->

View File

@ -9908,6 +9908,30 @@ Status: `implemented`
Tiers: `premium`, `ultimate`
### `redis_hll_counters.epics_usage.g_project_management_epic_issue_removed_monthly`
Count of MAU removing issues from epics
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210401183230_g_project_management_epic_issue_removed_monthly.yml)
Group: `group::product planning`
Status: `implemented`
Tiers: `premium`, `ultimate`
### `redis_hll_counters.epics_usage.g_project_management_epic_issue_removed_weekly`
Counts of WAU removing issues from epics
[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_7d/20210401182457_g_project_management_g_project_management_epic_issue_removed_weekly.yml)
Group: `group::product planning`
Status: `implemented`
Tiers: `premium`, `ultimate`
### `redis_hll_counters.epics_usage.g_project_management_epic_reopened_monthly`
Counts of MAU closing epics

View File

@ -394,4 +394,4 @@ end
You can link related issues to a feature flag. In the **Linked issues** section,
click the `+` button and input the issue reference number or the full URL of the issue.
This feature is similar to the [related issues](../user/project/issues/related_issues.md) feature.
This feature is similar to the [linked issues](../user/project/issues/related_issues.md) feature.

View File

@ -5,11 +5,13 @@ info: "To determine the technical writer assigned to the Stage/Group associated
type: reference, howto
---
# Partial Clone **(FREE)**
# Partial clone **(FREE)**
As Git repositories grow in size, they can become cumbersome to work with
because of the large amount of history that must be downloaded, and the large
amount of disk space they require.
because of:
- The large amount of history that must be downloaded.
- The large amount of disk space they require.
[Partial clone](https://github.com/git/git/blob/master/Documentation/technical/partial-clone.txt)
is a performance optimization that "allows Git to function without having a
@ -58,9 +60,10 @@ Updating files: 100% (13008/13008), done.
Filtering content: 100% (3/3), 131.24 MiB | 4.65 MiB/s, done.
```
The output is longer because Git first clones the repository excluding
files larger than 1 megabyte, and second download any missing large files needed
to checkout the `master` branch.
The output is longer because Git:
1. Clones the repository excluding files larger than 1 megabyte.
1. Downloads any missing large files needed to check out the default branch.
When changing branches, Git may need to download more missing files.
@ -68,9 +71,9 @@ When changing branches, Git may need to download more missing files.
> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/2553) in GitLab 12.10.
For enormous repositories with millions of files, and long history, it may be
helpful to exclude all files and use in combination with `sparse-checkout` to
reduce the size of your working copy.
For repositories with millions of files and a long history, you can exclude all files and use
[`git sparse-checkout`](https://git-scm.com/docs/git-sparse-checkout) to reduce the size of
your working copy.
```plaintext
# Clone the repo excluding all files
@ -108,21 +111,22 @@ For more details, see the Git documentation for
## Filter by file path
WARNING:
Partial Clone using `sparse` filters is experimental, slow, and
significantly increases Gitaly resource utilization when cloning and fetching.
Deeper integration between partial clone and sparse checkout is possible through the
`--filter=sparse:oid=<blob-ish>` filter spec. This mode of filtering uses a format similar to a
`.gitignore` file to specify which files to include when cloning and fetching.
Deeper integration between Partial Clone and Sparse Checkout is being explored
through the `--filter=sparse:oid=<blob-ish>` filter spec, but this is highly
experimental. This mode of filtering uses a format similar to a `.gitignore`
file to specify which files should be included when cloning and fetching.
WARNING:
Partial clone using `sparse` filters is still experimental. It might be slow and significantly increase
[Gitaly](../../administration/gitaly/index.md) resource utilization when cloning and fetching.
[Filter all blobs and use sparse-checkout](#filter-by-object-type) instead, because
[`git-sparse-checkout`](https://git-scm.com/docs/git-sparse-checkout) simplifies
this type of partial clone use and overcomes its limitations.
For more details, see the Git documentation for
[`rev-list-options`](https://gitlab.com/gitlab-org/git/-/blob/9fadedd637b312089337d73c3ed8447e9f0aa775/Documentation/rev-list-options.txt#L735-780).
[`rev-list-options`](https://git-scm.com/docs/git-rev-list#Documentation/git-rev-list.txt---filterltfilter-specgt).
1. **Create a filter spec.** For example, consider a monolithic repository with
many applications, each in a different subdirectory in the root. Create a file
`shiny-app/.filterspec` using the GitLab web interface:
1. Create a filter spec. For example, consider a monolithic repository with many applications,
each in a different subdirectory in the root. Create a file `shiny-app/.filterspec`:
```plaintext
# Only the paths listed in the file will be downloaded when performing a
@ -142,28 +146,14 @@ For more details, see the Git documentation for
shared-component-b/
```
1. **Create a new Git repository and fetch.** Support for `--filter=sparse:oid`
using the clone command is incomplete, so we emulate the clone command
by hand, using `git init` and `git fetch`. Follow
[issue tracking support for `--filter=sparse:oid`](https://gitlab.com/gitlab-org/git/-/issues/4)
for updates.
1. Clone and filter by path. Support for `--filter=sparse:oid` using the
clone command is not yet fully integrated with sparse checkout.
```shell
# Create a new directory for the Git repository
mkdir jumbo-repo && cd jumbo-repo
# Initialize a new Git repository
git init
# Add the remote
git remote add origin <url>
# Enable partial clone support for the remote
git config --local extensions.partialClone origin
# Fetch the filtered set of objects using the filterspec stored on the
# server. WARNING: this step is slow!
git fetch --filter=sparse:oid=master:shiny-app/.gitfilterspec origin
# Clone the filtered set of objects using the filterspec stored on the
# server. WARNING: this step may be very slow!
git clone --sparse --filter=sparse:oid=master:shiny-app/.gitfilterspec <url>
# Optional: observe there are missing objects that we have not fetched
git rev-list --all --quiet --objects --missing=print | wc -l
@ -175,21 +165,6 @@ For more details, see the Git documentation for
entire repository. You many need to disable or reconfigure these
integrations.
1. **Sparse checkout** must be enabled and configured to prevent objects from
other paths being downloaded automatically when checking out branches. Follow
[issue proposing automating sparse checkouts](https://gitlab.com/gitlab-org/git/-/issues/5) for updates.
```shell
# Enable sparse checkout
git config --local core.sparsecheckout true
# Configure sparse checkout
git show master:snazzy-app/.gitfilterspec >> .git/info/sparse-checkout
# Checkout master
git checkout master
```
## Remove partial clone filtering
Git repositories with partial clone filtering can have the filtering removed. To

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

View File

@ -228,15 +228,7 @@ If you already have an open issue, you can link to it from the vulnerability.
To link to an existing issue:
1. Open the vulnerability.
1. In the **Related Issues** section, select the plus (**{plus}**) icon.
1. In the text box that appears, type an issue number or paste an issue link.
- Type `#` followed by a number to show an autocomplete menu.
- You can enter multiple issues at once. Press the space bar after each issue number or link to converts them to tags.
1. Select **Add**.
To remove an issue, to the right of the issue number, select **{close}**.
![Vulnerability related issues text box tags animation](img/vulnerability_related_issues_text_box_tags_v13_2.gif)
1. [Add a linked issue](../project/issues/related_issues.md).
### Apply an automatic remediation for a vulnerability

View File

@ -179,17 +179,21 @@ For GitLab.com users, the KAS is available at `wss://kas.gitlab.com`.
Replace the value of `agent-token` below with the token received from the previous step. Also, replace `kas-address` with the configured access of the Kubernetes Agent Server:
```shell
docker run --rm registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/cli:latest generate --agent-token=your-agent-token --kas-address=wss://kas.gitlab.example.com --agent-version latest | kubectl apply -f -
docker run --pull=always --rm registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/cli:stable generate --agent-token=your-agent-token --kas-address=wss://kas.gitlab.example.com --agent-version stable | kubectl apply -f -
```
Set `agent-version` to the latest released patch version matching your
Set `--agent-version` to the latest released patch version matching your
GitLab installation's major and minor versions. For example, if you have
GitLab v13.9.0, set `--agent-version=v13.9.1`.
WARNING:
Version `stable` can be used to refer to the latest stable release at the time when the command runs. It's fine for
testing purposes but for production please make sure to specify a matching version explicitly.
To find out the various options the above Docker container supports, run:
```shell
docker run --rm -it registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/cli:latest generate --help
docker run --pull=always --rm registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/cli:stable generate --help
```
#### Advanced installation
@ -286,7 +290,8 @@ spec:
serviceAccountName: gitlab-agent
containers:
- name: agent
image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:latest"
# Make sure to specify a matching version for production
image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:stable"
args:
- --token-file=/config/token
- --kas-address
@ -554,7 +559,7 @@ Then in `resources.yml`:
serviceAccountName: gitlab-agent
containers:
- name: agent
image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:latest"
image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:<version>"
args:
- --token-file=/config/token
- --kas-address
@ -584,7 +589,7 @@ Alternatively, you can mount the certificate file at a different location and in
```yaml
containers:
- name: agent
image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:latest"
image: "registry.gitlab.com/gitlab-org/cluster-integration/gitlab-agent/agentk:<version>"
args:
- --ca-cert-file=/tmp/myCA.pem
- --token-file=/config/token

View File

@ -141,7 +141,7 @@ To remove a member from a group:
1. From the left menu, select **Members**.
1. Next to the member you want to remove, select **Delete**.
1. Optional. On the **Remove member** confirmation box, select the
**Also unassign this user from related issues and merge requests** checkbox.
**Also unassign this user from linked issues and merge requests** checkbox.
1. Select **Remove member**.
## Filter and sort members in a group

View File

@ -59,7 +59,7 @@ With GitLab Enterprise Edition, you can also:
- [Merge Request Approvals](project/merge_requests/merge_request_approvals.md).
- [Multiple Assignees for Issues](project/issues/multiple_assignees_for_issues.md).
- [Multiple Issue Boards](project/issue_board.md#multiple-issue-boards).
- Create formal relationships between issues with [Related Issues](project/issues/related_issues.md).
- Create formal relationships between issues with [linked issues](project/issues/related_issues.md).
- Use [Burndown Charts](project/milestones/burndown_and_burnup_charts.md) to track progress during a sprint or while working on a new version of their software.
- Leverage [Elasticsearch](../integration/elasticsearch.md) with [Advanced Search](search/advanced_search.md) for faster, more advanced code search across your entire GitLab instance.
- [Authenticate users with Kerberos](../integration/kerberos.md).

View File

@ -66,7 +66,7 @@ The following table depicts the various user permission levels in a project.
| Download and browse job artifacts | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ |
| Create confidential issue | ✓ | ✓ | ✓ | ✓ | ✓ |
| Create new issue | ✓ | ✓ | ✓ | ✓ | ✓ |
| See related issues | ✓ | ✓ | ✓ | ✓ | ✓ |
| See linked issues | ✓ | ✓ | ✓ | ✓ | ✓ |
| View [Releases](project/releases/index.md) | ✓ (*6*) | ✓ | ✓ | ✓ | ✓ |
| View requirements **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
| View Insights **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ |
@ -82,7 +82,7 @@ The following table depicts the various user permission levels in a project.
| [Set issue estimate and record time spent](project/time_tracking.md) | | ✓ | ✓ | ✓ | ✓ |
| Lock issue threads | | ✓ | ✓ | ✓ | ✓ |
| Manage issue tracker | | ✓ | ✓ | ✓ | ✓ |
| Manage related issues | | ✓ | ✓ | ✓ | ✓ |
| Manage linked issues | | ✓ | ✓ | ✓ | ✓ |
| Manage labels | | ✓ | ✓ | ✓ | ✓ |
| Create code snippets | | ✓ | ✓ | ✓ | ✓ |
| See a commit status | | ✓ | ✓ | ✓ | ✓ |

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

View File

@ -4,18 +4,23 @@ group: Ecosystem
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# Mattermost Notifications Service **(FREE)**
# Mattermost notifications service **(FREE)**
The Mattermost Notifications Service allows your GitLab project to send events (e.g., `issue created`) to your existing Mattermost team as notifications. This requires configurations in both Mattermost and GitLab.
Use the Mattermost notifications service to send notifications for GitLab events
(for example, `issue created`) to Mattermost. You must configure both [Mattermost](#configure-mattermost-to-receive-gitlab-notifications)
and [GitLab](#configure-gitlab-to-send-notifications-to-mattermost).
You can also use Mattermost slash commands to control GitLab inside Mattermost. This is the separately configured [Mattermost slash commands](mattermost_slash_commands.md).
You can also use [Mattermost slash commands](mattermost_slash_commands.md) to control
GitLab inside Mattermost.
## On Mattermost
## Configure Mattermost to receive GitLab notifications
To enable Mattermost integration you must create an incoming webhook integration:
To use the Mattermost integration you must create an incoming webhook integration
in Mattermost:
1. Sign in to your Mattermost instance.
1. Visit incoming webhooks, that is something like: `https://mattermost.example.com/your_team_name/integrations/incoming_webhooks/add`.
1. [Enable incoming webhooks](https://docs.mattermost.com/developer/webhooks-incoming.html#enabling-incoming-webhooks).
1. [Add an incoming webhook](https://docs.mattermost.com/developer/webhooks-incoming.html#creating-integrations-using-incoming-webhooks).
1. Choose a display name, description and channel, those can be overridden on GitLab.
1. Save it and copy the **Webhook URL** because we need this later for GitLab.
@ -29,36 +34,24 @@ to enable it on:
Display name override is not enabled by default, you need to ask your administrator to enable it on that same section.
## On GitLab
## Configure GitLab to send notifications to Mattermost
After you set up Mattermost, it's time to set up GitLab.
After the Mattermost instance has an incoming webhook set up, you can set up GitLab
to send the notifications.
Navigate to the [Integrations page](overview.md#accessing-integrations)
and select the **Mattermost notifications** service to configure it.
There, you see a checkbox with the following events that can be triggered:
and select the **Mattermost notifications** service. Select the GitLab events
you want to generate notifications for.
- Push
- Issue
- Confidential issue
- Merge request
- Note
- Confidential note
- Tag push
- Pipeline
- Wiki page
- Deployment
For each event you select, input the Mattermost channel you want to receive the
notification. You do not need to add the hash sign (`#`).
Below each of these event checkboxes, you have an input field to enter
which Mattermost channel you want to send that event message. Enter your preferred channel handle (the hash sign `#` is optional).
At the end, fill in your Mattermost details:
Then fill in the integration configuration:
| Field | Description |
| ----- | ----------- |
| **Webhook** | The incoming webhook URL which you have to set up on Mattermost, similar to: `http://mattermost.example/hooks/5xo…` |
| **Username** | Optional username which can be on messages sent to Mattermost. Fill this in if you want to change the username of the bot. |
| **Notify only broken pipelines** | If you choose to enable the **Pipeline** event and you want to be only notified about failed pipelines. |
| **Branches to be notified** | Select which types of branches to send notifications for. |
| **Labels to be notified** | Optional labels that the issue or merge request must have in order to trigger a notification. Leave blank to get all notifications. |
![Mattermost configuration](img/mattermost_configuration_v2.png)
| **Webhook** | The incoming webhook URL on Mattermost, similar to: `http://mattermost.example/hooks/5xo…`. |
| **Username** | (Optional) The username to show on messages sent to Mattermost. Fill this in to change the username of the bot. |
| **Notify only broken pipelines** | If you enable the **Pipeline** event and you want to be notified about failed pipelines only. |
| **Branches to be notified** | Select which branches to send notifications for. |
| **Labels to be notified** | (Optional) Labels that the issue or merge request must have to trigger a notification. Leave blank to get notifications for all issues and merge requests. |

View File

@ -4,18 +4,21 @@ group: Project Management
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
---
# Crosslinking Issues
# Crosslinking issues
Please read through the [GitLab Issue Documentation](index.md) for an overview on GitLab Issues.
There are several ways to mention an issue or make issues appear in each other's
[Linked issues](related_issues.md) section.
## From Commit Messages
For more information on GitLab Issues, read the [issues documentation](index.md).
## From commit messages
Every time you mention an issue in your commit message, you're creating
a relationship between the two stages of the development workflow: the
issue itself and the first commit related to that issue.
If the issue and the code you're committing are both in the same project,
you simply add `#xxx` to the commit message, where `xxx` is the issue number.
add `#xxx` to the commit message, where `xxx` is the issue number.
If they are not in the same project, you can add the full URL to the issue
(`https://gitlab.com/<username>/<projectname>/issues/<xxx>`).
@ -36,11 +39,10 @@ for tracking your process with [GitLab Value Stream Analytics](https://about.git
It measures the time taken for planning the implementation of that issue,
which is the time between creating an issue and making the first commit.
## From Related Issues
## From linked issues
Mentioning related issues in merge requests and other issues is useful
for your team members and collaborators to know that there are opened
issues regarding the same topic.
Mentioning linked issues in merge requests and other issues helps your team members and
collaborators know that there are opened issues regarding the same topic.
You do that as explained above, when [mentioning an issue from a commit message](#from-commit-messages).
@ -50,13 +52,13 @@ display in both issues. The same is valid when mentioning issues in [merge reque
![issue mentioned in issue](img/mention_in_issue.png)
## From Merge Requests
## From merge requests
Mentioning issues in merge request comments works exactly the same way as
they do for [related issues](#from-related-issues).
they do for [linked issues](#from-linked-issues).
When you mention an issue in a merge request description, it
[links the issue and merge request together](#from-related-issues). Additionally,
[links the issue and merge request together](#from-linked-issues). Additionally,
you can also [set an issue to close automatically](managing_issues.md#closing-issues-automatically)
as soon as the merge request is merged.

View File

@ -39,10 +39,10 @@ To learn how the GitLab Strategic Marketing department uses GitLab issues with [
- [Import issues](csv_import.md)
- [Export issues](csv_export.md)
- [Upload designs to issues](design_management.md)
- [Relate issues](related_issues.md)
- [Linked issues](related_issues.md)
- [Cross-link issues](crosslinking_issues.md)
- [Bulk edit issues](../bulk_editing.md)
- [Sort issue lists](sorting_issue_lists.md)
- [Sort issue lists](sorting_issue_lists.md)
- [Search for issues](../../search/index.md#filtering-issue-and-merge-request-lists)
- [Epics](../../group/epics/index.md)
- [Issue Boards](../issue_board.md)

View File

@ -39,7 +39,7 @@ The numbers in the image correspond to the following features:
- **15.** [Edit](#edit)
- **16.** [Description](#description)
- **17.** [Mentions](#mentions)
- **18.** [Related Issues](#related-issues)
- **18.** [Linked Issues](#linked-issues)
- **19.** [Related Merge Requests](#related-merge-requests)
- **20.** [Award emoji](#award-emoji)
- **21.** [Show all activity](#show-all-activity)
@ -205,10 +205,10 @@ in a different color, which allows you to quickly see which comments involve you
Avoid mentioning `@all` in issues and merge requests, as it sends an email notification
to all the members of that project's group. This might be interpreted as spam.
### Related Issues
### Linked Issues
Issues that were mentioned as [related issues](related_issues.md) are listed here.
You can also click the `+` to add more related issues.
Issues that were mentioned as [linked issues](related_issues.md) are listed here.
You can also click the `+` to add more linked issues.
### Related Merge Requests

View File

@ -6,8 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Linked issues **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1797) in GitLab 9.4.
> - The simple "relates to" relationship [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212329) to [GitLab Free](https://about.gitlab.com/pricing/) in 13.4.
> The simple "relates to" relationship [moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212329) to [GitLab Free](https://about.gitlab.com/pricing/) in 13.4.
Linked issues are a bi-directional relationship between any two issues and appear in a block below
the issue description. Issues can be across groups and projects.
@ -52,6 +51,9 @@ them categorized so their relationships can be better understood visually.
![Related issue block](img/related_issue_block_v12_8.png)
You can also add a linked issue from a commit message or the description in another issue or MR.
[Learn more about crosslinking issues](crosslinking_issues.md).
## Remove a linked issue
In the **Linked issues** section of an issue, click the remove button (**{close}**) on the

View File

@ -83,4 +83,4 @@ the following table.
You may enable or disable project access token creation for all projects in a group in **Group > Settings > General > Permissions, LFS, 2FA > Allow project access token creation**.
Even when creation is disabled, you can still use and revoke existing project access tokens.
This setting is only available on root-level groups.
This setting is available only on top-level groups.

View File

@ -558,10 +558,6 @@ module API
def increment_unique_values(event_name, values)
return unless values.present?
feature_flag = "usage_data_#{event_name}"
return unless Feature.enabled?(feature_flag, default_enabled: true)
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event_name, values: values)
rescue => error
Gitlab::AppLogger.warn("Redis tracking event failed for event: #{event_name}, message: #{error.message}")

View File

@ -87,6 +87,12 @@
aggregation: daily
feature_flag: track_epics_activity
- name: g_project_management_epic_issue_removed
category: epics_usage
redis_slot: project_management
aggregation: daily
feature_flag: track_epics_activity
- name: g_project_management_epic_closed
category: epics_usage
redis_slot: project_management

View File

@ -1776,6 +1776,9 @@ msgstr ""
msgid "Activity"
msgstr ""
msgid "Activity|An error occured while retrieving activity. Reload the page to try again."
msgstr ""
msgid "Add"
msgstr ""
@ -5802,9 +5805,6 @@ msgstr ""
msgid "Changing group URL can have unintended side effects."
msgstr ""
msgid "Channel handle (e.g. town-square)"
msgstr ""
msgid "Charts can't be displayed as the request for data has timed out. %{documentationLink}"
msgstr ""
@ -6438,12 +6438,24 @@ msgstr ""
msgid "CloudLicense|Activate"
msgstr ""
msgid "CloudLicense|Activate subscription"
msgstr ""
msgid "CloudLicense|Activation code"
msgstr ""
msgid "CloudLicense|I agree that my use of the GitLab Software is subject to the Subscription Agreement located at the %{linkStart}Terms of Service%{linkEnd}, unless otherwise agreed to in writing with GitLab."
msgstr ""
msgid "CloudLicense|ID"
msgstr ""
msgid "CloudLicense|Last Sync"
msgstr ""
msgid "CloudLicense|Learn how to %{linkStart}activate your subscription%{linkEnd}."
msgstr ""
msgid "CloudLicense|Licensed to"
msgstr ""
@ -6453,9 +6465,6 @@ msgstr ""
msgid "CloudLicense|Paste your activation code"
msgstr ""
msgid "CloudLicense|Paste your activation code below"
msgstr ""
msgid "CloudLicense|Plan"
msgstr ""
@ -6474,6 +6483,9 @@ msgstr ""
msgid "CloudLicense|This instance is currently using the %{planName} plan."
msgstr ""
msgid "CloudLicense|Your subscription"
msgstr ""
msgid "Cluster"
msgstr ""
@ -18999,6 +19011,9 @@ msgstr ""
msgid "Mattermost URL:"
msgstr ""
msgid "Mattermost notifications"
msgstr ""
msgid "MattermostService|Add to Mattermost"
msgstr ""
@ -21675,6 +21690,12 @@ msgstr ""
msgid "OnCallSchedules|Try adding a rotation"
msgstr ""
msgid "OnCallSchedules|View next timeframe"
msgstr ""
msgid "OnCallSchedules|View previous timeframe"
msgstr ""
msgid "OnCallSchedules|Your schedule has been successfully created and all alerts from this project will now be routed to this schedule. Currently, only one schedule can be created per project. More coming soon! To add individual users to this schedule, use the add a rotation button."
msgstr ""
@ -24164,42 +24185,6 @@ msgstr ""
msgid "ProjectService|Enter new password"
msgstr ""
msgid "ProjectService|Event triggered when a commit is created or updated."
msgstr ""
msgid "ProjectService|Event triggered when a confidential issue is created, updated, or closed."
msgstr ""
msgid "ProjectService|Event triggered when a deployment starts or finishes."
msgstr ""
msgid "ProjectService|Event triggered when a merge request is created, updated, or merged."
msgstr ""
msgid "ProjectService|Event triggered when a new tag is pushed to the repository."
msgstr ""
msgid "ProjectService|Event triggered when a new, unique alert is recorded."
msgstr ""
msgid "ProjectService|Event triggered when a pipeline status changes."
msgstr ""
msgid "ProjectService|Event triggered when a wiki page is created or updated."
msgstr ""
msgid "ProjectService|Event triggered when an issue is created, updated, or closed."
msgstr ""
msgid "ProjectService|Event triggered when someone adds a comment on a confidential issue."
msgstr ""
msgid "ProjectService|Event triggered when someone adds a comment."
msgstr ""
msgid "ProjectService|Event triggered when someone pushes to the repository."
msgstr ""
msgid "ProjectService|Issue URL"
msgstr ""
@ -24227,6 +24212,42 @@ msgstr ""
msgid "ProjectService|To configure this integration, you should:"
msgstr ""
msgid "ProjectService|Trigger event for new comments on confidential issues."
msgstr ""
msgid "ProjectService|Trigger event for new comments."
msgstr ""
msgid "ProjectService|Trigger event for new tags pushed to the repository."
msgstr ""
msgid "ProjectService|Trigger event for pushes to the repository."
msgstr ""
msgid "ProjectService|Trigger event when a commit is created or updated."
msgstr ""
msgid "ProjectService|Trigger event when a confidential issue is created, updated, or closed."
msgstr ""
msgid "ProjectService|Trigger event when a deployment starts or finishes."
msgstr ""
msgid "ProjectService|Trigger event when a merge request is created, updated, or merged."
msgstr ""
msgid "ProjectService|Trigger event when a new, unique alert is recorded."
msgstr ""
msgid "ProjectService|Trigger event when a pipeline status changes."
msgstr ""
msgid "ProjectService|Trigger event when a wiki page is created or updated."
msgstr ""
msgid "ProjectService|Trigger event when an issue is created, updated, or closed."
msgstr ""
msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
@ -27818,6 +27839,12 @@ msgstr ""
msgid "Send message"
msgstr ""
msgid "Send notifications about project events to Mattermost channels."
msgstr ""
msgid "Send notifications about project events to Mattermost channels. %{docs_link}"
msgstr ""
msgid "Send report"
msgstr ""
@ -36852,6 +36879,9 @@ msgstr ""
msgid "my-awesome-group"
msgstr ""
msgid "my-channel"
msgstr ""
msgid "n/a"
msgstr ""

View File

@ -26,10 +26,6 @@ function install_api_client_dependencies_with_apk() {
apk add --update openssl curl jq
}
function install_api_client_dependencies_with_apt() {
apt update && apt install jq -y
}
function install_gitlab_gem() {
gem install httparty --no-document --version 0.18.1
gem install gitlab --no-document --version 4.17.0

View File

@ -7,6 +7,7 @@ RSpec.describe 'When a user filters Sentry errors by status', :js, :use_clean_ra
let_it_be(:issues_response_body) { fixture_file('sentry/issues_sample_response.json') }
let_it_be(:filtered_errors_by_status_response) { Gitlab::Json.parse(issues_response_body).filter { |error| error['status'] == 'ignored' }.to_json }
let(:issues_api_url) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved" }
let(:issues_api_url_filter) { "#{sentry_api_urls.issues_url}?limit=20&query=is:ignored" }
let(:auth_token) {{ 'Authorization' => 'Bearer access_token_123' }}

View File

@ -7,6 +7,7 @@ RSpec.describe 'When a user searches for Sentry errors', :js, :use_clean_rails_m
let_it_be(:issues_response_body) { fixture_file('sentry/issues_sample_response.json') }
let_it_be(:error_search_response_body) { fixture_file('sentry/error_list_search_response.json') }
let(:issues_api_url) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved" }
let(:issues_api_url_search) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved%20NotFound" }

View File

@ -7,6 +7,7 @@ RSpec.describe 'View error index page', :js, :use_clean_rails_memory_store_cachi
let_it_be(:issues_response_body) { fixture_file('sentry/issues_sample_response.json') }
let_it_be(:issues_response) { Gitlab::Json.parse(issues_response_body) }
let(:issues_api_url) { "#{sentry_api_urls.issues_url}?limit=20&query=is:unresolved" }
before do

View File

@ -26,7 +26,6 @@ RSpec.describe 'Merge request > User sees pipelines triggered by merge request',
end
before do
stub_feature_flags(new_pipelines_table: false)
stub_application_setting(auto_devops_enabled: false)
stub_ci_pipeline_yaml_file(YAML.dump(config))
project.add_maintainer(user)

View File

@ -14,7 +14,6 @@ RSpec.describe 'Pipelines', :js do
sign_in(user)
stub_feature_flags(graphql_pipeline_details: false)
stub_feature_flags(graphql_pipeline_details_users: false)
stub_feature_flags(new_pipelines_table: false)
project.add_developer(user)
project.update!(auto_devops_attributes: { enabled: false })

View File

@ -254,7 +254,7 @@ describe('Tracking', () => {
expect(eventSpy).toHaveBeenCalledWith('_category_', 'nested_event', {});
});
it('brings in experiment data if linked to an experiment', () => {
it('includes experiment data if linked to an experiment', () => {
const mockExperimentData = {
variant: 'candidate',
experiment: 'repo_integrations_link',
@ -326,6 +326,30 @@ describe('Tracking', () => {
mixin.computed.tracking = { foo: 'baz', baz: 'bar' };
expect(mixin.computed.trackingOptions()).toEqual({ foo: 'baz', baz: 'bar' });
});
it('includes experiment data if linked to an experiment', () => {
const mockExperimentData = {
variant: 'candidate',
experiment: 'darkMode',
};
getExperimentData.mockReturnValue(mockExperimentData);
const mixin = Tracking.mixin({ foo: 'bar', experiment: 'darkMode' });
expect(mixin.computed.trackingOptions()).toEqual({
foo: 'bar',
context: {
schema: TRACKING_CONTEXT_SCHEMA,
data: mockExperimentData,
},
});
});
it('does not include experiment data if experiment data does not exist', () => {
const mixin = Tracking.mixin({ foo: 'bar', experiment: 'lightMode' });
expect(mixin.computed.trackingOptions()).toEqual({
foo: 'bar',
});
});
});
describe('trackingCategory', () => {

View File

@ -179,46 +179,23 @@ RSpec.describe API::Helpers do
let(:value) { '9f302fea-f828-4ca9-aef4-e10bd723c0b3' }
let(:event_name) { 'g_compliance_dashboard' }
let(:unknown_event) { 'unknown' }
let(:feature) { "usage_data_#{event_name}" }
before do
skip_feature_flags_yaml_validation
it 'tracks redis hll event' do
expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(event_name, values: value)
subject.increment_unique_values(event_name, value)
end
context 'with feature enabled' do
before do
stub_feature_flags(feature => true)
end
it 'logs an exception for unknown event' do
expect(Gitlab::AppLogger).to receive(:warn).with("Redis tracking event failed for event: #{unknown_event}, message: Unknown event #{unknown_event}")
it 'tracks redis hll event' do
expect(Gitlab::UsageDataCounters::HLLRedisCounter).to receive(:track_event).with(event_name, values: value)
subject.increment_unique_values(event_name, value)
end
it 'logs an exception for unknown event' do
expect(Gitlab::AppLogger).to receive(:warn).with("Redis tracking event failed for event: #{unknown_event}, message: Unknown event #{unknown_event}")
subject.increment_unique_values(unknown_event, value)
end
it 'does not track event for nil values' do
expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
subject.increment_unique_values(unknown_event, nil)
end
subject.increment_unique_values(unknown_event, value)
end
context 'with feature disabled' do
before do
stub_feature_flags(feature => false)
end
it 'does not track event for nil values' do
expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
it 'does not track event' do
expect(Gitlab::UsageDataCounters::HLLRedisCounter).not_to receive(:track_event)
subject.increment_unique_values(event_name, value)
end
subject.increment_unique_values(unknown_event, nil)
end
end

View File

@ -5,6 +5,7 @@ require 'spec_helper'
RSpec.describe Ci::ArtifactBlob do
let_it_be(:project) { create(:project, :public) }
let_it_be(:build) { create(:ci_build, :artifacts, project: project) }
let(:entry) { build.artifacts_metadata_entry('other_artifacts_0.1.2/another-subdirectory/banana_sample.gif') }
subject { described_class.new(entry) }

View File

@ -3730,6 +3730,7 @@ RSpec.describe Ci::Build do
describe '.matches_tag_ids' do
let_it_be(:build, reload: true) { create(:ci_build, project: project, user: user) }
let(:tag_ids) { ::ActsAsTaggableOn::Tag.named_any(tag_list).ids }
subject { described_class.where(id: build).matches_tag_ids(tag_ids) }
@ -4181,6 +4182,7 @@ RSpec.describe Ci::Build do
describe '#artifacts_metadata_entry' do
let_it_be(:build) { create(:ci_build, project: project) }
let(:path) { 'other_artifacts_0.1.2/another-subdirectory/banana_sample.gif' }
around do |example|

View File

@ -6,6 +6,7 @@ RSpec.describe Ci::BuildTraceChunk, :clean_gitlab_redis_shared_state do
include ExclusiveLeaseHelpers
let_it_be(:build) { create(:ci_build, :running) }
let(:chunk_index) { 0 }
let(:data_store) { :redis }
let(:raw_data) { nil }

View File

@ -86,6 +86,7 @@ RSpec.describe Ci::DailyBuildGroupReportResult do
describe 'scopes' do
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let(:recent_build_group_report_result) { create(:ci_daily_build_group_report_result, project: project, group: group) }
let(:old_build_group_report_result) do
create(:ci_daily_build_group_report_result, date: 1.week.ago, project: project)

View File

@ -427,6 +427,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
subject { pipeline.legacy_detached_merge_request_pipeline? }
let_it_be(:merge_request) { create(:merge_request) }
let(:ref) { 'feature' }
let(:target_sha) { nil }
@ -832,6 +833,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
let_it_be(:assignees) { create_list(:user, 2) }
let_it_be(:milestone) { create(:milestone, project: project) }
let_it_be(:labels) { create_list(:label, 2) }
let(:merge_request) do
create(:merge_request, :simple,
source_project: project,
@ -1276,6 +1278,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe 'state machine' do
let_it_be_with_reload(:pipeline) { create(:ci_empty_pipeline, :created) }
let(:current) { Time.current.change(usec: 0) }
let(:build) { create_build('build1', queued_at: 0) }
let(:build_b) { create_build('build2', queued_at: 0) }
@ -2327,6 +2330,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
subject { pipeline.reload.status }
let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
let(:build) { create(:ci_build, :created, pipeline: pipeline, name: 'test') }
context 'on waiting for resource' do
@ -2721,6 +2725,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#execute_hooks' do
let_it_be(:pipeline) { create(:ci_empty_pipeline, :created) }
let!(:build_a) { create_build('a', 0) }
let!(:build_b) { create_build('b', 0) }
@ -3386,6 +3391,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#build_with_artifacts_in_self_and_descendants' do
let_it_be(:pipeline) { create(:ci_pipeline) }
let!(:build) { create(:ci_build, name: 'test', pipeline: pipeline) }
let(:child_pipeline) { create(:ci_pipeline, child_of: pipeline) }
let!(:child_build) { create(:ci_build, :artifacts, name: 'test', pipeline: child_pipeline) }
@ -3896,6 +3902,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
describe '#find_stage_by_name' do
let_it_be(:pipeline) { create(:ci_pipeline) }
let(:stage_name) { 'test' }
let(:stage) do
@ -4181,6 +4188,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
subject { pipeline.base_and_ancestors(same_project: same_project) }
let_it_be(:pipeline) { create(:ci_pipeline, :created) }
let(:same_project) { false }
context 'when pipeline is not child nor parent' do
@ -4217,6 +4225,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when pipeline is a child of a child pipeline' do
let_it_be(:pipeline) { create(:ci_pipeline, :created) }
let(:ancestor) { create(:ci_pipeline) }
let(:parent) { create(:ci_pipeline) }
@ -4232,6 +4241,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
context 'when pipeline is a triggered pipeline' do
let_it_be(:pipeline) { create(:ci_pipeline, :created) }
let(:upstream) { create(:ci_pipeline, project: create(:project)) }
before do

View File

@ -353,6 +353,7 @@ RSpec.describe Ci::Runner do
using RSpec::Parameterized::TableSyntax
let_it_be(:pipeline) { create(:ci_pipeline) }
let(:build) { create(:ci_build, pipeline: pipeline) }
let(:runner_project) { build.project }
let(:runner) { create(:ci_runner, :project, projects: [runner_project], tag_list: tag_list, run_untagged: run_untagged) }

View File

@ -4,6 +4,7 @@ require 'spec_helper'
RSpec.describe Ci::Stage, :models do
let_it_be(:pipeline) { create(:ci_empty_pipeline) }
let(:stage) { create(:ci_stage_entity, pipeline: pipeline, project: pipeline.project) }
it_behaves_like 'having unique enum values'

View File

@ -17,7 +17,7 @@ RSpec.describe ServiceEventEntity do
let(:event) { 'push' }
it 'exposes correct attributes' do
expect(subject[:description]).to eq('Event triggered when someone pushes to the repository.')
expect(subject[:description]).to eq('Trigger event for pushes to the repository.')
expect(subject[:name]).to eq('push_events')
expect(subject[:title]).to eq('push')
expect(subject[:value]).to be(true)
@ -29,7 +29,7 @@ RSpec.describe ServiceEventEntity do
let(:event) { 'note' }
it 'exposes correct attributes' do
expect(subject[:description]).to eq('Event triggered when someone adds a comment.')
expect(subject[:description]).to eq('Trigger event for new comments.')
expect(subject[:name]).to eq('note_events')
expect(subject[:title]).to eq('note')
expect(subject[:value]).to eq(false)

View File

@ -673,7 +673,17 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(rugged.config['gitlab.fullpath']).to eq project.full_path
end
it 'triggers PostCreationWorker' do
expect(Projects::PostCreationWorker).to receive(:perform_async).with(a_kind_of(Integer))
create_project(user, opts)
end
context 'when project has access to shared service' do
before do
stub_feature_flags(projects_post_creation_worker: false)
end
context 'Prometheus application is shared via group cluster' do
let(:cluster) { create(:cluster, :group, groups: [group]) }
let(:group) do

View File

@ -0,0 +1,89 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Projects::PostCreationWorker do
let_it_be(:user) { create :user }
let(:worker) { described_class.new }
let(:project) { create(:project) }
subject { described_class.new.perform(project.id) }
it_behaves_like 'an idempotent worker' do
let(:job_args) { [project.id] }
describe 'Prometheus service' do
context 'project is nil' do
let(:job_args) { [nil] }
it 'does not create prometheus service' do
expect { subject }.not_to change { Service.count }
end
end
context 'when project has access to shared service' do
context 'Prometheus application is shared via group cluster' do
let(:project) { create(:project, group: group) }
let(:cluster) { create(:cluster, :group, groups: [group]) }
let(:group) do
create(:group).tap do |group|
group.add_owner(user)
end
end
before do
create(:clusters_applications_prometheus, :installed, cluster: cluster)
end
it 'creates PrometheusService record', :aggregate_failures do
subject
service = project.prometheus_service
expect(service.active).to be true
expect(service.manual_configuration?).to be false
expect(service.persisted?).to be true
end
end
context 'Prometheus application is shared via instance cluster' do
let(:cluster) { create(:cluster, :instance) }
before do
create(:clusters_applications_prometheus, :installed, cluster: cluster)
end
it 'creates PrometheusService record', :aggregate_failures do
subject
service = project.prometheus_service
expect(service.active).to be true
expect(service.manual_configuration?).to be false
expect(service.persisted?).to be true
end
it 'cleans invalid record and logs warning', :aggregate_failures do
invalid_service_record = build(:prometheus_service, properties: { api_url: nil, manual_configuration: true }.to_json)
allow_next_found_instance_of(Project) do |instance|
allow(instance).to receive(:build_prometheus_service).and_return(invalid_service_record)
end
expect(Gitlab::ErrorTracking).to receive(:track_exception).with(an_instance_of(ActiveRecord::RecordInvalid), include(extra: { project_id: a_kind_of(Integer) })).twice
subject
expect(project.prometheus_service).to be_nil
end
end
context 'shared Prometheus application is not available' do
it 'does not persist PrometheusService record', :aggregate_failures do
subject
expect(project.prometheus_service).to be_nil
end
end
end
end
end
end