Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
526346a4d3
commit
9ff3c1ace6
|
|
@ -18,6 +18,10 @@ stages:
|
|||
- GIT_DEPTH
|
||||
- GIT_STRATEGY
|
||||
|
||||
workflow:
|
||||
auto_cancel:
|
||||
on_new_commit: none
|
||||
|
||||
variables:
|
||||
GIT_DEPTH: 20
|
||||
GIT_STRATEGY: fetch
|
||||
|
|
@ -46,6 +50,15 @@ release-environments-deploy-env:
|
|||
expire_in: 7 days
|
||||
when: always
|
||||
|
||||
release-environments-update-resource-group:
|
||||
stage: prepare
|
||||
script:
|
||||
# Make sure pipelines run in order
|
||||
# See https://docs.gitlab.com/ee/ci/resource_groups/index.html#change-the-process-mode
|
||||
- |
|
||||
curl --request PUT --data "process_mode=oldest_first" --header "PRIVATE-TOKEN:${ENVIRONMENT_API_TOKEN}" \
|
||||
"${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/resource_groups/release-environment-${CI_COMMIT_REF_SLUG}"
|
||||
|
||||
release-environments-notification-start:
|
||||
stage: start
|
||||
extends: .inherit_variables
|
||||
|
|
@ -67,6 +80,7 @@ release-environments-deploy:
|
|||
branch: main
|
||||
strategy: depend
|
||||
needs: ["release-environments-deploy-env"]
|
||||
resource_group: release-environment-${CI_COMMIT_REF_SLUG}
|
||||
|
||||
release-environments-qa:
|
||||
stage: qa
|
||||
|
|
@ -80,6 +94,7 @@ release-environments-qa:
|
|||
GITLAB_INITIAL_ROOT_PASSWORD: "${RELEASE_ENVIRONMENTS_ROOT_PASSWORD}"
|
||||
QA_PRAEFECT_REPOSITORY_STORAGE: "default"
|
||||
SIGNUP_DISABLED: "true"
|
||||
resource_group: release-environment-${CI_COMMIT_REF_SLUG}
|
||||
|
||||
release-environments-notification-failure:
|
||||
stage: finish
|
||||
|
|
|
|||
|
|
@ -51,18 +51,6 @@ Layout/ArgumentAlignment:
|
|||
- 'ee/app/graphql/mutations/security_policy/assign_security_policy_project.rb'
|
||||
- 'ee/app/graphql/mutations/security_policy/commit_scan_execution_policy.rb'
|
||||
- 'ee/app/graphql/mutations/security_policy/create_security_policy_project.rb'
|
||||
- 'ee/app/graphql/types/dast/profile_branch_type.rb'
|
||||
- 'ee/app/graphql/types/dast/profile_cadence_input_type.rb'
|
||||
- 'ee/app/graphql/types/dast/profile_cadence_type.rb'
|
||||
- 'ee/app/graphql/types/dast/profile_schedule_input_type.rb'
|
||||
- 'ee/app/graphql/types/dast/profile_type.rb'
|
||||
- 'ee/app/graphql/types/dast/site_profile_auth_input_type.rb'
|
||||
- 'ee/app/graphql/types/dast/site_profile_auth_type.rb'
|
||||
- 'ee/app/graphql/types/dast_scanner_profile_type.rb'
|
||||
- 'ee/app/graphql/types/dast_site_profile_type.rb'
|
||||
- 'ee/app/graphql/types/dast_site_validation_type.rb'
|
||||
- 'ee/app/graphql/types/deployments/approval_status_enum.rb'
|
||||
- 'ee/app/graphql/types/deployments/approval_summary_status_enum.rb'
|
||||
- 'ee/app/graphql/types/deployments/approval_summary_type.rb'
|
||||
- 'ee/app/graphql/types/deployments/approval_type.rb'
|
||||
- 'ee/app/graphql/types/epic_descendant_weight_sum_type.rb'
|
||||
|
|
|
|||
|
|
@ -115,7 +115,6 @@ Lint/SymbolConversion:
|
|||
- 'lib/gitlab/metrics/transaction.rb'
|
||||
- 'lib/gitlab/usage_data/topology.rb'
|
||||
- 'lib/gitlab/usage_data_counters/base_counter.rb'
|
||||
- 'lib/gitlab/usage_data_counters/note_counter.rb'
|
||||
- 'lib/peek/views/detailed_view.rb'
|
||||
- 'qa/qa/ee/page/workspace/action.rb'
|
||||
- 'qa/qa/ee/page/workspace/list.rb'
|
||||
|
|
|
|||
|
|
@ -3963,9 +3963,7 @@ RSpec/FeatureCategory:
|
|||
- 'spec/lib/gitlab/usage_data_counters/jetbrains_plugin_activity_unique_counter_spec.rb'
|
||||
- 'spec/lib/gitlab/usage_data_counters/kubernetes_agent_counter_spec.rb'
|
||||
- 'spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb'
|
||||
- 'spec/lib/gitlab/usage_data_counters/merge_request_counter_spec.rb'
|
||||
- 'spec/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter_spec.rb'
|
||||
- 'spec/lib/gitlab/usage_data_counters/note_counter_spec.rb'
|
||||
- 'spec/lib/gitlab/usage_data_counters/package_event_counter_spec.rb'
|
||||
- 'spec/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter_spec.rb'
|
||||
- 'spec/lib/gitlab/usage_data_counters/redis_counter_spec.rb'
|
||||
|
|
|
|||
|
|
@ -505,7 +505,6 @@ Style/ClassAndModuleChildren:
|
|||
- 'lib/gitlab/instrumentation/elasticsearch_transport.rb'
|
||||
- 'lib/gitlab/usage_data_counters/base_counter.rb'
|
||||
- 'lib/gitlab/usage_data_counters/ci_template_unique_counter.rb'
|
||||
- 'lib/gitlab/usage_data_counters/note_counter.rb'
|
||||
- 'lib/release_highlights/validator/entry.rb'
|
||||
- 'qa/qa/page/component/project/templates.rb'
|
||||
- 'scripts/perf/gc/print_gc_stats.rb'
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ export const initJobDetails = () => {
|
|||
testReportSummaryUrl,
|
||||
pipelineTestReportUrl,
|
||||
logViewerPath,
|
||||
duoFeaturesEnabled,
|
||||
} = el.dataset;
|
||||
|
||||
const fullScreenAPIAvailable = document.fullscreenEnabled;
|
||||
|
|
@ -55,6 +56,7 @@ export const initJobDetails = () => {
|
|||
projectPath,
|
||||
retryOutdatedJobDocsUrl,
|
||||
aiRootCauseAnalysisAvailable: parseBoolean(aiRootCauseAnalysisAvailable),
|
||||
duoFeaturesEnabled: parseBoolean(duoFeaturesEnabled),
|
||||
pipelineTestReportUrl,
|
||||
},
|
||||
render(h) {
|
||||
|
|
|
|||
|
|
@ -207,6 +207,14 @@ export default {
|
|||
showDropdownTooltip() {
|
||||
return !this.isDesktopDropdownVisible ? this.dropdownText : '';
|
||||
},
|
||||
promoteToEpicItem() {
|
||||
return {
|
||||
text: __('Promote to epic'),
|
||||
extraAttrs: {
|
||||
disabled: this.isToggleStateButtonLoading,
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
created() {
|
||||
eventHub.$on('toggle.issuable.state', this.toggleIssueState);
|
||||
|
|
@ -361,9 +369,11 @@ export default {
|
|||
<template #list-item>{{ buttonText }}</template>
|
||||
</gl-disclosure-dropdown-item>
|
||||
<gl-disclosure-dropdown-item v-if="canCreateIssue" :item="newIssueItem" />
|
||||
<gl-disclosure-dropdown-item v-if="canPromoteToEpic" @action="promoteToEpic">
|
||||
<template #list-item>{{ __('Promote to epic') }}</template>
|
||||
</gl-disclosure-dropdown-item>
|
||||
<gl-disclosure-dropdown-item
|
||||
v-if="canPromoteToEpic"
|
||||
:item="promoteToEpicItem"
|
||||
@action="promoteToEpic"
|
||||
/>
|
||||
<template v-if="showLockIssueOption">
|
||||
<issuable-lock-form :is-editable="false" data-testid="lock-issue-toggle" />
|
||||
</template>
|
||||
|
|
@ -461,12 +471,10 @@ export default {
|
|||
<gl-disclosure-dropdown-item v-if="canCreateIssue && isUserSignedIn" :item="newIssueItem" />
|
||||
<gl-disclosure-dropdown-item
|
||||
v-if="canPromoteToEpic"
|
||||
:disabled="isToggleStateButtonLoading"
|
||||
:item="promoteToEpicItem"
|
||||
data-testid="promote-button"
|
||||
@action="promoteToEpic"
|
||||
>
|
||||
<template #list-item>{{ __('Promote to epic') }}</template>
|
||||
</gl-disclosure-dropdown-item>
|
||||
/>
|
||||
<template v-if="showLockIssueOption">
|
||||
<issuable-lock-form :is-editable="false" data-testid="lock-issue-toggle" />
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
.popup {
|
||||
@include triangle(
|
||||
$gray-lighter,
|
||||
$gray-10,
|
||||
$gray-50,
|
||||
$popup-triangle-size,
|
||||
$popup-triangle-border-size
|
||||
);
|
||||
|
||||
padding: $gl-padding;
|
||||
background-color: $gray-lighter;
|
||||
background-color: $gray-10;
|
||||
border: 1px solid $gray-50;
|
||||
border-radius: $gl-border-radius-base;
|
||||
box-shadow: 0 5px 8px $popup-box-shadow-color;
|
||||
|
|
|
|||
|
|
@ -87,7 +87,6 @@ $purple: #6d49cb !default;
|
|||
$purple-light: #ede8fb !default;
|
||||
|
||||
$gray-light: $gray-10 !default;
|
||||
$gray-lighter: lighten($gray-50, 4) !default;
|
||||
|
||||
/*
|
||||
* UI elements
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
.issue-token-reference {
|
||||
margin-right: 1px;
|
||||
background-color: $gray-lighter;
|
||||
background-color: $gray-10;
|
||||
transition: background $general-hover-transition-duration $general-hover-transition-curve, color $general-hover-transition-duration $general-hover-transition-curve;
|
||||
|
||||
.issue-token:hover &,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
@import '@gitlab/ui/src/tokens/build/scss/tokens.dark';
|
||||
|
||||
$gray-light: lighten($gray-10, 2);
|
||||
$gray-lighter: darken($gray-50, 4);
|
||||
|
||||
$black-normal: $gray-900;
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,11 @@ module MergeRequests
|
|||
todo_service.new_merge_request(merge_request, current_user)
|
||||
merge_request.cache_merge_request_closes_issues!(current_user)
|
||||
|
||||
Gitlab::UsageDataCounters::MergeRequestCounter.count(:create)
|
||||
Gitlab::InternalEvents.track_event(
|
||||
'create_merge_request',
|
||||
user: current_user,
|
||||
project: merge_request.target_project
|
||||
)
|
||||
link_lfs_objects(merge_request)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -13,12 +13,13 @@ module Notes
|
|||
end
|
||||
|
||||
def increment_usage_counter(note)
|
||||
if note.noteable_type == 'Commit'
|
||||
case note.noteable_type
|
||||
when 'Commit'
|
||||
track_internal_event('create_commit_note', project: project, user: current_user)
|
||||
elsif note.noteable_type == 'Snippet'
|
||||
when 'Snippet'
|
||||
track_internal_event('create_snippet_note', project: project, user: current_user)
|
||||
else
|
||||
Gitlab::UsageDataCounters::NoteCounter.count(:create, note.noteable_type)
|
||||
when 'MergeRequest'
|
||||
track_internal_event('create_merge_request_note', project: project, user: current_user)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
description: Tracks creation of merge requests
|
||||
internal_events: true
|
||||
action: create_merge_request
|
||||
identifiers:
|
||||
- project
|
||||
- user
|
||||
- namespace
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
milestone: '17.1'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/151474
|
||||
distributions:
|
||||
- ce
|
||||
- ee
|
||||
tiers:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
description: A note was created for a merge request
|
||||
internal_events: true
|
||||
action: create_merge_request_note
|
||||
identifiers:
|
||||
- project
|
||||
- user
|
||||
- namespace
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
milestone: '17.1'
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/151474
|
||||
distributions:
|
||||
- ce
|
||||
- ee
|
||||
tiers:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -8,11 +8,9 @@ product_group: code_review
|
|||
value_type: number
|
||||
status: active
|
||||
time_frame: all
|
||||
data_source: redis
|
||||
instrumentation_class: RedisMetric
|
||||
options:
|
||||
prefix: note
|
||||
event: create_mergerequest
|
||||
data_source: internal_events
|
||||
events:
|
||||
- name: create_merge_request_note
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
|
|
|
|||
|
|
@ -8,11 +8,9 @@ product_group: code_review
|
|||
value_type: number
|
||||
status: active
|
||||
time_frame: all
|
||||
data_source: redis
|
||||
instrumentation_class: RedisMetric
|
||||
options:
|
||||
prefix: merge_request
|
||||
event: create
|
||||
data_source: internal_events
|
||||
events:
|
||||
- name: create_merge_request
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
|
|
|
|||
|
|
@ -7,5 +7,15 @@ feature_categories:
|
|||
description: Historical timeline events belonging to a cluster agent
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74577
|
||||
milestone: '14.6'
|
||||
gitlab_schema: gitlab_main
|
||||
sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/461521
|
||||
gitlab_schema: gitlab_main_cell
|
||||
allow_cross_foreign_keys:
|
||||
- gitlab_main_clusterwide
|
||||
desired_sharding_key:
|
||||
agent_project_id:
|
||||
references: projects
|
||||
backfill_via:
|
||||
parent:
|
||||
foreign_key: agent_id
|
||||
table: cluster_agents
|
||||
sharding_key: project_id
|
||||
belongs_to: agent
|
||||
|
|
|
|||
|
|
@ -18979,10 +18979,10 @@ Represents a product analytics dashboard.
|
|||
| <a id="customizabledashboardconfigurationproject"></a>`configurationProject` | [`Project`](#project) | Project which contains the dashboard definition. |
|
||||
| <a id="customizabledashboarddescription"></a>`description` | [`String`](#string) | Description of the dashboard. |
|
||||
| <a id="customizabledashboarderrors"></a>`errors` | [`[String!]`](#string) | Errors on yaml definition. |
|
||||
| <a id="customizabledashboardpanels"></a>`panels` | [`CustomizableDashboardPanelConnection!`](#customizabledashboardpanelconnection) | Panels shown on the dashboard. (see [Connections](#connections)) |
|
||||
| <a id="customizabledashboardpanels"></a>`panels` | [`CustomizableDashboardPanelConnection`](#customizabledashboardpanelconnection) | Panels shown on the dashboard. (see [Connections](#connections)) |
|
||||
| <a id="customizabledashboardslug"></a>`slug` | [`String!`](#string) | Slug of the dashboard. |
|
||||
| <a id="customizabledashboardstatus"></a>`status` **{warning-solid}** | [`String`](#string) | **Introduced** in GitLab 17.0. **Status**: Experiment. Status of the dashboard. |
|
||||
| <a id="customizabledashboardtitle"></a>`title` | [`String!`](#string) | Title of the dashboard. |
|
||||
| <a id="customizabledashboardtitle"></a>`title` | [`String`](#string) | Title of the dashboard. |
|
||||
| <a id="customizabledashboarduserdefined"></a>`userDefined` | [`Boolean!`](#boolean) | Indicates whether the dashboard is user-defined or provided by GitLab. |
|
||||
|
||||
### `CustomizableDashboardPanel`
|
||||
|
|
@ -18995,8 +18995,8 @@ Represents a product analytics dashboard panel.
|
|||
| ---- | ---- | ----------- |
|
||||
| <a id="customizabledashboardpanelgridattributes"></a>`gridAttributes` | [`JSON`](#json) | Description of the position and size of the panel. |
|
||||
| <a id="customizabledashboardpanelqueryoverrides"></a>`queryOverrides` | [`JSON`](#json) | Overrides for the visualization query object. |
|
||||
| <a id="customizabledashboardpaneltitle"></a>`title` | [`String!`](#string) | Title of the panel. |
|
||||
| <a id="customizabledashboardpanelvisualization"></a>`visualization` | [`CustomizableDashboardVisualization!`](#customizabledashboardvisualization) | Visualization of the panel. |
|
||||
| <a id="customizabledashboardpaneltitle"></a>`title` | [`String`](#string) | Title of the panel. |
|
||||
| <a id="customizabledashboardpanelvisualization"></a>`visualization` | [`CustomizableDashboardVisualization`](#customizabledashboardvisualization) | Visualization of the panel. |
|
||||
|
||||
### `CustomizableDashboardVisualization`
|
||||
|
||||
|
|
|
|||
|
|
@ -43,9 +43,18 @@ DETAILS:
|
|||
|
||||
- Processes and generates text and code in a conversational manner.
|
||||
Helps you quickly identify useful information in large volumes of text in issues, epics, code, and GitLab documentation.
|
||||
- LLM: Anthropic [`claude-3-sonnet-20240229`](https://docs.anthropic.com/en/docs/models-overview#claude-3-a-new-generation-of-ai) and Vertex AI Codey [`textembedding-gecko`](https://cloud.google.com/vertex-ai/generative-ai/docs/embeddings/get-text-embeddings)
|
||||
- LLM: Anthropic [`claude-3-sonnet-20240229`](https://docs.anthropic.com/en/docs/models-overview#claude-3-a-new-generation-of-ai),
|
||||
Anthropic [`claude-3-haiku-20240307`](https://docs.anthropic.com/en/docs/models-overview#claude-3-a-new-generation-of-ai),
|
||||
[`claude-2.1`](https://docs.anthropic.com/en/docs/legacy-model-guide#anthropics-legacy-models),
|
||||
and [Vertex AI Search](https://cloud.google.com/enterprise-search).
|
||||
- [View documentation](gitlab_duo_chat.md).
|
||||
|
||||
NOTE:
|
||||
The LLM for GitLab Duo Chat depends on the question asked. For more information, see
|
||||
the [Duo Chat examples](gitlab_duo_chat_examples.md).
|
||||
For self-managed, the models also depend on your GitLab version.
|
||||
For the most benefit, use the latest GitLab version whenever possible.
|
||||
|
||||
### Suggested Reviewers
|
||||
|
||||
DETAILS:
|
||||
|
|
|
|||
|
|
@ -313,6 +313,10 @@ If the error persists:
|
|||
- Check that your configurations match the [dashboard JSON schema](#define-a-dashboard) defined in `ee/app/validators/json_schemas/analytics_dashboard.json`.
|
||||
- For product analytics, make sure your [admin and project settings](../product_analytics/index.md#project-level-settings) are set up correctly.
|
||||
|
||||
### `Invalid dashboard configuration`
|
||||
|
||||
If the dashboard displays a global error message that the configuration is invalid, check that your configurations match the [dashboard JSON schema](#define-a-dashboard) defined in `ee/app/validators/json_schemas/analytics_dashboard.json`.
|
||||
|
||||
### `Invalid visualization configuration`
|
||||
|
||||
If a dashboard panel displays a message that the visualization configuration is invalid,
|
||||
|
|
|
|||
|
|
@ -276,10 +276,13 @@ After you have set up the project, set up the configuration file:
|
|||
| `height` (subfield of `gridAttributes`) | Height of the panel |
|
||||
|
||||
```yaml
|
||||
# title - Change the title of the Value Streams Dashboard. [optional]
|
||||
# version - The latest version of the analytics dashboard schema
|
||||
version: '2'
|
||||
|
||||
# title - Change the title of the Value Streams Dashboard.
|
||||
title: 'Custom Dashboard title'
|
||||
|
||||
# description - Change the description of the Value Streams Dashboard. [optional]
|
||||
# description - Change the description of the Value Streams Dashboard.
|
||||
description: 'Custom description'
|
||||
|
||||
# panels - List of panels that contain panel settings.
|
||||
|
|
|
|||
|
|
@ -75,11 +75,10 @@ For each finding you can:
|
|||
- Create an issue for the finding.
|
||||
- Dismiss the finding.
|
||||
|
||||
When you merge the merge request's branch into the target branch, all reported findings are
|
||||
in the [vulnerability report](index.md). Scan results in pipelines executed on the
|
||||
When you merge the merge request's branch into the target branch, all reported findings from the next pipeline to run on the default branch are shown in the [vulnerability report](index.md). Scan results in pipelines executed on the
|
||||
default branch are incorporated after the pipeline finishes, according to the following table:
|
||||
|
||||
| Existing vulnerability status | Dismissed in pipeline? | New vulnerability status |
|
||||
| Existing vulnerability status | Dismissed from pipeline security tab? | New vulnerability status |
|
||||
|:------------------------------|:-----------------------|:-------------------------|
|
||||
| any | Yes | Dismissed |
|
||||
| Dismissed | any | Dismissed |
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ DETAILS:
|
|||
**Tier:** Freely available for Premium and Ultimate for a limited time. In the future, will require Premium or Ultimate with [GitLab Duo Pro or Duo Enterprise](../subscriptions/subscription-add-ons.md).
|
||||
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
|
||||
**Editors:** GitLab UI, Web IDE, VS Code, and JetBrains IDEs
|
||||
**LLMs:** Anthopic: [`claude-3-sonnet-20240229`](https://docs.anthropic.com/en/docs/models-overview#claude-3-a-new-generation-of-ai), Vertex AI Codey [`textembedding-gecko`](https://cloud.google.com/vertex-ai/generative-ai/docs/embeddings/get-text-embeddings)
|
||||
**LLMs:** Anthopic: [`claude-3-sonnet-20240229`](https://docs.anthropic.com/en/docs/models-overview#claude-3-a-new-generation-of-ai), [Vertex AI Search](https://cloud.google.com/enterprise-search)
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/117695) for GitLab.com in GitLab 16.0.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/451215) ability to ask doc-related questions on self-managed in GitLab 17.0 [with a flag](../administration/feature_flags.md) named `ai_gateway_docs_search`. Disabled by default.
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@ module Gitlab
|
|||
Error type: #{error['type']}
|
||||
Data: #{error['data']}
|
||||
Path: #{error['data_pointer']}
|
||||
Details: #{error['details']}
|
||||
ERROR_MSG
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -4,10 +4,8 @@ module Gitlab
|
|||
module UsageDataCounters
|
||||
COUNTERS = [
|
||||
PackageEventCounter,
|
||||
MergeRequestCounter,
|
||||
DiffsCounter,
|
||||
KubernetesAgentCounter,
|
||||
NoteCounter,
|
||||
WebIdeCounter,
|
||||
MergeRequestWidgetExtensionCounter
|
||||
].freeze
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module UsageDataCounters
|
||||
class MergeRequestCounter < BaseCounter
|
||||
KNOWN_EVENTS = %w[create].freeze
|
||||
PREFIX = 'merge_request'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab::UsageDataCounters
|
||||
class NoteCounter < BaseCounter
|
||||
KNOWN_EVENTS = %w[create].freeze
|
||||
PREFIX = 'note'
|
||||
COUNTABLE_TYPES = %w[MergeRequest].freeze
|
||||
|
||||
class << self
|
||||
def redis_key(event, noteable_type)
|
||||
"#{super(event)}_#{noteable_type}".upcase
|
||||
end
|
||||
|
||||
def count(event, noteable_type)
|
||||
return unless countable?(noteable_type)
|
||||
|
||||
increment(redis_key(event, noteable_type))
|
||||
end
|
||||
|
||||
def read(event, noteable_type)
|
||||
return 0 unless countable?(noteable_type)
|
||||
|
||||
total_count(redis_key(event, noteable_type))
|
||||
end
|
||||
|
||||
def totals
|
||||
COUNTABLE_TYPES.to_h do |countable_type|
|
||||
[counter_key(countable_type), read(:create, countable_type)]
|
||||
end
|
||||
end
|
||||
|
||||
def fallback_totals
|
||||
COUNTABLE_TYPES.to_h { |counter_key| [counter_key(counter_key), -1] }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def counter_key(countable_type)
|
||||
"#{countable_type.underscore}_comment".to_sym
|
||||
end
|
||||
|
||||
def countable?(noteable_type)
|
||||
COUNTABLE_TYPES.include?(noteable_type.to_s)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -32,3 +32,5 @@
|
|||
'{event_counters}_create_design_management_design': USAGE_DESIGN_MANAGEMENT_DESIGNS_CREATE
|
||||
'{event_counters}_update_design_management_design': USAGE_DESIGN_MANAGEMENT_DESIGNS_UPDATE
|
||||
'{event_counters}_delete_design_management_design': USAGE_DESIGN_MANAGEMENT_DESIGNS_DELETE
|
||||
'{event_counters}_create_merge_request': USAGE_MERGE_REQUEST_CREATE
|
||||
'{event_counters}_create_merge_request_note': USAGE_NOTE_CREATE_MERGEREQUEST
|
||||
|
|
|
|||
|
|
@ -5944,6 +5944,9 @@ msgstr ""
|
|||
msgid "Analytics|Host"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Invalid dashboard configuration"
|
||||
msgstr ""
|
||||
|
||||
msgid "Analytics|Invalid visualization configuration"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -14356,6 +14359,9 @@ msgstr ""
|
|||
msgid "Containers"
|
||||
msgstr ""
|
||||
|
||||
msgid "Contains errors"
|
||||
msgstr ""
|
||||
|
||||
msgid "Contains only whitespace changes."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'gitlab-qa', '~> 14', '>= 14.10.0', require: 'gitlab/qa'
|
||||
gem 'gitlab_quality-test_tooling', '~> 1.25.0', require: false
|
||||
gem 'gitlab_quality-test_tooling', '~> 1.26.0', require: false
|
||||
gem 'gitlab-utils', path: '../gems/gitlab-utils'
|
||||
gem 'activesupport', '~> 7.0.8.1' # This should stay in sync with the root's Gemfile
|
||||
gem 'allure-rspec', '~> 2.24.5'
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ GEM
|
|||
rainbow (>= 3, < 4)
|
||||
table_print (= 1.5.7)
|
||||
zeitwerk (>= 2, < 3)
|
||||
gitlab_quality-test_tooling (1.25.0)
|
||||
gitlab_quality-test_tooling (1.26.0)
|
||||
activesupport (>= 6.1, < 7.2)
|
||||
amatch (~> 0.4.1)
|
||||
gitlab (~> 4.19)
|
||||
|
|
@ -378,7 +378,7 @@ DEPENDENCIES
|
|||
gitlab-cng!
|
||||
gitlab-qa (~> 14, >= 14.10.0)
|
||||
gitlab-utils!
|
||||
gitlab_quality-test_tooling (~> 1.25.0)
|
||||
gitlab_quality-test_tooling (~> 1.26.0)
|
||||
influxdb-client (~> 3.1)
|
||||
junit_merge (~> 0.1.2)
|
||||
knapsack (~> 4.0)
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ module QA
|
|||
end
|
||||
end
|
||||
|
||||
context 'on a project with an unrecognized LICENSE',
|
||||
context 'on a project with an unrecognized LICENSE', :blocking,
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/366843' do
|
||||
it_behaves_like 'project license detection' do
|
||||
let(:license_file_name) { 'other' }
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ module QA
|
|||
context 'when a file with the same name already exists' do
|
||||
let(:file_name) { 'README.md' }
|
||||
|
||||
it 'throws an error', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/432899' do
|
||||
it 'throws an error', :blocking, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/432899' do
|
||||
Page::Project::WebIDE::VSCode.perform do |ide|
|
||||
ide.create_new_file(file_name)
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ module QA
|
|||
HTTP_STATUS_NO_CONTENT = 204
|
||||
HTTP_STATUS_ACCEPTED = 202
|
||||
HTTP_STATUS_PERMANENT_REDIRECT = 308
|
||||
HTTP_STATUS_UNAUTHORIZED = 401
|
||||
HTTP_STATUS_NOT_FOUND = 404
|
||||
HTTP_STATUS_TOO_MANY_REQUESTS = 429
|
||||
HTTP_STATUS_SERVER_ERROR = 500
|
||||
|
|
|
|||
|
|
@ -88,7 +88,7 @@ module QA
|
|||
def resource_exists?(project)
|
||||
response = get(resource_request(project))
|
||||
|
||||
if response.code == 404
|
||||
if response.code == HTTP_STATUS_NOT_FOUND
|
||||
logger.info("Project #{project[:path_with_namespace]} is no longer available\n")
|
||||
false
|
||||
else
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ module QA
|
|||
return log_failure(resource, response) unless mark_for_deletion_possible?(resource)
|
||||
|
||||
@permanently_delete ? delete_permanently(resource) : log_marked_for_deletion(resource)
|
||||
elsif response&.code == 404
|
||||
elsif response&.code == HTTP_STATUS_NOT_FOUND
|
||||
log_permanent_deletion(resource)
|
||||
else
|
||||
log_failure(resource, response)
|
||||
|
|
@ -98,6 +98,7 @@ module QA
|
|||
|
||||
unless user_response.code == HTTP_STATUS_OK
|
||||
logger.error("Request for #{qa_username} returned (#{user_response.code}): `#{user_response}` ")
|
||||
exit 1 if user_response.code == HTTP_STATUS_UNAUTHORIZED
|
||||
return
|
||||
end
|
||||
|
||||
|
|
@ -135,6 +136,7 @@ module QA
|
|||
resources.concat(parse_body(response).select { |r| Date.parse(r[:created_at]) < @delete_before })
|
||||
else
|
||||
logger.error("Request for #{@type} returned (#{response.code}): `#{response}` ")
|
||||
exit 1 if response.code == HTTP_STATUS_UNAUTHORIZED
|
||||
end
|
||||
|
||||
page_no = response.headers[:x_next_page].to_s
|
||||
|
|
@ -263,7 +265,7 @@ module QA
|
|||
# @return [Boolean]
|
||||
def permanently_deleted?(resource)
|
||||
response = get(resource_request(resource))
|
||||
response.code == 404
|
||||
response.code == HTTP_STATUS_NOT_FOUND
|
||||
end
|
||||
|
||||
# Prints failed deletion attempts
|
||||
|
|
@ -305,11 +307,12 @@ module QA
|
|||
def wait_for_resource_deletion(resource, permanent = false)
|
||||
wait_until(max_duration: 60, sleep_interval: 1, raise_on_failure: false) do
|
||||
response = get(resource_request(resource))
|
||||
deleted = response&.code == HTTP_STATUS_NOT_FOUND
|
||||
|
||||
if permanent
|
||||
response&.code == 404
|
||||
deleted
|
||||
else
|
||||
response&.code == 404 || (success?(response&.code) && marked_for_deletion?(parse_body(response)))
|
||||
deleted || (success?(response&.code) && marked_for_deletion?(parse_body(response)))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ module QA
|
|||
def resource_exists?(subgroup)
|
||||
response = get(resource_request(subgroup))
|
||||
|
||||
if response.code == 404
|
||||
if response.code == HTTP_STATUS_NOT_FOUND
|
||||
logger.info("Subgroup #{subgroup[:full_path]} is no longer available\n")
|
||||
false
|
||||
else
|
||||
|
|
|
|||
|
|
@ -111,6 +111,7 @@ module QA
|
|||
|
||||
def fetch_qa_username(user_id)
|
||||
response = get Runtime::API::Request.new(@api_client, "/users/#{user_id}").url
|
||||
exit 1 if response.code == HTTP_STATUS_UNAUTHORIZED
|
||||
parsed_response = parse_body(response)
|
||||
parsed_response[:username]
|
||||
end
|
||||
|
|
@ -118,7 +119,7 @@ module QA
|
|||
def resource_exists?(project)
|
||||
response = get(resource_request(project))
|
||||
|
||||
if response.code == 404
|
||||
if response.code == HTTP_STATUS_NOT_FOUND
|
||||
logger.info("Project #{project[:path_with_namespace]} is no longer available\n")
|
||||
false
|
||||
else
|
||||
|
|
|
|||
|
|
@ -11,8 +11,9 @@ module QA
|
|||
|
||||
group_search_response = get Runtime::API::Request.new(api_client, "/groups/#{group_name}").url
|
||||
|
||||
if group_search_response.code != 200
|
||||
if group_search_response.code != HTTP_STATUS_OK
|
||||
logger.error("Response code #{group_search_response.code}: #{group_search_response.body}")
|
||||
exit 1 if group_search_response.code == HTTP_STATUS_UNAUTHORIZED
|
||||
return
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -137,6 +137,7 @@ describe('HeaderActions component', () => {
|
|||
const findReportAbuseButton = () => wrapper.findByTestId('report-abuse-item');
|
||||
const findCopyRefenceDropdownItem = () => wrapper.findByTestId('copy-reference');
|
||||
const findCopyEmailItem = () => wrapper.findByTestId('copy-email');
|
||||
const findPromoteToEpicButton = () => wrapper.findByTestId('promote-button');
|
||||
|
||||
const findModal = () => wrapper.findComponent(GlModal);
|
||||
|
||||
|
|
@ -359,7 +360,35 @@ describe('HeaderActions component', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('when "Promote to epic" button is clicked', () => {
|
||||
describe('"Promote to epic" button behavior', () => {
|
||||
describe('default', () => {
|
||||
it('the button is enabled when the user can promote to epic', () => {
|
||||
wrapper = mountComponent();
|
||||
|
||||
expect(findPromoteToEpicButton().props('item')).toMatchObject({
|
||||
extraAttrs: { disabled: false },
|
||||
text: 'Promote to epic',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when request is in flight', () => {
|
||||
it('disables the promote option', async () => {
|
||||
wrapper = mountComponent({
|
||||
promoteToEpicHandler: promoteToEpicMutationSuccessResponseHandler,
|
||||
});
|
||||
|
||||
findPromoteToEpicButton().vm.$emit('action');
|
||||
|
||||
await nextTick();
|
||||
|
||||
expect(findPromoteToEpicButton().props('item')).toMatchObject({
|
||||
extraAttrs: { disabled: true },
|
||||
text: 'Promote to epic',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when response is successful', () => {
|
||||
beforeEach(async () => {
|
||||
visitUrlSpy = jest.spyOn(urlUtility, 'visitUrl').mockReturnValue({});
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::UsageDataCounters::MergeRequestCounter do
|
||||
it_behaves_like 'a redis usage counter', 'Merge Request', :create
|
||||
|
||||
it_behaves_like 'a redis usage counter with totals', :merge_request, create: 5
|
||||
end
|
||||
|
|
@ -1,78 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::UsageDataCounters::NoteCounter, :clean_gitlab_redis_shared_state do
|
||||
shared_examples 'a note usage counter' do |event, noteable_type|
|
||||
describe ".count(#{event})" do
|
||||
it "increments the Note #{event} counter by 1" do
|
||||
expect do
|
||||
described_class.count(event, noteable_type)
|
||||
end.to change { described_class.read(event, noteable_type) }.by 1
|
||||
end
|
||||
end
|
||||
|
||||
describe ".read(#{event})" do
|
||||
event_count = 5
|
||||
|
||||
it "returns the total number of #{event} events" do
|
||||
event_count.times do
|
||||
described_class.count(event, noteable_type)
|
||||
end
|
||||
|
||||
expect(described_class.read(event, noteable_type)).to eq(event_count)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'a note usage counter', :create, 'MergeRequest'
|
||||
|
||||
describe '.totals' do
|
||||
let(:combinations) do
|
||||
[
|
||||
[:create, 'MergeRequest', 4]
|
||||
]
|
||||
end
|
||||
|
||||
let(:expected_totals) do
|
||||
{ merge_request_comment: 4 }
|
||||
end
|
||||
|
||||
before do
|
||||
combinations.each do |event, noteable_type, n|
|
||||
n.times do
|
||||
described_class.count(event, noteable_type)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'can report all totals' do
|
||||
expect(described_class.totals).to include(expected_totals)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'unknown events or noteable_type' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let(:unknown_event_error) { Gitlab::UsageDataCounters::BaseCounter::UnknownEvent }
|
||||
|
||||
where(:event, :noteable_type, :expected_count, :should_raise) do
|
||||
:create | 'MergeRequest' | 1 | false
|
||||
:wibble | 'MergeRequest' | 0 | true
|
||||
:create | 'Issue' | 0 | false
|
||||
:wibble | 'Issue' | 0 | false
|
||||
end
|
||||
|
||||
with_them do
|
||||
it 'handles event' do
|
||||
if should_raise
|
||||
expect { described_class.count(event, noteable_type) }.to raise_error(unknown_event_error)
|
||||
else
|
||||
described_class.count(event, noteable_type)
|
||||
|
||||
expect(described_class.read(event, noteable_type)).to eq(expected_count)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -40,11 +40,6 @@ RSpec.describe Gitlab::UsageDataQueries do
|
|||
describe '.redis_usage_data' do
|
||||
subject(:redis_usage_data) { described_class.redis_usage_data { 42 } }
|
||||
|
||||
it 'returns a stringified class for redis_usage_data with a counter call' do
|
||||
expect(described_class.redis_usage_data(Gitlab::UsageDataCounters::MergeRequestCounter))
|
||||
.to eq(redis_usage_data_counter: "Gitlab::UsageDataCounters::MergeRequestCounter")
|
||||
end
|
||||
|
||||
it 'returns a placeholder string for redis_usage_data with a block' do
|
||||
is_expected.to include(:redis_usage_data_block)
|
||||
expect(redis_usage_data[:redis_usage_data_block]).to eq('non-SQL usage data block')
|
||||
|
|
|
|||
|
|
@ -502,18 +502,18 @@ RSpec.describe Gitlab::Utils::UsageData do
|
|||
|
||||
context 'with counter given' do
|
||||
context 'when gets an error' do
|
||||
subject { described_class.redis_usage_data(::Gitlab::UsageDataCounters::MergeRequestCounter) }
|
||||
subject { described_class.redis_usage_data(::Gitlab::UsageDataCounters::PackageEventCounter) }
|
||||
|
||||
let(:fallback) { ::Gitlab::UsageDataCounters::MergeRequestCounter.fallback_totals }
|
||||
let(:failing_class) { ::Gitlab::UsageDataCounters::MergeRequestCounter }
|
||||
let(:fallback) { ::Gitlab::UsageDataCounters::PackageEventCounter.fallback_totals }
|
||||
let(:failing_class) { ::Gitlab::UsageDataCounters::PackageEventCounter }
|
||||
let(:failing_method) { :totals }
|
||||
|
||||
it_behaves_like 'failing hardening method', ::Redis::CommandError
|
||||
end
|
||||
|
||||
it 'returns the totals when couter is given' do
|
||||
allow(::Gitlab::UsageDataCounters::MergeRequestCounter).to receive(:totals).and_return({ merge_request_create: 2 })
|
||||
expect(described_class.redis_usage_data(::Gitlab::UsageDataCounters::MergeRequestCounter)).to eql({ merge_request_create: 2 })
|
||||
allow(::Gitlab::UsageDataCounters::PackageEventCounter).to receive(:totals).and_return({ merge_request_create: 2 })
|
||||
expect(described_class.redis_usage_data(::Gitlab::UsageDataCounters::PackageEventCounter)).to eql({ merge_request_create: 2 })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -234,7 +234,7 @@ RSpec.describe DraftNotes::PublishService, feature_category: :code_review_workfl
|
|||
|
||||
recorder = ActiveRecord::QueryRecorder.new(skip_cached: false) { publish }
|
||||
|
||||
expect(recorder.count).not_to be > 105
|
||||
expect(recorder.count).not_to be > 106
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -170,10 +170,12 @@ RSpec.describe MergeRequests::AfterCreateService, feature_category: :code_review
|
|||
end
|
||||
end
|
||||
|
||||
it 'increments the usage data counter of create event' do
|
||||
counter = Gitlab::UsageDataCounters::MergeRequestCounter
|
||||
it_behaves_like 'internal event tracking' do
|
||||
let(:user) { merge_request.author }
|
||||
let(:event) { 'create_merge_request' }
|
||||
let(:project) { merge_request.project }
|
||||
|
||||
expect { execute_service }.to change { counter.read(:create) }.by(1)
|
||||
subject(:track_event) { execute_service }
|
||||
end
|
||||
|
||||
context 'todos' do
|
||||
|
|
@ -247,12 +249,6 @@ RSpec.describe MergeRequests::AfterCreateService, feature_category: :code_review
|
|||
end
|
||||
end
|
||||
|
||||
it 'tracks merge request creation in usage data' do
|
||||
expect(Gitlab::UsageDataCounters::MergeRequestCounter).to receive(:count).with(:create)
|
||||
|
||||
execute_service
|
||||
end
|
||||
|
||||
it 'calls MergeRequests::LinkLfsObjectsService#execute' do
|
||||
service = instance_spy(MergeRequests::LinkLfsObjectsService)
|
||||
allow(MergeRequests::LinkLfsObjectsService).to receive(:new).with(project: merge_request.target_project).and_return(service)
|
||||
|
|
|
|||
|
|
@ -714,6 +714,18 @@ RSpec.describe Notes::CreateService, feature_category: :team_planning do
|
|||
let(:event) { 'create_snippet_note' }
|
||||
let(:category) { described_class.to_s }
|
||||
|
||||
context 'merge request' do
|
||||
let(:merge_request) { create(:merge_request) }
|
||||
let(:opts) { { note: 'reply', noteable_type: 'MergeRequest', noteable_id: merge_request.id, project: merge_request.project } }
|
||||
|
||||
it_behaves_like 'internal event tracking' do
|
||||
let(:event) { 'create_merge_request_note' }
|
||||
let(:project) { merge_request.project }
|
||||
|
||||
subject(:track_event) { described_class.new(merge_request.project, user, opts).execute }
|
||||
end
|
||||
end
|
||||
|
||||
context 'snippet note' do
|
||||
let(:snippet) { create(:project_snippet, project: project) }
|
||||
let(:opts) { { note: 'reply', noteable_type: 'Snippet', noteable_id: snippet.id, project: project } }
|
||||
|
|
|
|||
|
|
@ -6607,9 +6607,7 @@
|
|||
- './spec/lib/gitlab/usage_data_counters/jetbrains_plugin_activity_unique_counter_spec.rb'
|
||||
- './spec/lib/gitlab/usage_data_counters/kubernetes_agent_counter_spec.rb'
|
||||
- './spec/lib/gitlab/usage_data_counters/merge_request_activity_unique_counter_spec.rb'
|
||||
- './spec/lib/gitlab/usage_data_counters/merge_request_counter_spec.rb'
|
||||
- './spec/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter_spec.rb'
|
||||
- './spec/lib/gitlab/usage_data_counters/note_counter_spec.rb'
|
||||
- './spec/lib/gitlab/usage_data_counters/package_event_counter_spec.rb'
|
||||
- './spec/lib/gitlab/usage_data_counters/quick_action_activity_unique_counter_spec.rb'
|
||||
- './spec/lib/gitlab/usage_data_counters/redis_counter_spec.rb'
|
||||
|
|
|
|||
Loading…
Reference in New Issue