Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
79347b42ae
commit
76e4e8f1b0
|
@ -103,7 +103,7 @@ yarn-audit-dependency_scanning:
|
||||||
extends: .default-retry
|
extends: .default-retry
|
||||||
stage: test
|
stage: test
|
||||||
image:
|
image:
|
||||||
name: registry.gitlab.com/gitlab-com/gl-security/security-research/package-hunter-cli:1.1.0
|
name: registry.gitlab.com/gitlab-org/security-products/package-hunter-cli:v1.3.0@sha256:6cb717d1772cf5a8a68dd8268e44925f71b7867d9f3fa41a4ba2c291b7446c50
|
||||||
entrypoint: [""]
|
entrypoint: [""]
|
||||||
variables:
|
variables:
|
||||||
HTR_user: '$PACKAGE_HUNTER_USER'
|
HTR_user: '$PACKAGE_HUNTER_USER'
|
||||||
|
|
|
@ -406,7 +406,7 @@ function deduplicateFilesList(files) {
|
||||||
|
|
||||||
export function prepareDiffData({ diff, priorFiles = [], meta = false }) {
|
export function prepareDiffData({ diff, priorFiles = [], meta = false }) {
|
||||||
const cleanedFiles = (diff.diff_files || [])
|
const cleanedFiles = (diff.diff_files || [])
|
||||||
.map((file, index, allFiles) => prepareRawDiffFile({ file, allFiles, meta }))
|
.map((file, index, allFiles) => prepareRawDiffFile({ file, allFiles, meta, index }))
|
||||||
.map(ensureBasicDiffFileLines)
|
.map(ensureBasicDiffFileLines)
|
||||||
.map(prepareDiffFileLines)
|
.map(prepareDiffFileLines)
|
||||||
.map((file) => finalizeDiffFile(file));
|
.map((file) => finalizeDiffFile(file));
|
||||||
|
|
|
@ -50,7 +50,7 @@ function identifier(file) {
|
||||||
|
|
||||||
export const isNotDiffable = (file) => file?.viewer?.name === viewerModes.not_diffable;
|
export const isNotDiffable = (file) => file?.viewer?.name === viewerModes.not_diffable;
|
||||||
|
|
||||||
export function prepareRawDiffFile({ file, allFiles, meta = false }) {
|
export function prepareRawDiffFile({ file, allFiles, meta = false, index = -1 }) {
|
||||||
const additionalProperties = {
|
const additionalProperties = {
|
||||||
brokenSymlink: fileSymlinkInformation(file, allFiles),
|
brokenSymlink: fileSymlinkInformation(file, allFiles),
|
||||||
viewer: {
|
viewer: {
|
||||||
|
@ -66,6 +66,10 @@ export function prepareRawDiffFile({ file, allFiles, meta = false }) {
|
||||||
additionalProperties.id = identifier(file);
|
additionalProperties.id = identifier(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (index >= 0 && Number(index) === index) {
|
||||||
|
additionalProperties.order = index;
|
||||||
|
}
|
||||||
|
|
||||||
return Object.assign(file, additionalProperties);
|
return Object.assign(file, additionalProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { formatDate } from './date_format_utility';
|
||||||
*
|
*
|
||||||
* see https://github.com/hustcc/timeago.js/tree/v3.0.0/locales
|
* see https://github.com/hustcc/timeago.js/tree/v3.0.0/locales
|
||||||
*/
|
*/
|
||||||
const timeagoLanguageCode = languageCode().replace(/-/g, '_');
|
export const timeagoLanguageCode = languageCode().replace(/-/g, '_');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers timeago locales
|
* Registers timeago locales
|
||||||
|
|
|
@ -14,6 +14,8 @@ const LIST_LINE_HEAD_PATTERN = /^(?<indent>\s*)(?<leader>((?<isUl>[*+-])|(?<isOl
|
||||||
// detect a horizontal rule that might be mistaken for a list item (not full pattern for an <hr>)
|
// detect a horizontal rule that might be mistaken for a list item (not full pattern for an <hr>)
|
||||||
const HR_PATTERN = /^((\s{0,3}-+\s*-+\s*-+\s*[\s-]*)|(\s{0,3}\*+\s*\*+\s*\*+\s*[\s*]*))$/;
|
const HR_PATTERN = /^((\s{0,3}-+\s*-+\s*-+\s*[\s-]*)|(\s{0,3}\*+\s*\*+\s*\*+\s*[\s*]*))$/;
|
||||||
|
|
||||||
|
let compositioningNoteText = false;
|
||||||
|
|
||||||
function selectedText(text, textarea) {
|
function selectedText(text, textarea) {
|
||||||
return text.substring(textarea.selectionStart, textarea.selectionEnd);
|
return text.substring(textarea.selectionStart, textarea.selectionEnd);
|
||||||
}
|
}
|
||||||
|
@ -367,6 +369,8 @@ function handleContinueList(e, textArea) {
|
||||||
if (!(e.key === 'Enter')) return;
|
if (!(e.key === 'Enter')) return;
|
||||||
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return;
|
if (e.altKey || e.ctrlKey || e.metaKey || e.shiftKey) return;
|
||||||
if (textArea.selectionStart !== textArea.selectionEnd) return;
|
if (textArea.selectionStart !== textArea.selectionEnd) return;
|
||||||
|
// prevent unintended line breaks were inserted using Japanese IME on MacOS
|
||||||
|
if (compositioningNoteText) return;
|
||||||
|
|
||||||
const currentLine = lineBefore(textArea.value, textArea, false);
|
const currentLine = lineBefore(textArea.value, textArea, false);
|
||||||
const result = currentLine.match(LIST_LINE_HEAD_PATTERN);
|
const result = currentLine.match(LIST_LINE_HEAD_PATTERN);
|
||||||
|
@ -420,6 +424,14 @@ export function keypressNoteText(e) {
|
||||||
handleSurroundSelectedText(e, textArea);
|
handleSurroundSelectedText(e, textArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function compositionStartNoteText() {
|
||||||
|
compositioningNoteText = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function compositionEndNoteText() {
|
||||||
|
compositioningNoteText = false;
|
||||||
|
}
|
||||||
|
|
||||||
export function updateTextForToolbarBtn($toolbarBtn) {
|
export function updateTextForToolbarBtn($toolbarBtn) {
|
||||||
return updateText({
|
return updateText({
|
||||||
textArea: $toolbarBtn.closest('.md-area').find('textarea'),
|
textArea: $toolbarBtn.closest('.md-area').find('textarea'),
|
||||||
|
@ -435,6 +447,8 @@ export function updateTextForToolbarBtn($toolbarBtn) {
|
||||||
export function addMarkdownListeners(form) {
|
export function addMarkdownListeners(form) {
|
||||||
$('.markdown-area', form)
|
$('.markdown-area', form)
|
||||||
.on('keydown', keypressNoteText)
|
.on('keydown', keypressNoteText)
|
||||||
|
.on('compositionstart', compositionStartNoteText)
|
||||||
|
.on('compositionend', compositionEndNoteText)
|
||||||
.each(function attachTextareaShortcutHandlers() {
|
.each(function attachTextareaShortcutHandlers() {
|
||||||
Shortcuts.initMarkdownEditorShortcuts($(this), updateTextForToolbarBtn);
|
Shortcuts.initMarkdownEditorShortcuts($(this), updateTextForToolbarBtn);
|
||||||
});
|
});
|
||||||
|
@ -474,6 +488,8 @@ export function addEditorMarkdownListeners(editor) {
|
||||||
export function removeMarkdownListeners(form) {
|
export function removeMarkdownListeners(form) {
|
||||||
$('.markdown-area', form)
|
$('.markdown-area', form)
|
||||||
.off('keydown', keypressNoteText)
|
.off('keydown', keypressNoteText)
|
||||||
|
.off('compositionstart', compositionStartNoteText)
|
||||||
|
.off('compositionend', compositionEndNoteText)
|
||||||
.each(function removeTextareaShortcutHandlers() {
|
.each(function removeTextareaShortcutHandlers() {
|
||||||
Shortcuts.removeMarkdownEditorShortcuts($(this));
|
Shortcuts.removeMarkdownEditorShortcuts($(this));
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { formatDate, getTimeago } from '~/lib/utils/datetime_utility';
|
import { formatDate, getTimeago, timeagoLanguageCode } from '~/lib/utils/datetime_utility';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mixin with time ago methods used in some vue components
|
* Mixin with time ago methods used in some vue components
|
||||||
|
@ -8,7 +8,7 @@ export default {
|
||||||
timeFormatted(time) {
|
timeFormatted(time) {
|
||||||
const timeago = getTimeago();
|
const timeago = getTimeago();
|
||||||
|
|
||||||
return timeago.format(time);
|
return timeago.format(time, timeagoLanguageCode);
|
||||||
},
|
},
|
||||||
|
|
||||||
tooltipTitle(time) {
|
tooltipTitle(time) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* https://github.com/richleland/pygments-css/blob/master/monokai.css */
|
/* https://github.com/richleland/pygments-css/blob/master/monokai.css */
|
||||||
|
|
||||||
@import '../common';
|
@import '../common';
|
||||||
|
@import 'highlight.js/styles/base16/monokai.css';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Monokai Colors
|
* Monokai Colors
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* https://gist.github.com/qguv/7936275 */
|
/* https://gist.github.com/qguv/7936275 */
|
||||||
|
|
||||||
@import '../common';
|
@import '../common';
|
||||||
|
@import 'highlight.js/styles/base16/solarized-dark.css';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Solarized dark colors
|
* Solarized dark colors
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/* https://gist.github.com/qguv/7936275 */
|
/* https://gist.github.com/qguv/7936275 */
|
||||||
|
|
||||||
@import '../common';
|
@import '../common';
|
||||||
|
@import 'highlight.js/styles/base16/solarized-light.css';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Solarized light syntax colors
|
* Solarized light syntax colors
|
||||||
|
|
|
@ -28,7 +28,6 @@ module Projects
|
||||||
private
|
private
|
||||||
|
|
||||||
def render_logs(service, permitted_params)
|
def render_logs(service, permitted_params)
|
||||||
::Gitlab::UsageCounters::PodLogs.increment(project.id)
|
|
||||||
::Gitlab::PollingInterval.set_header(response, interval: 3_000)
|
::Gitlab::PollingInterval.set_header(response, interval: 3_000)
|
||||||
|
|
||||||
result = service.new(cluster, namespace, params: permitted_params).execute
|
result = service.new(cluster, namespace, params: permitted_params).execute
|
||||||
|
|
|
@ -11,6 +11,16 @@ module Clusters
|
||||||
|
|
||||||
RESERVED_NAMESPACES = %w(gitlab-managed-apps).freeze
|
RESERVED_NAMESPACES = %w(gitlab-managed-apps).freeze
|
||||||
|
|
||||||
|
IGNORED_CONNECTION_EXCEPTIONS = [
|
||||||
|
Gitlab::UrlBlocker::BlockedUrlError,
|
||||||
|
Kubeclient::HttpError,
|
||||||
|
Errno::ECONNREFUSED,
|
||||||
|
URI::InvalidURIError,
|
||||||
|
Errno::EHOSTUNREACH,
|
||||||
|
OpenSSL::X509::StoreError,
|
||||||
|
OpenSSL::SSL::SSLError
|
||||||
|
].freeze
|
||||||
|
|
||||||
self.table_name = 'cluster_platforms_kubernetes'
|
self.table_name = 'cluster_platforms_kubernetes'
|
||||||
self.reactive_cache_work_type = :external_dependency
|
self.reactive_cache_work_type = :external_dependency
|
||||||
|
|
||||||
|
@ -102,10 +112,23 @@ module Clusters
|
||||||
def calculate_reactive_cache_for(environment)
|
def calculate_reactive_cache_for(environment)
|
||||||
return unless enabled?
|
return unless enabled?
|
||||||
|
|
||||||
pods = read_pods(environment.deployment_namespace)
|
pods = []
|
||||||
deployments = read_deployments(environment.deployment_namespace)
|
deployments = []
|
||||||
|
ingresses = []
|
||||||
|
|
||||||
ingresses = read_ingresses(environment.deployment_namespace)
|
begin
|
||||||
|
pods = read_pods(environment.deployment_namespace)
|
||||||
|
deployments = read_deployments(environment.deployment_namespace)
|
||||||
|
|
||||||
|
ingresses = read_ingresses(environment.deployment_namespace)
|
||||||
|
rescue *IGNORED_CONNECTION_EXCEPTIONS => e
|
||||||
|
log_kube_connection_error(e)
|
||||||
|
|
||||||
|
# Return hash with default values so that it is cached.
|
||||||
|
return {
|
||||||
|
pods: pods, deployments: deployments, ingresses: ingresses
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
# extract only the data required for display to avoid unnecessary caching
|
# extract only the data required for display to avoid unnecessary caching
|
||||||
{
|
{
|
||||||
|
@ -292,6 +315,23 @@ module Clusters
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def log_kube_connection_error(error)
|
||||||
|
logger.error({
|
||||||
|
exception: {
|
||||||
|
class: error.class.name,
|
||||||
|
message: error.message
|
||||||
|
},
|
||||||
|
status_code: error.error_code,
|
||||||
|
namespace: self.namespace,
|
||||||
|
class_name: self.class.name,
|
||||||
|
event: :kube_connection_error
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
def logger
|
||||||
|
@logger ||= Gitlab::Kubernetes::Logger.build
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,7 +3,7 @@ table_name: clusters_integration_elasticstack
|
||||||
classes:
|
classes:
|
||||||
- Clusters::Integrations::ElasticStack
|
- Clusters::Integrations::ElasticStack
|
||||||
feature_categories:
|
feature_categories:
|
||||||
- integrations
|
- configure
|
||||||
description: TODO
|
description: TODO
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61077
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/61077
|
||||||
milestone: '13.12'
|
milestone: '13.12'
|
||||||
|
|
|
@ -50,6 +50,7 @@ classes:
|
||||||
- Integrations::Zentao
|
- Integrations::Zentao
|
||||||
feature_categories:
|
feature_categories:
|
||||||
- integrations
|
- integrations
|
||||||
description: TODO
|
description: Support 3rd party integrations: Jira, Slack, etc., formerly services table.
|
||||||
|
https://gitlab.com/gitlab-org/gitlab/-/commit/1dab19d0d7b25cb5af27b8d10c8b615b2d38c2cf
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64562
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64562
|
||||||
milestone: '9.4'
|
milestone: '9.4'
|
||||||
|
|
|
@ -4,6 +4,6 @@ classes:
|
||||||
- Integrations::IssueTrackerData
|
- Integrations::IssueTrackerData
|
||||||
feature_categories:
|
feature_categories:
|
||||||
- integrations
|
- integrations
|
||||||
description: TODO
|
description: Data related to the issue tracker integrations.
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/1f332ae8da994509232c7601074b25514ad23c52
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/14187
|
||||||
milestone: '12.0'
|
milestone: '12.0'
|
||||||
|
|
|
@ -4,6 +4,6 @@ classes:
|
||||||
- JiraConnectInstallation
|
- JiraConnectInstallation
|
||||||
feature_categories:
|
feature_categories:
|
||||||
- integrations
|
- integrations
|
||||||
description: TODO
|
description: GitLab.com for Jira Cloud app installation data, formerly Jira Connect App.
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9593
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/9593
|
||||||
milestone: '11.9'
|
milestone: '11.9'
|
||||||
|
|
|
@ -4,6 +4,6 @@ classes:
|
||||||
- JiraConnectSubscription
|
- JiraConnectSubscription
|
||||||
feature_categories:
|
feature_categories:
|
||||||
- integrations
|
- integrations
|
||||||
description: TODO
|
description: GitLab.com for Jira Cloud app subscriptions data, formerly Jira Connect App.
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/10453
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/10453
|
||||||
milestone: '11.11'
|
milestone: '11.11'
|
||||||
|
|
|
@ -4,6 +4,6 @@ classes:
|
||||||
- JiraImportState
|
- JiraImportState
|
||||||
feature_categories:
|
feature_categories:
|
||||||
- integrations
|
- integrations
|
||||||
description: TODO
|
description: Track Jira issue import progress into GitLab issues.
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/9af97ee69a36de1dc4e73f4030d6316d3f0a82c5
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28108
|
||||||
milestone: '13.0'
|
milestone: '12.10'
|
||||||
|
|
|
@ -4,6 +4,6 @@ classes:
|
||||||
- Integrations::JiraTrackerData
|
- Integrations::JiraTrackerData
|
||||||
feature_categories:
|
feature_categories:
|
||||||
- integrations
|
- integrations
|
||||||
description: TODO
|
description: Data related to the Jira integration.
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/1f332ae8da994509232c7601074b25514ad23c52
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/1f332ae8da994509232c7601074b25514ad23c52
|
||||||
milestone: '12.0'
|
milestone: '12.0'
|
||||||
|
|
|
@ -3,7 +3,7 @@ table_name: operations_feature_flags
|
||||||
classes:
|
classes:
|
||||||
- Operations::FeatureFlag
|
- Operations::FeatureFlag
|
||||||
feature_categories:
|
feature_categories:
|
||||||
- integrations
|
- release
|
||||||
description: TODO
|
description: TODO
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7433
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7433
|
||||||
milestone: '11.4'
|
milestone: '11.4'
|
||||||
|
|
|
@ -4,6 +4,6 @@ classes:
|
||||||
- SlackIntegration
|
- SlackIntegration
|
||||||
feature_categories:
|
feature_categories:
|
||||||
- integrations
|
- integrations
|
||||||
description: TODO
|
description: Data related to the Slack application integration.
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/f50ef96b87d8c785662e82843c22a2ef6093132e
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/f50ef96b87d8c785662e82843c22a2ef6093132e
|
||||||
milestone: '9.4'
|
milestone: '9.4'
|
||||||
|
|
|
@ -4,6 +4,6 @@ classes:
|
||||||
- WebHookLog
|
- WebHookLog
|
||||||
feature_categories:
|
feature_categories:
|
||||||
- integrations
|
- integrations
|
||||||
description: TODO
|
description: Webhooks logs data.
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/330789c23c777d8ca646eba7c25f39cb7342cdee
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/330789c23c777d8ca646eba7c25f39cb7342cdee
|
||||||
milestone: '9.3'
|
milestone: '9.3'
|
||||||
|
|
|
@ -8,6 +8,6 @@ classes:
|
||||||
- WebHook
|
- WebHook
|
||||||
feature_categories:
|
feature_categories:
|
||||||
- integrations
|
- integrations
|
||||||
description: TODO
|
description: Webhooks data with the custom HTTP callbacks that a user defines.
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/edab46e9fa5f568b1423c0021e81d30453d7dc1e
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/edab46e9fa5f568b1423c0021e81d30453d7dc1e
|
||||||
milestone: "<6.0"
|
milestone: "<6.0"
|
||||||
|
|
|
@ -4,6 +4,6 @@ classes:
|
||||||
- Integrations::ZentaoTrackerData
|
- Integrations::ZentaoTrackerData
|
||||||
feature_categories:
|
feature_categories:
|
||||||
- integrations
|
- integrations
|
||||||
description: TODO
|
description: Data related to the ZenTao integration.
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67938
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/67938
|
||||||
milestone: '14.2'
|
milestone: '14.2'
|
||||||
|
|
|
@ -268,10 +268,9 @@ Arguments:
|
||||||
|
|
||||||
#### Ordinary Redis counters
|
#### Ordinary Redis counters
|
||||||
|
|
||||||
Examples of implementation:
|
Example of implementation:
|
||||||
|
|
||||||
- Using Redis methods [`INCR`](https://redis.io/commands/incr), [`GET`](https://redis.io/commands/get), and [`Gitlab::UsageDataCounters::WikiPageCounter`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/wiki_page_counter.rb)
|
Using Redis methods [`INCR`](https://redis.io/commands/incr), [`GET`](https://redis.io/commands/get), and [`Gitlab::UsageDataCounters::WikiPageCounter`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/wiki_page_counter.rb)
|
||||||
- Using Redis methods [`HINCRBY`](https://redis.io/commands/hincrby), [`HGETALL`](https://redis.io/commands/hgetall), and [`Gitlab::UsageCounters::PodLogs`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_counters/pod_logs.rb)
|
|
||||||
|
|
||||||
##### `UsageData` API
|
##### `UsageData` API
|
||||||
|
|
||||||
|
@ -580,7 +579,6 @@ Example:
|
||||||
```ruby
|
```ruby
|
||||||
# Redis Counters
|
# Redis Counters
|
||||||
redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter)
|
redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter)
|
||||||
redis_usage_data { ::Gitlab::UsageCounters::PodLogs.usage_totals[:total] }
|
|
||||||
|
|
||||||
# Define events in common.yml https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml
|
# Define events in common.yml https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml
|
||||||
|
|
||||||
|
|
|
@ -127,12 +127,6 @@ To retrieve metrics for change failure rate, use the [GraphQL](../../api/graphql
|
||||||
|
|
||||||
We use the following terms to describe GitLab analytics:
|
We use the following terms to describe GitLab analytics:
|
||||||
|
|
||||||
- **Cycle time:** The duration of only the execution work. Cycle time is often displayed in combination with the lead time, which is longer than the cycle time. GitLab measures cycle time from the earliest commit of a [linked issue's merge request](../project/issues/crosslinking_issues.md) to when that issue is closed. The cycle time approach underestimates the lead time because merge request creation is always later than commit time. GitLab displays cycle time in [group-level Value Stream Analytics](../group/value_stream_analytics/index.md) and [project-level Value Stream Analytics](../analytics/value_stream_analytics.md).
|
|
||||||
- **Deploys:** The total number of successful deployments to production in the given time frame (across all applicable projects). GitLab displays deploys in [group-level Value Stream Analytics](../group/value_stream_analytics/index.md) and [project-level Value Stream Analytics](value_stream_analytics.md).
|
|
||||||
- **Lead time:** The duration of your value stream, from start to finish. Different to
|
|
||||||
[Lead time for changes](#lead-time-for-changes). Often displayed in combination with "cycle time,"
|
|
||||||
which is shorter. GitLab measures lead time from issue creation to issue close. GitLab displays lead
|
|
||||||
time in [group-level Value Stream Analytics](../group/value_stream_analytics/index.md).
|
|
||||||
- **Mean Time to Change (MTTC):** The average duration between idea and delivery. GitLab measures
|
- **Mean Time to Change (MTTC):** The average duration between idea and delivery. GitLab measures
|
||||||
MTTC from issue creation to the issue's latest related merge request's deployment to production.
|
MTTC from issue creation to the issue's latest related merge request's deployment to production.
|
||||||
- **Mean Time to Detect (MTTD):** The average duration that a bug goes undetected in production.
|
- **Mean Time to Detect (MTTD):** The average duration that a bug goes undetected in production.
|
||||||
|
@ -142,11 +136,6 @@ merge request creation to merge request merge (and closed/un-merged merge reques
|
||||||
For more information, see [Merge Request Analytics](merge_request_analytics.md).
|
For more information, see [Merge Request Analytics](merge_request_analytics.md).
|
||||||
- **Mean Time to Recover/Repair/Resolution/Resolve/Restore (MTTR):** The average duration that a bug
|
- **Mean Time to Recover/Repair/Resolution/Resolve/Restore (MTTR):** The average duration that a bug
|
||||||
is not fixed in production. GitLab measures MTTR from deployment of bug to deployment of fix.
|
is not fixed in production. GitLab measures MTTR from deployment of bug to deployment of fix.
|
||||||
- **Throughput:** The number of issues closed or merge requests merged (not closed) in a period of
|
|
||||||
time. Often measured per sprint. GitLab displays merge request throughput in [Merge Request Analytics](merge_request_analytics.md).
|
|
||||||
- **Value Stream:** The entire work process that is followed to deliver value to customers. For example,
|
|
||||||
the [DevOps lifecycle](https://about.gitlab.com/stages-devops-lifecycle/) is a value stream that starts
|
|
||||||
with "plan" and ends with "monitor". GitLab helps you track your value stream using [Value Stream Analytics](value_stream_analytics.md).
|
|
||||||
- **Velocity:** The total issue burden completed in some period of time. The burden is usually measured
|
- **Velocity:** The total issue burden completed in some period of time. The burden is usually measured
|
||||||
in points or weight, often per sprint. For example, your velocity may be "30 points per sprint". GitLab
|
in points or weight, often per sprint. For example, your velocity may be "30 points per sprint". GitLab
|
||||||
measures velocity as the total points or weight of issues closed in a given period of time.
|
measures velocity as the total points or weight of issues closed in a given period of time.
|
||||||
|
|
|
@ -48,7 +48,8 @@ To view the number of merge requests merged per month:
|
||||||
- In the **From** field, select a start date.
|
- In the **From** field, select a start date.
|
||||||
- In the **To** field, select an end date.
|
- In the **To** field, select an end date.
|
||||||
|
|
||||||
The **Throughput** chart shows the number of merge requests merged per month.
|
The **Throughput** chart shows issues closed or merge requests merged (not closed) over a period of
|
||||||
|
time.
|
||||||
|
|
||||||
The table shows up to 20 merge requests per page, and includes
|
The table shows up to 20 merge requests per page, and includes
|
||||||
information about each merge request.
|
information about each merge request.
|
||||||
|
@ -58,9 +59,10 @@ information about each merge request.
|
||||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229389) in GitLab 13.9.
|
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229389) in GitLab 13.9.
|
||||||
|
|
||||||
Use the number in **Mean time to merge** to view the average time between when a merge request is
|
Use the number in **Mean time to merge** to view the average time between when a merge request is
|
||||||
created and when it's merged.
|
created and when it's merged. Closed and un-merged merge requests are not included.
|
||||||
|
|
||||||
To view **Mean time to merge**:
|
To view **Mean time to merge**:
|
||||||
|
|
||||||
1. On the top bar, select **Menu > Projects** and find your project.
|
1. On the top bar, select **Menu > Projects** and find your project.
|
||||||
1. On the left sidebar, select **Analytics > Merge request**.
|
1. On the left sidebar, select **Analytics > Merge request**. The **Mean time to merge** number
|
||||||
|
is shown on the dashboard.
|
||||||
|
|
|
@ -12,6 +12,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
||||||
|
|
||||||
Value stream analytics provides metrics about each stage of your software development process.
|
Value stream analytics provides metrics about each stage of your software development process.
|
||||||
|
|
||||||
|
A **value stream** is the entire work process that delivers value to customers. For example,
|
||||||
|
the [DevOps lifecycle](https://about.gitlab.com/stages-devops-lifecycle/) is a value stream that starts
|
||||||
|
with the Manage stage and ends with the Protect stage.
|
||||||
|
|
||||||
Use value stream analytics to identify:
|
Use value stream analytics to identify:
|
||||||
|
|
||||||
- The amount of time it takes to go from an idea to production.
|
- The amount of time it takes to go from an idea to production.
|
||||||
|
@ -74,7 +78,7 @@ To view the median time spent in each stage:
|
||||||
Value stream analytics shows the lead time and cycle time for issues in your project:
|
Value stream analytics shows the lead time and cycle time for issues in your project:
|
||||||
|
|
||||||
- Lead time: Median time from when the issue was created to when it was closed.
|
- Lead time: Median time from when the issue was created to when it was closed.
|
||||||
- Cycle time: Median time from first commit to issue closed. Commits are associated with issues when users [cross-link them in the commit message](../project/issues/crosslinking_issues.md#from-commit-messages).
|
- Cycle time: Median time from first commit to issue closed. GitLab measures cycle time from the earliest commit of a [linked issue's merge request](../project/issues/crosslinking_issues.md) to when that issue is closed. The cycle time approach underestimates the lead time because merge request creation is always later than commit time.
|
||||||
|
|
||||||
To view the lead time and cycle time for issues:
|
To view the lead time and cycle time for issues:
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
||||||
|
|
||||||
Value stream analytics provides metrics about each stage of your software development process.
|
Value stream analytics provides metrics about each stage of your software development process.
|
||||||
|
|
||||||
|
A **value stream** is the entire work process that delivers value to customers. For example,
|
||||||
|
the [DevOps lifecycle](https://about.gitlab.com/stages-devops-lifecycle/) is a value stream that starts
|
||||||
|
with the "manage" and ends with the "protect" stage.
|
||||||
|
|
||||||
Use value stream analytics to identify:
|
Use value stream analytics to identify:
|
||||||
|
|
||||||
- The amount of time it takes to go from an idea to production.
|
- The amount of time it takes to go from an idea to production.
|
||||||
|
@ -91,7 +95,7 @@ To view the median time spent in each stage by a group:
|
||||||
Value stream analytics shows the lead time and cycle time for issues in your groups:
|
Value stream analytics shows the lead time and cycle time for issues in your groups:
|
||||||
|
|
||||||
- Lead time: Median time from when the issue was created to when it was closed.
|
- Lead time: Median time from when the issue was created to when it was closed.
|
||||||
- Cycle time: Median time from first commit to issue closed. Commits are associated with issues when users [cross-link them in the commit message](../../project/issues/crosslinking_issues.md#from-commit-messages).
|
- Cycle time: Median time from first commit to issue closed. GitLab measures cycle time from the earliest commit of a [linked issue's merge request](../../project/issues/crosslinking_issues.md#from-commit-messages) to when that issue is closed. The cycle time approach underestimates the lead time because merge request creation is always later than commit time.
|
||||||
|
|
||||||
To view the lead time and cycle time for issues:
|
To view the lead time and cycle time for issues:
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ pre-push:
|
||||||
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
|
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
|
||||||
glob: '{app/graphql/**/*.rb,ee/app/graphql/**/*.rb}'
|
glob: '{app/graphql/**/*.rb,ee/app/graphql/**/*.rb}'
|
||||||
run: bundle exec rake gitlab:graphql:check_docs
|
run: bundle exec rake gitlab:graphql:check_docs
|
||||||
vale: # Requires Vale: https://docs.gitlab.com/ee/development/documentation/#install-linters
|
vale: # Requires Vale: https://docs.gitlab.com/ee/development/documentation/testing.html#install-linters
|
||||||
tags: documentation style
|
tags: documentation style
|
||||||
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
|
files: git diff --name-only --diff-filter=d $(git merge-base origin/master HEAD)..HEAD
|
||||||
glob: 'doc/*.md'
|
glob: 'doc/*.md'
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Gitlab
|
|
||||||
module UsageCounters
|
|
||||||
class Common
|
|
||||||
class << self
|
|
||||||
def increment(project_id)
|
|
||||||
Gitlab::Redis::SharedState.with { |redis| redis.hincrby(base_key, project_id, 1) }
|
|
||||||
end
|
|
||||||
|
|
||||||
def usage_totals
|
|
||||||
Gitlab::Redis::SharedState.with do |redis|
|
|
||||||
total_sum = 0
|
|
||||||
|
|
||||||
totals = redis.hgetall(base_key).each_with_object({}) do |(project_id, count), result|
|
|
||||||
total_sum += result[project_id.to_i] = count.to_i
|
|
||||||
end
|
|
||||||
|
|
||||||
totals[:total] = total_sum
|
|
||||||
totals
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def base_key
|
|
||||||
raise NotImplementedError
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,11 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Gitlab
|
|
||||||
module UsageCounters
|
|
||||||
class PodLogs < Common
|
|
||||||
def self.base_key
|
|
||||||
'POD_LOGS_USAGE_COUNTS'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -9,7 +9,7 @@
|
||||||
# active_user_count: count(User.active)
|
# active_user_count: count(User.active)
|
||||||
# alt_usage_data { Gitlab::VERSION }
|
# alt_usage_data { Gitlab::VERSION }
|
||||||
# redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter)
|
# redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter)
|
||||||
# redis_usage_data { ::Gitlab::UsageCounters::PodLogs.usage_totals[:total] }
|
# redis_usage_data { Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'users_expanding_vulnerabilities', start_date: 28.days.ago, end_date: Date.current) }
|
||||||
|
|
||||||
# NOTE:
|
# NOTE:
|
||||||
# Implementing metrics direct in `usage_data.rb` is deprecated,
|
# Implementing metrics direct in `usage_data.rb` is deprecated,
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
#
|
#
|
||||||
# Examples:
|
# Examples:
|
||||||
# redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter)
|
# redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter)
|
||||||
# redis_usage_data { ::Gitlab::UsageCounters::PodLogs.usage_totals[:total] }
|
# redis_usage_data { Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'users_expanding_vulnerabilities', start_date: 28.days.ago, end_date: Date.current) }
|
||||||
|
|
||||||
module Gitlab
|
module Gitlab
|
||||||
module Utils
|
module Utils
|
||||||
|
|
|
@ -33764,6 +33764,9 @@ msgstr ""
|
||||||
msgid "SecurityPolicies|Policy type"
|
msgid "SecurityPolicies|Policy type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "SecurityReports|%{count} Selected"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "SecurityReports|%{count}+ projects"
|
msgid "SecurityReports|%{count}+ projects"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -103,14 +103,6 @@ RSpec.describe Projects::LogsController do
|
||||||
expect(json_response).to eq(service_result_json)
|
expect(json_response).to eq(service_result_json)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'registers a usage of the endpoint' do
|
|
||||||
expect(::Gitlab::UsageCounters::PodLogs).to receive(:increment).with(project.id)
|
|
||||||
|
|
||||||
get endpoint, params: environment_params(pod_name: pod_name, format: :json)
|
|
||||||
|
|
||||||
expect(response).to have_gitlab_http_status(:success)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'sets the polling header' do
|
it 'sets the polling header' do
|
||||||
get endpoint, params: environment_params(pod_name: pod_name, format: :json)
|
get endpoint, params: environment_params(pod_name: pod_name, format: :json)
|
||||||
|
|
||||||
|
|
|
@ -329,7 +329,7 @@ describe('StageTable', () => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('with sortDesc=false will toggle the direction field', async () => {
|
it('with sortDesc=false will toggle the direction field', () => {
|
||||||
expect(wrapper.emitted('handleUpdatePagination')).toBeUndefined();
|
expect(wrapper.emitted('handleUpdatePagination')).toBeUndefined();
|
||||||
triggerTableSort(false);
|
triggerTableSort(false);
|
||||||
|
|
||||||
|
|
|
@ -115,10 +115,10 @@ describe('ValueStreamFilters', () => {
|
||||||
expect(findAggregationToggle().props('value')).toBe(true);
|
expect(findAggregationToggle().props('value')).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('will emit `toggleAggregation` when the toggle is changed', async () => {
|
it('will emit `toggleAggregation` when the toggle is changed', () => {
|
||||||
expect(wrapper.emitted('toggleAggregation')).toBeUndefined();
|
expect(wrapper.emitted('toggleAggregation')).toBeUndefined();
|
||||||
|
|
||||||
await findAggregationToggle().vm.$emit('change', true);
|
findAggregationToggle().vm.$emit('change', true);
|
||||||
|
|
||||||
expect(wrapper.emitted('toggleAggregation')).toHaveLength(1);
|
expect(wrapper.emitted('toggleAggregation')).toHaveLength(1);
|
||||||
expect(wrapper.emitted('toggleAggregation')).toEqual([[true]]);
|
expect(wrapper.emitted('toggleAggregation')).toEqual([[true]]);
|
||||||
|
@ -134,10 +134,10 @@ describe('ValueStreamFilters', () => {
|
||||||
expect(findAggregationToggle().props('disabled')).toBe(true);
|
expect(findAggregationToggle().props('disabled')).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('will not emit `toggleAggregation` when the toggle is changed', async () => {
|
it('will not emit `toggleAggregation` when the toggle is changed', () => {
|
||||||
expect(wrapper.emitted('toggleAggregation')).toBeUndefined();
|
expect(wrapper.emitted('toggleAggregation')).toBeUndefined();
|
||||||
|
|
||||||
await findAggregationToggle().vm.$emit('change', true);
|
findAggregationToggle().vm.$emit('change', true);
|
||||||
|
|
||||||
expect(wrapper.emitted('toggleAggregation')).toBeUndefined();
|
expect(wrapper.emitted('toggleAggregation')).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
|
@ -149,6 +149,38 @@ describe('diff_file utilities', () => {
|
||||||
|
|
||||||
expect(preppedFile).not.toHaveProp('id');
|
expect(preppedFile).not.toHaveProp('id');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it.each`
|
||||||
|
index
|
||||||
|
${null}
|
||||||
|
${undefined}
|
||||||
|
${-1}
|
||||||
|
${false}
|
||||||
|
${true}
|
||||||
|
${'idx'}
|
||||||
|
${'42'}
|
||||||
|
`('does not set the order property if an invalid index ($index) is provided', ({ index }) => {
|
||||||
|
const preppedFile = prepareRawDiffFile({
|
||||||
|
file: files[0],
|
||||||
|
allFiles: files,
|
||||||
|
index,
|
||||||
|
});
|
||||||
|
|
||||||
|
/* expect.anything() doesn't match null or undefined */
|
||||||
|
expect(preppedFile).toEqual(expect.not.objectContaining({ order: null }));
|
||||||
|
expect(preppedFile).toEqual(expect.not.objectContaining({ order: undefined }));
|
||||||
|
expect(preppedFile).toEqual(expect.not.objectContaining({ order: expect.anything() }));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sets the provided valid index to the order property', () => {
|
||||||
|
const preppedFile = prepareRawDiffFile({
|
||||||
|
file: files[0],
|
||||||
|
allFiles: files,
|
||||||
|
index: 42,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(preppedFile).toEqual(expect.objectContaining({ order: 42 }));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getShortShaFromFile', () => {
|
describe('getShortShaFromFile', () => {
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import { insertMarkdownText, keypressNoteText } from '~/lib/utils/text_markdown';
|
import {
|
||||||
|
insertMarkdownText,
|
||||||
|
keypressNoteText,
|
||||||
|
compositionStartNoteText,
|
||||||
|
compositionEndNoteText,
|
||||||
|
} from '~/lib/utils/text_markdown';
|
||||||
import '~/lib/utils/jquery_at_who';
|
import '~/lib/utils/jquery_at_who';
|
||||||
|
|
||||||
describe('init markdown', () => {
|
describe('init markdown', () => {
|
||||||
|
@ -173,6 +178,10 @@ describe('init markdown', () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
gon.features = { markdownContinueLists: true };
|
gon.features = { markdownContinueLists: true };
|
||||||
|
|
||||||
|
textArea.addEventListener('keydown', keypressNoteText);
|
||||||
|
textArea.addEventListener('compositionstart', compositionStartNoteText);
|
||||||
|
textArea.addEventListener('compositionend', compositionEndNoteText);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each`
|
it.each`
|
||||||
|
@ -203,7 +212,6 @@ describe('init markdown', () => {
|
||||||
textArea.value = text;
|
textArea.value = text;
|
||||||
textArea.setSelectionRange(text.length, text.length);
|
textArea.setSelectionRange(text.length, text.length);
|
||||||
|
|
||||||
textArea.addEventListener('keydown', keypressNoteText);
|
|
||||||
textArea.dispatchEvent(enterEvent);
|
textArea.dispatchEvent(enterEvent);
|
||||||
|
|
||||||
expect(textArea.value).toEqual(expected);
|
expect(textArea.value).toEqual(expected);
|
||||||
|
@ -231,7 +239,6 @@ describe('init markdown', () => {
|
||||||
textArea.value = text;
|
textArea.value = text;
|
||||||
textArea.setSelectionRange(text.length, text.length);
|
textArea.setSelectionRange(text.length, text.length);
|
||||||
|
|
||||||
textArea.addEventListener('keydown', keypressNoteText);
|
|
||||||
textArea.dispatchEvent(enterEvent);
|
textArea.dispatchEvent(enterEvent);
|
||||||
|
|
||||||
expect(textArea.value.substr(0, textArea.selectionStart)).toEqual(expected);
|
expect(textArea.value.substr(0, textArea.selectionStart)).toEqual(expected);
|
||||||
|
@ -251,7 +258,6 @@ describe('init markdown', () => {
|
||||||
textArea.value = text;
|
textArea.value = text;
|
||||||
textArea.setSelectionRange(text.length, text.length);
|
textArea.setSelectionRange(text.length, text.length);
|
||||||
|
|
||||||
textArea.addEventListener('keydown', keypressNoteText);
|
|
||||||
textArea.dispatchEvent(enterEvent);
|
textArea.dispatchEvent(enterEvent);
|
||||||
|
|
||||||
expect(textArea.value).toEqual(expected);
|
expect(textArea.value).toEqual(expected);
|
||||||
|
@ -267,7 +273,6 @@ describe('init markdown', () => {
|
||||||
textArea.value = text;
|
textArea.value = text;
|
||||||
textArea.setSelectionRange(add_at, add_at);
|
textArea.setSelectionRange(add_at, add_at);
|
||||||
|
|
||||||
textArea.addEventListener('keydown', keypressNoteText);
|
|
||||||
textArea.dispatchEvent(enterEvent);
|
textArea.dispatchEvent(enterEvent);
|
||||||
|
|
||||||
expect(textArea.value).toEqual(expected);
|
expect(textArea.value).toEqual(expected);
|
||||||
|
@ -283,7 +288,25 @@ describe('init markdown', () => {
|
||||||
textArea.value = text;
|
textArea.value = text;
|
||||||
textArea.setSelectionRange(text.length, text.length);
|
textArea.setSelectionRange(text.length, text.length);
|
||||||
|
|
||||||
textArea.addEventListener('keydown', keypressNoteText);
|
textArea.dispatchEvent(enterEvent);
|
||||||
|
|
||||||
|
expect(textArea.value).toEqual(expected);
|
||||||
|
expect(textArea.selectionStart).toBe(expected.length);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('does not duplicate a line item for IME characters', () => {
|
||||||
|
const text = '- 日本語';
|
||||||
|
const expected = '- 日本語\n- ';
|
||||||
|
|
||||||
|
textArea.dispatchEvent(new CompositionEvent('compositionstart'));
|
||||||
|
textArea.value = text;
|
||||||
|
|
||||||
|
// Press enter to end composition
|
||||||
|
textArea.dispatchEvent(enterEvent);
|
||||||
|
textArea.dispatchEvent(new CompositionEvent('compositionend'));
|
||||||
|
textArea.setSelectionRange(text.length, text.length);
|
||||||
|
|
||||||
|
// Press enter to make new line
|
||||||
textArea.dispatchEvent(enterEvent);
|
textArea.dispatchEvent(enterEvent);
|
||||||
|
|
||||||
expect(textArea.value).toEqual(expected);
|
expect(textArea.value).toEqual(expected);
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { GlModal } from '@gitlab/ui';
|
||||||
import { mount } from '@vue/test-utils';
|
import { mount } from '@vue/test-utils';
|
||||||
import * as timeago from 'timeago.js';
|
import * as timeago from 'timeago.js';
|
||||||
import { nextTick } from 'vue';
|
import { nextTick } from 'vue';
|
||||||
|
import { timeagoLanguageCode } from '~/lib/utils/datetime/timeago_utility';
|
||||||
import UserListsTable from '~/user_lists/components/user_lists_table.vue';
|
import UserListsTable from '~/user_lists/components/user_lists_table.vue';
|
||||||
import { userList } from 'jest/feature_flags/mock_data';
|
import { userList } from 'jest/feature_flags/mock_data';
|
||||||
|
|
||||||
|
@ -31,7 +32,7 @@ describe('User Lists Table', () => {
|
||||||
userList.user_xids.replace(/,/g, ', '),
|
userList.user_xids.replace(/,/g, ', '),
|
||||||
);
|
);
|
||||||
expect(wrapper.find('[data-testid="ffUserListTimestamp"]').text()).toBe('created 2 weeks ago');
|
expect(wrapper.find('[data-testid="ffUserListTimestamp"]').text()).toBe('created 2 weeks ago');
|
||||||
expect(timeago.format).toHaveBeenCalledWith(userList.created_at);
|
expect(timeago.format).toHaveBeenCalledWith(userList.created_at, timeagoLanguageCode);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set the title for a tooltip on the created stamp', () => {
|
it('should set the title for a tooltip on the created stamp', () => {
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
require 'spec_helper'
|
|
||||||
|
|
||||||
RSpec.describe Gitlab::UsageCounters::PodLogs, :clean_gitlab_redis_shared_state do
|
|
||||||
it_behaves_like 'a usage counter'
|
|
||||||
end
|
|
|
@ -457,7 +457,23 @@ RSpec.describe Clusters::Platforms::Kubernetes do
|
||||||
stub_kubeclient_ingresses(namespace, status: 500)
|
stub_kubeclient_ingresses(namespace, status: 500)
|
||||||
end
|
end
|
||||||
|
|
||||||
it { expect { subject }.to raise_error(Kubeclient::HttpError) }
|
it 'does not raise error' do
|
||||||
|
expect { subject }.not_to raise_error(Kubeclient::HttpError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'logs the error' do
|
||||||
|
expect_next_instance_of(Gitlab::Kubernetes::Logger) do |logger|
|
||||||
|
expect(logger).to receive(:error)
|
||||||
|
.with(hash_including(event: :kube_connection_error))
|
||||||
|
.and_call_original
|
||||||
|
end
|
||||||
|
|
||||||
|
subject
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns empty array for the k8s component keys' do
|
||||||
|
expect(subject).to include({ pods: [], deployments: [], ingresses: [] })
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when kubernetes responds with 404s' do
|
context 'when kubernetes responds with 404s' do
|
||||||
|
@ -755,6 +771,18 @@ RSpec.describe Clusters::Platforms::Kubernetes do
|
||||||
expect(rollout_status.instances.map { |p| p[:pod_name] }).to eq(['pod-a-1', 'pod-a-2', 'pod-b-1', 'pod-b-2'])
|
expect(rollout_status.instances.map { |p| p[:pod_name] }).to eq(['pod-a-1', 'pod-a-2', 'pod-b-1', 'pod-b-2'])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Scenario when there are K8s connection errors.
|
||||||
|
context 'when cache keys are defaulted' do
|
||||||
|
let(:cache_data) { Hash(deployments: [], pods: [], ingresses: []) }
|
||||||
|
|
||||||
|
it 'does not raise error' do
|
||||||
|
expect { rollout_status }.not_to raise_error
|
||||||
|
|
||||||
|
expect(rollout_status).to be_kind_of(::Gitlab::Kubernetes::RolloutStatus)
|
||||||
|
expect(rollout_status).to be_not_found
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#ingresses' do
|
describe '#ingresses' do
|
||||||
|
|
Loading…
Reference in New Issue