Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
a5c4a731c8
commit
0ef9ecf0ce
|
@ -1948,7 +1948,6 @@ Layout/LineLength:
|
||||||
- 'ee/spec/features/groups/security/compliance_dashboards_spec.rb'
|
- 'ee/spec/features/groups/security/compliance_dashboards_spec.rb'
|
||||||
- 'ee/spec/features/groups/sso_spec.rb'
|
- 'ee/spec/features/groups/sso_spec.rb'
|
||||||
- 'ee/spec/features/groups/usage_quotas_spec.rb'
|
- 'ee/spec/features/groups/usage_quotas_spec.rb'
|
||||||
- 'ee/spec/features/incidents/incident_details_spec.rb'
|
|
||||||
- 'ee/spec/features/integrations/jira/jira_issues_list_spec.rb'
|
- 'ee/spec/features/integrations/jira/jira_issues_list_spec.rb'
|
||||||
- 'ee/spec/features/invites_spec.rb'
|
- 'ee/spec/features/invites_spec.rb'
|
||||||
- 'ee/spec/features/issues/filtered_search/filter_issues_weight_spec.rb'
|
- 'ee/spec/features/issues/filtered_search/filter_issues_weight_spec.rb'
|
||||||
|
@ -2790,8 +2789,6 @@ Layout/LineLength:
|
||||||
- 'ee/spec/services/ee/groups/autocomplete_service_spec.rb'
|
- 'ee/spec/services/ee/groups/autocomplete_service_spec.rb'
|
||||||
- 'ee/spec/services/ee/groups/deploy_tokens/create_service_spec.rb'
|
- 'ee/spec/services/ee/groups/deploy_tokens/create_service_spec.rb'
|
||||||
- 'ee/spec/services/ee/groups/import_export/export_service_spec.rb'
|
- 'ee/spec/services/ee/groups/import_export/export_service_spec.rb'
|
||||||
- 'ee/spec/services/ee/incident_management/issuable_escalation_statuses/after_update_service_spec.rb'
|
|
||||||
- 'ee/spec/services/ee/incident_management/issuable_escalation_statuses/prepare_update_service_spec.rb'
|
|
||||||
- 'ee/spec/services/ee/ip_restrictions/update_service_spec.rb'
|
- 'ee/spec/services/ee/ip_restrictions/update_service_spec.rb'
|
||||||
- 'ee/spec/services/ee/issuable/common_system_notes_service_spec.rb'
|
- 'ee/spec/services/ee/issuable/common_system_notes_service_spec.rb'
|
||||||
- 'ee/spec/services/ee/issuable/destroy_service_spec.rb'
|
- 'ee/spec/services/ee/issuable/destroy_service_spec.rb'
|
||||||
|
|
|
@ -154,7 +154,6 @@ RSpec/ContextWording:
|
||||||
- 'ee/spec/features/groups/wiki/user_views_wiki_empty_spec.rb'
|
- 'ee/spec/features/groups/wiki/user_views_wiki_empty_spec.rb'
|
||||||
- 'ee/spec/features/groups_spec.rb'
|
- 'ee/spec/features/groups_spec.rb'
|
||||||
- 'ee/spec/features/ide/user_opens_ide_spec.rb'
|
- 'ee/spec/features/ide/user_opens_ide_spec.rb'
|
||||||
- 'ee/spec/features/incidents/incident_details_spec.rb'
|
|
||||||
- 'ee/spec/features/integrations/jira/jira_issues_list_spec.rb'
|
- 'ee/spec/features/integrations/jira/jira_issues_list_spec.rb'
|
||||||
- 'ee/spec/features/issues/epic_in_issue_sidebar_spec.rb'
|
- 'ee/spec/features/issues/epic_in_issue_sidebar_spec.rb'
|
||||||
- 'ee/spec/features/issues/filtered_search/filter_issues_by_iteration_spec.rb'
|
- 'ee/spec/features/issues/filtered_search/filter_issues_by_iteration_spec.rb'
|
||||||
|
@ -869,7 +868,6 @@ RSpec/ContextWording:
|
||||||
- 'ee/spec/services/ee/ci/job_artifacts/destroy_batch_service_spec.rb'
|
- 'ee/spec/services/ee/ci/job_artifacts/destroy_batch_service_spec.rb'
|
||||||
- 'ee/spec/services/ee/git/branch_push_service_spec.rb'
|
- 'ee/spec/services/ee/git/branch_push_service_spec.rb'
|
||||||
- 'ee/spec/services/ee/groups/autocomplete_service_spec.rb'
|
- 'ee/spec/services/ee/groups/autocomplete_service_spec.rb'
|
||||||
- 'ee/spec/services/ee/incident_management/issuable_escalation_statuses/after_update_service_spec.rb'
|
|
||||||
- 'ee/spec/services/ee/integrations/test/project_service_spec.rb'
|
- 'ee/spec/services/ee/integrations/test/project_service_spec.rb'
|
||||||
- 'ee/spec/services/ee/ip_restrictions/update_service_spec.rb'
|
- 'ee/spec/services/ee/ip_restrictions/update_service_spec.rb'
|
||||||
- 'ee/spec/services/ee/issuable/bulk_update_service_spec.rb'
|
- 'ee/spec/services/ee/issuable/bulk_update_service_spec.rb'
|
||||||
|
|
|
@ -5,6 +5,7 @@ module WorkItems
|
||||||
self.table_name = 'work_item_parent_links'
|
self.table_name = 'work_item_parent_links'
|
||||||
|
|
||||||
MAX_CHILDREN = 100
|
MAX_CHILDREN = 100
|
||||||
|
PARENT_TYPES = [:issue, :incident].freeze
|
||||||
|
|
||||||
belongs_to :work_item
|
belongs_to :work_item
|
||||||
belongs_to :work_item_parent, class_name: 'WorkItem'
|
belongs_to :work_item_parent, class_name: 'WorkItem'
|
||||||
|
@ -21,15 +22,20 @@ module WorkItems
|
||||||
return unless work_item
|
return unless work_item
|
||||||
|
|
||||||
unless work_item.task?
|
unless work_item.task?
|
||||||
errors.add :work_item, _('Only Task can be assigned as a child in hierarchy.')
|
errors.add :work_item, _('only Task can be assigned as a child in hierarchy.')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_parent_type
|
def validate_parent_type
|
||||||
return unless work_item_parent
|
return unless work_item_parent
|
||||||
|
|
||||||
unless work_item_parent.issue?
|
base_type = work_item_parent.work_item_type.base_type.to_sym
|
||||||
errors.add :work_item_parent, _('Only Issue can be parent of Task.')
|
unless PARENT_TYPES.include?(base_type)
|
||||||
|
parent_names = WorkItems::Type::BASE_TYPES.slice(*WorkItems::ParentLink::PARENT_TYPES)
|
||||||
|
.values.map { |type| type[:name] }
|
||||||
|
|
||||||
|
errors.add :work_item_parent, _('only %{parent_types} can be parent of Task.') %
|
||||||
|
{ parent_types: parent_names.to_sentence }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -37,7 +43,7 @@ module WorkItems
|
||||||
return if work_item.nil? || work_item_parent.nil?
|
return if work_item.nil? || work_item_parent.nil?
|
||||||
|
|
||||||
if work_item.resource_parent != work_item_parent.resource_parent
|
if work_item.resource_parent != work_item_parent.resource_parent
|
||||||
errors.add :work_item_parent, _('Parent must be in the same project as child.')
|
errors.add :work_item_parent, _('parent must be in the same project as child.')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -46,7 +52,7 @@ module WorkItems
|
||||||
|
|
||||||
max = persisted? ? MAX_CHILDREN : MAX_CHILDREN - 1
|
max = persisted? ? MAX_CHILDREN : MAX_CHILDREN - 1
|
||||||
if work_item_parent.child_links.count > max
|
if work_item_parent.child_links.count > max
|
||||||
errors.add :work_item_parent, _('Parent already has maximum number of children.')
|
errors.add :work_item_parent, _('parent already has maximum number of children.')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -22,7 +22,7 @@ module WorkItems
|
||||||
|
|
||||||
WIDGETS_FOR_TYPE = {
|
WIDGETS_FOR_TYPE = {
|
||||||
issue: [Widgets::Assignees, Widgets::Description, Widgets::Hierarchy, Widgets::Weight],
|
issue: [Widgets::Assignees, Widgets::Description, Widgets::Hierarchy, Widgets::Weight],
|
||||||
incident: [Widgets::Description],
|
incident: [Widgets::Description, Widgets::Hierarchy],
|
||||||
test_case: [Widgets::Description],
|
test_case: [Widgets::Description],
|
||||||
requirement: [Widgets::Description],
|
requirement: [Widgets::Description],
|
||||||
task: [Widgets::Assignees, Widgets::Description, Widgets::Hierarchy, Widgets::Weight]
|
task: [Widgets::Assignees, Widgets::Description, Widgets::Hierarchy, Widgets::Weight]
|
||||||
|
|
|
@ -4,13 +4,13 @@ module WorkItems
|
||||||
module Widgets
|
module Widgets
|
||||||
class Hierarchy < Base
|
class Hierarchy < Base
|
||||||
def parent
|
def parent
|
||||||
return unless Feature.enabled?(:work_items_hierarchy, work_item.project)
|
return unless Feature.enabled?(:work_items, work_item.project)
|
||||||
|
|
||||||
work_item.work_item_parent
|
work_item.work_item_parent
|
||||||
end
|
end
|
||||||
|
|
||||||
def children
|
def children
|
||||||
return WorkItem.none unless Feature.enabled?(:work_items_hierarchy, work_item.project)
|
return WorkItem.none unless Feature.enabled?(:work_items, work_item.project)
|
||||||
|
|
||||||
work_item.work_item_children
|
work_item.work_item_children
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
---
|
---
|
||||||
name: issue_email_participants
|
name: issue_email_participants
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49264
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49264
|
||||||
rollout_issue_url:
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/350460
|
||||||
milestone: '13.8'
|
milestone: '13.8'
|
||||||
type: development
|
type: development
|
||||||
group: group::product planning
|
group: group::product planning
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
name: skip_scheduling_mirrors_for_free
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92377
|
||||||
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/367712
|
||||||
|
milestone: '15.2'
|
||||||
|
type: development
|
||||||
|
group: group::source code
|
||||||
|
default_enabled: false
|
|
@ -59,6 +59,7 @@
|
||||||
events:
|
events:
|
||||||
- users_creating_work_items
|
- users_creating_work_items
|
||||||
- users_updating_work_item_title
|
- users_updating_work_item_title
|
||||||
|
- users_updating_weight_estimate
|
||||||
feature_flag: track_work_items_activity
|
feature_flag: track_work_items_activity
|
||||||
- name: xmau_project_management
|
- name: xmau_project_management
|
||||||
operator: OR
|
operator: OR
|
||||||
|
@ -67,6 +68,7 @@
|
||||||
events:
|
events:
|
||||||
- users_creating_work_items
|
- users_creating_work_items
|
||||||
- users_updating_work_item_title
|
- users_updating_work_item_title
|
||||||
|
- users_updating_weight_estimate
|
||||||
feature_flag: track_work_items_activity
|
feature_flag: track_work_items_activity
|
||||||
- name: users_work_items
|
- name: users_work_items
|
||||||
operator: OR
|
operator: OR
|
||||||
|
@ -75,4 +77,5 @@
|
||||||
events:
|
events:
|
||||||
- users_creating_work_items
|
- users_creating_work_items
|
||||||
- users_updating_work_item_title
|
- users_updating_work_item_title
|
||||||
|
- users_updating_weight_estimate
|
||||||
feature_flag: track_work_items_activity
|
feature_flag: track_work_items_activity
|
||||||
|
|
|
@ -9,6 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
||||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332747) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `ff_external_audit_events_namespace`. Disabled by default.
|
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/332747) in GitLab 14.5 [with a flag](../administration/feature_flags.md) named `ff_external_audit_events_namespace`. Disabled by default.
|
||||||
> - [Enabled on GitLab.com and by default on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/338939) in GitLab 14.7.
|
> - [Enabled on GitLab.com and by default on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/338939) in GitLab 14.7.
|
||||||
> - [Feature flag `ff_external_audit_events_namespace`](https://gitlab.com/gitlab-org/gitlab/-/issues/349588) removed in GitLab 14.8.
|
> - [Feature flag `ff_external_audit_events_namespace`](https://gitlab.com/gitlab-org/gitlab/-/issues/349588) removed in GitLab 14.8.
|
||||||
|
> - [Subgroup events recording](https://gitlab.com/gitlab-org/gitlab/-/issues/366878) fixed in GitLab 15.2.
|
||||||
|
|
||||||
Users can set an HTTP endpoint for a top-level group to receive all audit events about the group, its subgroups, and
|
Users can set an HTTP endpoint for a top-level group to receive all audit events about the group, its subgroups, and
|
||||||
projects as structured JSON.
|
projects as structured JSON.
|
||||||
|
|
|
@ -40,7 +40,7 @@ A typical pipeline might consist of four stages, executed in the following order
|
||||||
NOTE:
|
NOTE:
|
||||||
If you have a [mirrored repository that GitLab pulls from](../../user/project/repository/mirror/pull.md),
|
If you have a [mirrored repository that GitLab pulls from](../../user/project/repository/mirror/pull.md),
|
||||||
you may need to enable pipeline triggering in your project's
|
you may need to enable pipeline triggering in your project's
|
||||||
**Settings > Repository > Pull from a remote repository > Trigger pipelines for mirror updates**.
|
**Settings > Repository > Mirroring repositories > Trigger pipelines for mirror updates**.
|
||||||
|
|
||||||
## Types of pipelines
|
## Types of pipelines
|
||||||
|
|
||||||
|
|
|
@ -61,4 +61,6 @@ the rule fires. You can respond to a page or stop incident escalations by
|
||||||
[updating the incident's status](incidents.md#change-incident-status) or, if applicable,
|
[updating the incident's status](incidents.md#change-incident-status) or, if applicable,
|
||||||
[unsetting the incident's escalation policy](incidents.md#change-escalation-policy).
|
[unsetting the incident's escalation policy](incidents.md#change-escalation-policy).
|
||||||
|
|
||||||
To avoid duplicate pages, [incidents created from alerts](alerts.md#create-an-incident-from-an-alert) do not support independent escalation.
|
In GitLab 15.1 and earlier, [incidents created from alerts](alerts.md#create-an-incident-from-an-alert)
|
||||||
|
do not support independent escalation. In [GitLab 15.2 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/356057),
|
||||||
|
all incidents can be escalated independently.
|
||||||
|
|
|
@ -69,7 +69,7 @@ This rule enforces the defined actions based on the information provided.
|
||||||
| Field | Type | Possible values | Description |
|
| Field | Type | Possible values | Description |
|
||||||
|------------|------|-----------------|-------------|
|
|------------|------|-----------------|-------------|
|
||||||
| `type` | `string` | `scan_finding` | The rule's type. |
|
| `type` | `string` | `scan_finding` | The rule's type. |
|
||||||
| `branches` | `array` of `string` | `[]` or the branch's name | Protected branches for this rule to consider. |
|
| `branches` | `array` of `string` | `[]` or the branch's name | Applicable only to protected target branches. An empty array, `[]`, applies the rule to all protected target branches. |
|
||||||
| `scanners` | `array` of `string` | `sast`, `secret_detection`, `dependency_scanning`, `container_scanning`, `dast`, `coverage_fuzzing`, `api_fuzzing` | The security scanners for this rule to consider. |
|
| `scanners` | `array` of `string` | `sast`, `secret_detection`, `dependency_scanning`, `container_scanning`, `dast`, `coverage_fuzzing`, `api_fuzzing` | The security scanners for this rule to consider. |
|
||||||
| `vulnerabilities_allowed` | `integer` | Greater than or equal to zero | Number of vulnerabilities allowed before this rule is considered. |
|
| `vulnerabilities_allowed` | `integer` | Greater than or equal to zero | Number of vulnerabilities allowed before this rule is considered. |
|
||||||
| `severity_levels` | `array` of `string` | `info`, `unknown`, `low`, `medium`, `high`, `critical`| The severity levels for this rule to consider. |
|
| `severity_levels` | `array` of `string` | `info`, `unknown`, `low`, `medium`, `high`, `critical`| The severity levels for this rule to consider. |
|
||||||
|
|
|
@ -209,3 +209,25 @@ upload:
|
||||||
The [Write CI-CD Variables in Pipeline](https://gitlab.com/guided-explorations/cfg-data/write-ci-cd-variables-in-pipeline) project contains a working example you can use to create, upload, and download generic packages in GitLab CI/CD.
|
The [Write CI-CD Variables in Pipeline](https://gitlab.com/guided-explorations/cfg-data/write-ci-cd-variables-in-pipeline) project contains a working example you can use to create, upload, and download generic packages in GitLab CI/CD.
|
||||||
|
|
||||||
It also demonstrates how to manage a semantic version for the generic package: storing it in a CI/CD variable, retrieving it, incrementing it, and writing it back to the CI/CD variable when tests for the download work correctly.
|
It also demonstrates how to manage a semantic version for the generic package: storing it in a CI/CD variable, retrieving it, incrementing it, and writing it back to the CI/CD variable when tests for the download work correctly.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Internal Server error on large file uploads to S3
|
||||||
|
|
||||||
|
S3-compatible object storage [limits the size of a single PUT request to 5GB](https://docs.aws.amazon.com/AmazonS3/latest/userguide/upload-objects.html). If the `aws_signature_version` is set to `2` in the [object storage connection settings](../../../administration/object_storage.md), attempting to publish a package file larger than the 5GB limit can result in a `HTTP 500: Internal Server Error` response.
|
||||||
|
|
||||||
|
If you are receiving `HTTP 500: Internal Server Error` responses when publishing large files to S3, set the `aws_signature_version` to `4`:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
# Consolidated Object Storage settings
|
||||||
|
gitlab_rails['object_store']['connection'] = {
|
||||||
|
# Other connection settings
|
||||||
|
`aws_signature_version` => '4'
|
||||||
|
}
|
||||||
|
# OR
|
||||||
|
# Storage-specific form settings
|
||||||
|
gitlab_rails['packages_object_store_connection'] = {
|
||||||
|
# Other connection settings
|
||||||
|
`aws_signature_version` => '4'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
|
@ -9,3 +9,8 @@
|
||||||
redis_slot: users
|
redis_slot: users
|
||||||
aggregation: weekly
|
aggregation: weekly
|
||||||
feature_flag: track_work_items_activity
|
feature_flag: track_work_items_activity
|
||||||
|
- name: users_updating_weight_estimate
|
||||||
|
category: work_items
|
||||||
|
redis_slot: users
|
||||||
|
aggregation: weekly
|
||||||
|
feature_flag: track_work_items_activity
|
||||||
|
|
|
@ -26,3 +26,7 @@ module Gitlab
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# rubocop:disable Layout/LineLength
|
||||||
|
Gitlab::UsageDataCounters::WorkItemActivityUniqueCounter.prepend_mod_with('Gitlab::UsageDataCounters::WorkItemActivityUniqueCounter')
|
||||||
|
# rubocop:enable Layout/LineLength
|
||||||
|
|
|
@ -27101,18 +27101,12 @@ msgstr ""
|
||||||
msgid "Only Issue ID or merge request ID is required"
|
msgid "Only Issue ID or merge request ID is required"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Only Issue can be parent of Task."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Only Project Members"
|
msgid "Only Project Members"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Only SSH"
|
msgid "Only SSH"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Only Task can be assigned as a child in hierarchy."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Only accessible by %{membersPageLinkStart}project members%{membersPageLinkEnd}. Membership must be explicitly granted to each user."
|
msgid "Only accessible by %{membersPageLinkStart}project members%{membersPageLinkEnd}. Membership must be explicitly granted to each user."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -27880,18 +27874,12 @@ msgstr ""
|
||||||
msgid "Parent"
|
msgid "Parent"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Parent already has maximum number of children."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Parent epic doesn't exist."
|
msgid "Parent epic doesn't exist."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Parent epic is not present."
|
msgid "Parent epic is not present."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Parent must be in the same project as child."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
msgid "Parsing error for param :embed_json. %{message}"
|
msgid "Parsing error for param :embed_json. %{message}"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -46531,6 +46519,12 @@ msgstr ""
|
||||||
msgid "on track"
|
msgid "on track"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "only %{parent_types} can be parent of Task."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "only Task can be assigned as a child in hierarchy."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "only available on top-level groups."
|
msgid "only available on top-level groups."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
@ -46562,6 +46556,12 @@ msgid_plural "parents"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
||||||
|
msgid "parent already has maximum number of children."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "parent must be in the same project as child."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "password"
|
msgid "password"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,7 @@
|
||||||
"dateformat": "^5.0.1",
|
"dateformat": "^5.0.1",
|
||||||
"deckar01-task_list": "^2.3.1",
|
"deckar01-task_list": "^2.3.1",
|
||||||
"diff": "^3.4.0",
|
"diff": "^3.4.0",
|
||||||
"dompurify": "^2.3.8",
|
"dompurify": "^2.3.9",
|
||||||
"dropzone": "^4.2.0",
|
"dropzone": "^4.2.0",
|
||||||
"editorconfig": "^0.15.3",
|
"editorconfig": "^0.15.3",
|
||||||
"emoji-regex": "^10.0.0",
|
"emoji-regex": "^10.0.0",
|
||||||
|
|
|
@ -14,5 +14,10 @@ FactoryBot.define do
|
||||||
issue_type { :task }
|
issue_type { :task }
|
||||||
association :work_item_type, :default, :task
|
association :work_item_type, :default, :task
|
||||||
end
|
end
|
||||||
|
|
||||||
|
trait :incident do
|
||||||
|
issue_type { :incident }
|
||||||
|
association :work_item_type, :default, :incident
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,46 +5,6 @@ require 'spec_helper'
|
||||||
RSpec.describe Gitlab::UsageDataCounters::WorkItemActivityUniqueCounter, :clean_gitlab_redis_shared_state do
|
RSpec.describe Gitlab::UsageDataCounters::WorkItemActivityUniqueCounter, :clean_gitlab_redis_shared_state do
|
||||||
let(:user) { build(:user, id: 1) }
|
let(:user) { build(:user, id: 1) }
|
||||||
|
|
||||||
shared_examples 'counter that does not track the event' do
|
|
||||||
it 'does not track the event' do
|
|
||||||
expect { 3.times { track_event } }.to not_change {
|
|
||||||
Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(
|
|
||||||
event_names: event_name,
|
|
||||||
start_date: 2.weeks.ago,
|
|
||||||
end_date: 2.weeks.from_now
|
|
||||||
)
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
shared_examples 'work item unique counter' do
|
|
||||||
context 'when track_work_items_activity FF is enabled' do
|
|
||||||
it 'tracks a unique event only once' do
|
|
||||||
expect { 3.times { track_event } }.to change {
|
|
||||||
Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(
|
|
||||||
event_names: event_name,
|
|
||||||
start_date: 2.weeks.ago,
|
|
||||||
end_date: 2.weeks.from_now
|
|
||||||
)
|
|
||||||
}.by(1)
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when author is nil' do
|
|
||||||
let(:user) { nil }
|
|
||||||
|
|
||||||
it_behaves_like 'counter that does not track the event'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context 'when track_work_items_activity FF is disabled' do
|
|
||||||
before do
|
|
||||||
stub_feature_flags(track_work_items_activity: false)
|
|
||||||
end
|
|
||||||
|
|
||||||
it_behaves_like 'counter that does not track the event'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
describe '.track_work_item_created_action' do
|
describe '.track_work_item_created_action' do
|
||||||
subject(:track_event) { described_class.track_work_item_created_action(author: user) }
|
subject(:track_event) { described_class.track_work_item_created_action(author: user) }
|
||||||
|
|
||||||
|
|
|
@ -15,32 +15,37 @@ RSpec.describe WorkItems::ParentLink do
|
||||||
describe 'hierarchy' do
|
describe 'hierarchy' do
|
||||||
let_it_be(:project) { create(:project) }
|
let_it_be(:project) { create(:project) }
|
||||||
let_it_be(:issue) { build(:work_item, project: project) }
|
let_it_be(:issue) { build(:work_item, project: project) }
|
||||||
|
let_it_be(:incident) { build(:work_item, :incident, project: project) }
|
||||||
let_it_be(:task1) { build(:work_item, :task, project: project) }
|
let_it_be(:task1) { build(:work_item, :task, project: project) }
|
||||||
let_it_be(:task2) { build(:work_item, :task, project: project) }
|
let_it_be(:task2) { build(:work_item, :task, project: project) }
|
||||||
|
|
||||||
it 'is valid if not-task parent has task child' do
|
it 'is valid if issue parent has task child' do
|
||||||
expect(build(:parent_link, work_item: task1, work_item_parent: issue)).to be_valid
|
expect(build(:parent_link, work_item: task1, work_item_parent: issue)).to be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'is valid if incident parent has task child' do
|
||||||
|
expect(build(:parent_link, work_item: task1, work_item_parent: incident)).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
it 'is not valid if child is not task' do
|
it 'is not valid if child is not task' do
|
||||||
link = build(:parent_link, work_item: issue)
|
link = build(:parent_link, work_item: issue)
|
||||||
|
|
||||||
expect(link).not_to be_valid
|
expect(link).not_to be_valid
|
||||||
expect(link.errors[:work_item]).to include('Only Task can be assigned as a child in hierarchy.')
|
expect(link.errors[:work_item]).to include('only Task can be assigned as a child in hierarchy.')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'is not valid if parent is task' do
|
it 'is not valid if parent is task' do
|
||||||
link = build(:parent_link, work_item_parent: task1)
|
link = build(:parent_link, work_item_parent: task1)
|
||||||
|
|
||||||
expect(link).not_to be_valid
|
expect(link).not_to be_valid
|
||||||
expect(link.errors[:work_item_parent]).to include('Only Issue can be parent of Task.')
|
expect(link.errors[:work_item_parent]).to include('only Issue and Incident can be parent of Task.')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'is not valid if parent is in other project' do
|
it 'is not valid if parent is in other project' do
|
||||||
link = build(:parent_link, work_item_parent: task1, work_item: build(:work_item))
|
link = build(:parent_link, work_item_parent: task1, work_item: build(:work_item))
|
||||||
|
|
||||||
expect(link).not_to be_valid
|
expect(link).not_to be_valid
|
||||||
expect(link.errors[:work_item_parent]).to include('Parent must be in the same project as child.')
|
expect(link.errors[:work_item_parent]).to include('parent must be in the same project as child.')
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when parent already has maximum number of links' do
|
context 'when parent already has maximum number of links' do
|
||||||
|
@ -54,7 +59,7 @@ RSpec.describe WorkItems::ParentLink do
|
||||||
link2 = build(:parent_link, work_item_parent: issue, work_item: task2)
|
link2 = build(:parent_link, work_item_parent: issue, work_item: task2)
|
||||||
|
|
||||||
expect(link2).not_to be_valid
|
expect(link2).not_to be_valid
|
||||||
expect(link2.errors[:work_item_parent]).to include('Parent already has maximum number of children.')
|
expect(link2.errors[:work_item_parent]).to include('parent already has maximum number of children.')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'existing link is still valid' do
|
it 'existing link is still valid' do
|
||||||
|
|
|
@ -24,9 +24,9 @@ RSpec.describe WorkItems::Widgets::Hierarchy do
|
||||||
|
|
||||||
it { is_expected.to eq parent_link.work_item_parent }
|
it { is_expected.to eq parent_link.work_item_parent }
|
||||||
|
|
||||||
context 'when work_items_hierarchy flag is disabled' do
|
context 'when work_items flag is disabled' do
|
||||||
before do
|
before do
|
||||||
stub_feature_flags(work_items_hierarchy: false)
|
stub_feature_flags(work_items: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it { is_expected.to be_nil }
|
it { is_expected.to be_nil }
|
||||||
|
@ -41,9 +41,9 @@ RSpec.describe WorkItems::Widgets::Hierarchy do
|
||||||
|
|
||||||
it { is_expected.to match_array([parent_link1.work_item, parent_link2.work_item]) }
|
it { is_expected.to match_array([parent_link1.work_item, parent_link2.work_item]) }
|
||||||
|
|
||||||
context 'when work_items_hierarchy flag is disabled' do
|
context 'when work_items flag is disabled' do
|
||||||
before do
|
before do
|
||||||
stub_feature_flags(work_items_hierarchy: false)
|
stub_feature_flags(work_items: false)
|
||||||
end
|
end
|
||||||
|
|
||||||
it { is_expected.to be_empty }
|
it { is_expected.to be_empty }
|
||||||
|
|
|
@ -120,7 +120,8 @@ RSpec.describe 'Create a work item' do
|
||||||
it 'returns error' do
|
it 'returns error' do
|
||||||
post_graphql_mutation(mutation, current_user: current_user)
|
post_graphql_mutation(mutation, current_user: current_user)
|
||||||
|
|
||||||
expect(mutation_response['errors']).to contain_exactly(/cannot be added: Only Issue can be parent of Task./)
|
expect(mutation_response['errors'])
|
||||||
|
.to contain_exactly(/cannot be added: only Issue and Incident can be parent of Task./)
|
||||||
expect(mutation_response['workItem']).to be_nil
|
expect(mutation_response['workItem']).to be_nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -170,7 +170,7 @@ RSpec.describe 'Update a work item' do
|
||||||
let_it_be(:invalid_parent) { create(:work_item, :task, project: project) }
|
let_it_be(:invalid_parent) { create(:work_item, :task, project: project) }
|
||||||
|
|
||||||
context 'when parent work item type is invalid' do
|
context 'when parent work item type is invalid' do
|
||||||
let(:error) { "#{work_item.to_reference} cannot be added: Only Issue can be parent of Task." }
|
let(:error) { "#{work_item.to_reference} cannot be added: only Issue and Incident can be parent of Task." }
|
||||||
let(:input) do
|
let(:input) do
|
||||||
{ 'hierarchyWidget' => { 'parentId' => invalid_parent.to_global_id.to_s }, 'title' => 'new title' }
|
{ 'hierarchyWidget' => { 'parentId' => invalid_parent.to_global_id.to_s }, 'title' => 'new title' }
|
||||||
end
|
end
|
||||||
|
@ -281,7 +281,7 @@ RSpec.describe 'Update a work item' do
|
||||||
|
|
||||||
let(:input) { { 'hierarchyWidget' => { 'childrenIds' => children_ids } } }
|
let(:input) { { 'hierarchyWidget' => { 'childrenIds' => children_ids } } }
|
||||||
let(:error) do
|
let(:error) do
|
||||||
"#{invalid_child.to_reference} cannot be added: Only Task can be assigned as a child in hierarchy."
|
"#{invalid_child.to_reference} cannot be added: only Task can be assigned as a child in hierarchy."
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when child work item type is invalid' do
|
context 'when child work item type is invalid' do
|
||||||
|
|
|
@ -68,7 +68,7 @@ RSpec.describe WorkItems::CreateAndLinkService do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns a link creation error message' do
|
it 'returns a link creation error message' do
|
||||||
expect(service_result.errors).to contain_exactly(/Only Issue can be parent of Task./)
|
expect(service_result.errors).to contain_exactly(/only Issue and Incident can be parent of Task./)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -148,7 +148,7 @@ RSpec.describe WorkItems::CreateService do
|
||||||
expect { service_result }.not_to change(WorkItem, :count)
|
expect { service_result }.not_to change(WorkItem, :count)
|
||||||
|
|
||||||
expect(service_result[:status]).to be(:error)
|
expect(service_result[:status]).to be(:error)
|
||||||
expect(service_result[:message]).to match(/Only Issue can be parent of Task./)
|
expect(service_result[:message]).to match(/only Issue and Incident can be parent of Task./)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -102,8 +102,8 @@ RSpec.describe WorkItems::ParentLinks::CreateService do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns error status' do
|
it 'returns error status' do
|
||||||
error = "#{issue.to_reference} cannot be added: Only Task can be assigned as a child in hierarchy.. " \
|
error = "#{issue.to_reference} cannot be added: only Task can be assigned as a child in hierarchy.. " \
|
||||||
"#{other_project_task.to_reference} cannot be added: Parent must be in the same project as child."
|
"#{other_project_task.to_reference} cannot be added: parent must be in the same project as child."
|
||||||
|
|
||||||
is_expected.to eq(service_error(error, http_status: 422))
|
is_expected.to eq(service_error(error, http_status: 422))
|
||||||
end
|
end
|
||||||
|
@ -115,7 +115,7 @@ RSpec.describe WorkItems::ParentLinks::CreateService do
|
||||||
let(:params) { { target_issuable: task1 } }
|
let(:params) { { target_issuable: task1 } }
|
||||||
|
|
||||||
it 'returns error status' do
|
it 'returns error status' do
|
||||||
error = "#{task1.to_reference} cannot be added: Only Issue can be parent of Task."
|
error = "#{task1.to_reference} cannot be added: only Issue and Incident can be parent of Task."
|
||||||
|
|
||||||
is_expected.to eq(service_error(error, http_status: 422))
|
is_expected.to eq(service_error(error, http_status: 422))
|
||||||
end
|
end
|
||||||
|
@ -129,7 +129,7 @@ RSpec.describe WorkItems::ParentLinks::CreateService do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns error status' do
|
it 'returns error status' do
|
||||||
error = "#{task2.to_reference} cannot be added: Parent already has maximum number of children."
|
error = "#{task2.to_reference} cannot be added: parent already has maximum number of children."
|
||||||
|
|
||||||
is_expected.to eq(service_error(error, http_status: 422))
|
is_expected.to eq(service_error(error, http_status: 422))
|
||||||
end
|
end
|
||||||
|
|
|
@ -165,7 +165,7 @@ RSpec.describe WorkItems::UpdateService do
|
||||||
it 'returns error status' do
|
it 'returns error status' do
|
||||||
expect(subject[:status]).to be(:error)
|
expect(subject[:status]).to be(:error)
|
||||||
expect(subject[:message])
|
expect(subject[:message])
|
||||||
.to match("#{child_work_item.to_reference} cannot be added: Only Task can be assigned as a child in hierarchy.")
|
.to match("#{child_work_item.to_reference} cannot be added: only Task can be assigned as a child in hierarchy.")
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not update work item attributes' do
|
it 'does not update work item attributes' do
|
||||||
|
|
|
@ -85,7 +85,7 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
|
||||||
|
|
||||||
it_behaves_like 'raises a WidgetError' do
|
it_behaves_like 'raises a WidgetError' do
|
||||||
let(:message) do
|
let(:message) do
|
||||||
"#{child_issue.to_reference} cannot be added: Only Task can be assigned as a child in hierarchy."
|
"#{child_issue.to_reference} cannot be added: only Task can be assigned as a child in hierarchy."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -149,7 +149,9 @@ RSpec.describe WorkItems::Widgets::HierarchyService::UpdateService do
|
||||||
let(:params) {{ parent: parent_task } }
|
let(:params) {{ parent: parent_task } }
|
||||||
|
|
||||||
it_behaves_like 'raises a WidgetError' do
|
it_behaves_like 'raises a WidgetError' do
|
||||||
let(:message) { "#{work_item.to_reference} cannot be added: Only Issue can be parent of Task." }
|
let(:message) do
|
||||||
|
"#{work_item.to_reference} cannot be added: only Issue and Incident can be parent of Task."
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
RSpec.shared_examples 'counter that does not track the event' do
|
||||||
|
it 'does not track the event' do
|
||||||
|
expect { 3.times { track_event } }.to not_change {
|
||||||
|
Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(
|
||||||
|
event_names: event_name,
|
||||||
|
start_date: 2.weeks.ago,
|
||||||
|
end_date: 2.weeks.from_now
|
||||||
|
)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
RSpec.shared_examples 'work item unique counter' do
|
||||||
|
context 'when track_work_items_activity FF is enabled' do
|
||||||
|
it 'tracks a unique event only once' do
|
||||||
|
expect { 3.times { track_event } }.to change {
|
||||||
|
Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(
|
||||||
|
event_names: event_name,
|
||||||
|
start_date: 2.weeks.ago,
|
||||||
|
end_date: 2.weeks.from_now
|
||||||
|
)
|
||||||
|
}.by(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when author is nil' do
|
||||||
|
let(:user) { nil }
|
||||||
|
|
||||||
|
it_behaves_like 'counter that does not track the event'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when track_work_items_activity FF is disabled' do
|
||||||
|
before do
|
||||||
|
stub_feature_flags(track_work_items_activity: false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'counter that does not track the event'
|
||||||
|
end
|
||||||
|
end
|
Binary file not shown.
After Width: | Height: | Size: 6.1 KiB |
|
@ -2,6 +2,8 @@ package badgateway
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
_ "embed"
|
||||||
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"io"
|
"io"
|
||||||
|
@ -12,6 +14,9 @@ import (
|
||||||
"gitlab.com/gitlab-org/gitlab/workhorse/internal/log"
|
"gitlab.com/gitlab-org/gitlab/workhorse/internal/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
//go:embed embed/gitlab-logo-500.png
|
||||||
|
var gitlabLogo []byte
|
||||||
|
|
||||||
// Error is a custom error for pretty Sentry 'issues'
|
// Error is a custom error for pretty Sentry 'issues'
|
||||||
type sentryError struct{ error }
|
type sentryError struct{ error }
|
||||||
|
|
||||||
|
@ -68,9 +73,10 @@ func (t *roundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||||
|
|
||||||
func developmentModeResponse(err error) (body string, contentType string) {
|
func developmentModeResponse(err error) (body string, contentType string) {
|
||||||
data := TemplateData{
|
data := TemplateData{
|
||||||
Time: time.Now().Format("15:04:05"),
|
Time: time.Now().Format("15:04:05"),
|
||||||
Error: err.Error(),
|
Error: err.Error(),
|
||||||
ReloadSeconds: 5,
|
ReloadSeconds: 5,
|
||||||
|
Base64EncodedGitLabLogo: base64.StdEncoding.EncodeToString(gitlabLogo),
|
||||||
}
|
}
|
||||||
|
|
||||||
buf := &bytes.Buffer{}
|
buf := &bytes.Buffer{}
|
||||||
|
@ -82,28 +88,44 @@ func developmentModeResponse(err error) (body string, contentType string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type TemplateData struct {
|
type TemplateData struct {
|
||||||
Time string
|
Time string
|
||||||
Error string
|
Error string
|
||||||
ReloadSeconds int
|
ReloadSeconds int
|
||||||
|
Base64EncodedGitLabLogo string
|
||||||
}
|
}
|
||||||
|
|
||||||
var developmentErrorTemplate = template.Must(template.New("error502").Parse(`
|
var developmentErrorTemplate = template.Must(template.New("error502").Parse(`
|
||||||
<html>
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>502: GitLab is not responding</title>
|
<title>Waiting for GitLab to boot</title>
|
||||||
<script>
|
|
||||||
window.setTimeout(function() { location.reload() }, {{.ReloadSeconds}} * 1000)
|
|
||||||
</script>
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<h1>502</h1>
|
<div style="text-align: center; font-family: Source Sans Pro, sans-serif">
|
||||||
<p>GitLab is not responding. The error was:</p>
|
<img style="padding: 60px 0" src="data:image/png;base64,{{.Base64EncodedGitLabLogo}}" alt="GitLab" />
|
||||||
|
|
||||||
<pre>{{.Error}}</pre>
|
<h1>Waiting for GitLab to boot</h1>
|
||||||
|
|
||||||
<p>If you just started GDK it can take 60-300 seconds before GitLab has finished booting. This page will automatically reload every {{.ReloadSeconds}} seconds.</p>
|
<pre>{{.Error}}</pre>
|
||||||
<footer>Generated by gitlab-workhorse running in development mode at {{.Time}}.</footer>
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<p>It can take 60-180 seconds for GitLab to boot completely.</p>
|
||||||
|
<p>This page will automatically reload every {{.ReloadSeconds}} seconds.</p>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<footer>
|
||||||
|
<p>Generated by gitlab-workhorse running in development mode at {{.Time}}.</p>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
window.setTimeout(function() { location.reload(); }, {{.ReloadSeconds}} * 1000)
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
`))
|
`))
|
||||||
|
|
Loading…
Reference in New Issue