summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/ci/reports.gitlab-ci.yml2
-rw-r--r--app/controllers/groups/settings/ci_cd_controller.rb2
-rw-r--r--app/controllers/projects/settings/ci_cd_controller.rb2
-rw-r--r--app/finders/award_emojis_finder.rb2
-rw-r--r--app/models/concerns/usage_statistics.rb13
-rw-r--r--app/models/discussion.rb1
-rw-r--r--app/models/note.rb9
-rw-r--r--app/models/zoom_meeting.rb8
-rw-r--r--app/policies/note_policy.rb41
-rw-r--r--app/services/users/build_service.rb10
-rw-r--r--app/views/ci/variables/_index.html.haml2
-rw-r--r--changelogs/unreleased/210335-fix-handling-of-numeric-emoji-names.yml5
-rw-r--r--changelogs/unreleased/ci-variables-ui-turn-on-ff.yml5
-rw-r--r--changelogs/unreleased/mo-use-new-code-quality-image.yml5
-rw-r--r--doc/development/contributing/issue_workflow.md17
-rw-r--r--doc/topics/autodevops/index.md2
-rw-r--r--doc/update/README.md1
-rw-r--r--doc/user/group/epics/index.md46
-rw-r--r--doc/user/markdown.md7
-rw-r--r--doc/user/project/issues/design_management.md36
-rw-r--r--doc/user/project/issues/img/issue_health_status_v12_9.pngbin0 -> 10509 bytes
-rw-r--r--doc/user/project/issues/index.md34
-rw-r--r--doc/user/project/merge_requests/code_quality.md12
-rw-r--r--lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml2
-rw-r--r--lib/gitlab/sidekiq_middleware/server_metrics.rb6
-rw-r--r--spec/factories/notes.rb4
-rw-r--r--spec/factories/pages_domains.rb32
-rw-r--r--spec/factories/serverless/domain_cluster.rb32
-rw-r--r--spec/factories/snippets.rb1
-rw-r--r--spec/features/projects/pages_spec.rb36
-rw-r--r--spec/finders/award_emojis_finder_spec.rb5
-rw-r--r--spec/fixtures/ssl_certificate.pem12
-rw-r--r--spec/fixtures/ssl_key.pem16
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb2
-rw-r--r--spec/lib/gitlab/sidekiq_middleware_spec.rb20
-rw-r--r--spec/lib/gitlab/usage_data_spec.rb16
-rw-r--r--spec/models/concerns/usage_statistics_spec.rb52
-rw-r--r--spec/models/note_spec.rb99
-rw-r--r--spec/models/pages_domain_spec.rb9
-rw-r--r--spec/models/zoom_meeting_spec.rb47
-rw-r--r--spec/policies/note_policy_spec.rb95
-rw-r--r--spec/workers/pages_domain_ssl_renewal_cron_worker_spec.rb5
42 files changed, 497 insertions, 256 deletions
diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml
index 6437f40f29f..f381c423f5d 100644
--- a/.gitlab/ci/reports.gitlab-ci.yml
+++ b/.gitlab/ci/reports.gitlab-ci.yml
@@ -20,7 +20,7 @@ code_quality:
variables:
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
- CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/security-products/codequality:0.85.9"
+ CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.85.9"
script:
- |
if ! docker info &>/dev/null; then
diff --git a/app/controllers/groups/settings/ci_cd_controller.rb b/app/controllers/groups/settings/ci_cd_controller.rb
index 3d347429398..ffa3f2c3364 100644
--- a/app/controllers/groups/settings/ci_cd_controller.rb
+++ b/app/controllers/groups/settings/ci_cd_controller.rb
@@ -7,7 +7,7 @@ module Groups
before_action :authorize_admin_group!
before_action :authorize_update_max_artifacts_size!, only: [:update]
before_action do
- push_frontend_feature_flag(:new_variables_ui, @group, default_enabled: true)
+ push_frontend_feature_flag(:new_variables_ui, @group)
end
before_action :define_variables, only: [:show, :create_deploy_token]
diff --git a/app/controllers/projects/settings/ci_cd_controller.rb b/app/controllers/projects/settings/ci_cd_controller.rb
index 43c798bfc6e..aac6ecb07e4 100644
--- a/app/controllers/projects/settings/ci_cd_controller.rb
+++ b/app/controllers/projects/settings/ci_cd_controller.rb
@@ -6,7 +6,7 @@ module Projects
before_action :authorize_admin_pipeline!
before_action :define_variables
before_action do
- push_frontend_feature_flag(:new_variables_ui, @project, default_enabled: true)
+ push_frontend_feature_flag(:new_variables_ui, @project)
end
def show
diff --git a/app/finders/award_emojis_finder.rb b/app/finders/award_emojis_finder.rb
index 7320e035409..7882beb64bf 100644
--- a/app/finders/award_emojis_finder.rb
+++ b/app/finders/award_emojis_finder.rb
@@ -41,7 +41,7 @@ class AwardEmojisFinder
def validate_name_param
return unless params[:name]
- raise ArgumentError, 'Invalid name param' unless params[:name].in?(Gitlab::Emoji.emojis_names)
+ raise ArgumentError, 'Invalid name param' unless params[:name].to_s.in?(Gitlab::Emoji.emojis_names)
end
def validate_awarded_by_param
diff --git a/app/models/concerns/usage_statistics.rb b/app/models/concerns/usage_statistics.rb
new file mode 100644
index 00000000000..d6cafcb22b1
--- /dev/null
+++ b/app/models/concerns/usage_statistics.rb
@@ -0,0 +1,13 @@
+# frozen_string_literal: true
+
+module UsageStatistics
+ extend ActiveSupport::Concern
+
+ class_methods do
+ def distinct_count_by(column = nil, fallback = -1)
+ distinct.count(column)
+ rescue ActiveRecord::StatementInvalid
+ fallback
+ end
+ end
+end
diff --git a/app/models/discussion.rb b/app/models/discussion.rb
index 5c45c5fb7fb..c07078c03dd 100644
--- a/app/models/discussion.rb
+++ b/app/models/discussion.rb
@@ -14,6 +14,7 @@ class Discussion
:author,
:noteable,
:commit_id,
+ :confidential?,
:for_commit?,
:for_merge_request?,
:noteable_ability_name,
diff --git a/app/models/note.rb b/app/models/note.rb
index 670a981a78f..251a75e6025 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -320,6 +320,13 @@ class Note < ApplicationRecord
super(noteable_type.to_s.classify.constantize.base_class.to_s)
end
+ def noteable_assignee_or_author?(user)
+ return false unless user
+ return noteable.assignee_or_author?(user) if [MergeRequest, Issue].include?(noteable.class)
+
+ noteable.author_id == user.id
+ end
+
def special_role=(role)
raise "Role is undefined, #{role} not found in #{SpecialRole.values}" unless SpecialRole.value?(role)
@@ -337,7 +344,7 @@ class Note < ApplicationRecord
end
def confidential?
- noteable.try(:confidential?)
+ confidential || noteable.try(:confidential?)
end
def editable?
diff --git a/app/models/zoom_meeting.rb b/app/models/zoom_meeting.rb
index fe2f351018c..f83aa93b69a 100644
--- a/app/models/zoom_meeting.rb
+++ b/app/models/zoom_meeting.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class ZoomMeeting < ApplicationRecord
+ include UsageStatistics
+
belongs_to :project, optional: false
belongs_to :issue, optional: false
@@ -23,10 +25,4 @@ class ZoomMeeting < ApplicationRecord
def self.canonical_meeting_url(issue)
canonical_meeting(issue)&.url
end
-
- def self.distinct_count_by(column = nil, fallback = -1)
- distinct.count(column)
- rescue ActiveRecord::StatementInvalid
- fallback
- end
end
diff --git a/app/policies/note_policy.rb b/app/policies/note_policy.rb
index 54dc70b08cb..32be89439ba 100644
--- a/app/policies/note_policy.rb
+++ b/app/policies/note_policy.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
class NotePolicy < BasePolicy
+ include Gitlab::Utils::StrongMemoize
+
delegate { @subject.resource_parent }
delegate { @subject.noteable if DeclarativePolicy.has_policy?(@subject.noteable) }
@@ -13,6 +15,12 @@ class NotePolicy < BasePolicy
condition(:is_visible) { @subject.system_note_with_references_visible_for?(@user) }
+ condition(:confidential, scope: :subject) { @subject.confidential? }
+
+ condition(:can_read_confidential) do
+ access_level >= Gitlab::Access::REPORTER || @subject.noteable_assignee_or_author?(@user)
+ end
+
rule { ~editable }.prevent :admin_note
# If user can't read the issue/MR/etc then they should not be allowed to do anything to their own notes
@@ -39,4 +47,37 @@ class NotePolicy < BasePolicy
rule { is_noteable_author }.policy do
enable :resolve_note
end
+
+ rule { confidential & ~can_read_confidential }.policy do
+ prevent :read_note
+ prevent :admin_note
+ prevent :resolve_note
+ prevent :award_emoji
+ end
+
+ def parent_namespace
+ strong_memoize(:parent_namespace) do
+ next if @subject.is_a?(PersonalSnippet)
+ next @subject.noteable.group if @subject.noteable&.is_a?(Epic)
+
+ @subject.project
+ end
+ end
+
+ def access_level
+ return -1 if @user.nil?
+ return -1 unless parent_namespace
+
+ lookup_access_level!
+ end
+
+ def lookup_access_level!
+ return ::Gitlab::Access::REPORTER if alert_bot?
+
+ if parent_namespace.is_a?(Project)
+ parent_namespace.team.max_member_access(@user.id)
+ else
+ parent_namespace.max_member_access_for_user(@user)
+ end
+ end
end
diff --git a/app/services/users/build_service.rb b/app/services/users/build_service.rb
index 56631bf2785..4c3ae2d204d 100644
--- a/app/services/users/build_service.rb
+++ b/app/services/users/build_service.rb
@@ -28,9 +28,7 @@ module Users
end
end
- unless identity_params.empty?
- user.identities.build(identity_params)
- end
+ build_identity(user)
user
end
@@ -41,6 +39,12 @@ module Users
[:extern_uid, :provider]
end
+ def build_identity(user)
+ return if identity_params.empty?
+
+ user.identities.build(identity_params)
+ end
+
def can_create_user?
(current_user.nil? && Gitlab::CurrentSettings.allow_signup?) || current_user&.admin?
end
diff --git a/app/views/ci/variables/_index.html.haml b/app/views/ci/variables/_index.html.haml
index aadb2c62d83..f11c730eba6 100644
--- a/app/views/ci/variables/_index.html.haml
+++ b/app/views/ci/variables/_index.html.haml
@@ -5,7 +5,7 @@
- link_start = '<a href="%{url}">'.html_safe % { url: help_page_path('ci/variables/README', anchor: 'protected-variables') }
= s_('Environment variables are configured by your administrator to be %{link_start}protected%{link_end} by default').html_safe % { link_start: link_start, link_end: '</a>'.html_safe }
-- if Feature.enabled?(:new_variables_ui, @project || @group, default_enabled: true)
+- if Feature.enabled?(:new_variables_ui, @project || @group)
- is_group = !@group.nil?
#js-ci-project-variables{ data: { endpoint: save_endpoint, project_id: @project&.id || '', group: is_group.to_s, maskable_regex: ci_variable_maskable_regex} }
diff --git a/changelogs/unreleased/210335-fix-handling-of-numeric-emoji-names.yml b/changelogs/unreleased/210335-fix-handling-of-numeric-emoji-names.yml
new file mode 100644
index 00000000000..5686fb2a7a4
--- /dev/null
+++ b/changelogs/unreleased/210335-fix-handling-of-numeric-emoji-names.yml
@@ -0,0 +1,5 @@
+---
+title: Fix backend validation of numeric emoji names
+merge_request: 27101
+author:
+type: fixed
diff --git a/changelogs/unreleased/ci-variables-ui-turn-on-ff.yml b/changelogs/unreleased/ci-variables-ui-turn-on-ff.yml
deleted file mode 100644
index acacf115621..00000000000
--- a/changelogs/unreleased/ci-variables-ui-turn-on-ff.yml
+++ /dev/null
@@ -1,5 +0,0 @@
----
-title: Set new_variables_ui feature flag default value to true
-merge_request: 25731
-author:
-type: added
diff --git a/changelogs/unreleased/mo-use-new-code-quality-image.yml b/changelogs/unreleased/mo-use-new-code-quality-image.yml
new file mode 100644
index 00000000000..c95a5abc1e3
--- /dev/null
+++ b/changelogs/unreleased/mo-use-new-code-quality-image.yml
@@ -0,0 +1,5 @@
+---
+title: Use new codequality docker image from ci-cd group
+merge_request: 27098
+author:
+type: other
diff --git a/doc/development/contributing/issue_workflow.md b/doc/development/contributing/issue_workflow.md
index cc504d51cab..4d84e921acf 100644
--- a/doc/development/contributing/issue_workflow.md
+++ b/doc/development/contributing/issue_workflow.md
@@ -287,12 +287,12 @@ This label documents the planned timeline & urgency which is used to measure aga
Severity labels help us clearly communicate the impact of a ~bug on users.
There can be multiple facets of the impact. The below is a guideline.
-| Label | Meaning | Functionality | Affected Users | GitLab.com Availability | Performance Degradation |
-|-------|-------------------|-------------------------------------------------------|----------------------------------|----------------------------------------------------|------------------------------|
-| ~S1 | Blocker | Unusable feature with no workaround, user is blocked | Impacts 50% or more of users | Outage, Significant impact on all of GitLab.com | |
-| ~S2 | Critical Severity | Broken Feature, workaround too complex & unacceptable | Impacts between 25%-50% of users | Significant impact on large portions of GitLab.com | Degradation is guaranteed to occur in the near future |
-| ~S3 | Major Severity | Broken feature with an acceptable workaround | Impacts up to 25% of users | Limited impact on important portions of GitLab.com | Degradation is likely to occur in the near future |
-| ~S4 | Low Severity | Functionality inconvenience or cosmetic issue | Impacts less than 5% of users | Minor impact on GitLab.com | Degradation _may_ occur but it's not likely |
+| Label | Meaning | Functionality | Affected Users | GitLab.com Availability | Performance Degradation | API/Web Response time[^1] |
+|-------|-------------------|-------------------------------------------------------|----------------------------------|----------------------------------------------------|-------------------------------------------------------|----------------------------|
+| ~S1 | Blocker | Unusable feature with no workaround, user is blocked | Impacts 50% or more of users | Outage, Significant impact on all of GitLab.com | | Above 9000ms to timing out |
+| ~S2 | Critical Severity | Broken Feature, workaround too complex & unacceptable | Impacts between 25%-50% of users | Significant impact on large portions of GitLab.com | Degradation is guaranteed to occur in the near future | Between 2000ms and 9000ms |
+| ~S3 | Major Severity | Broken feature with an acceptable workaround | Impacts up to 25% of users | Limited impact on important portions of GitLab.com | Degradation is likely to occur in the near future | Between 1000ms and 2000ms |
+| ~S4 | Low Severity | Functionality inconvenience or cosmetic issue | Impacts less than 5% of users | Minor impact on GitLab.com | Degradation _may_ occur but it's not likely | Between 500ms and 1000ms |
If a bug seems to fall between two severity labels, assign it to the higher-severity label.
@@ -503,3 +503,8 @@ to be involved in some capacity when work begins on the follow-up issue.
---
[Return to Contributing documentation](index.md)
+
+[^1]: Our current response time standard is based on the TTFB P90 results of the
+ GitLab Performance Tool (GPT) being run against the 10k-user reference
+ environment. This run happens nightly and results are outputted to the
+ [wiki on the GPT project.](https://gitlab.com/gitlab-org/quality/performance/-/wikis/Benchmarks/Latest/10k)
diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md
index 50b2fbeaa60..57cceba8c0d 100644
--- a/doc/topics/autodevops/index.md
+++ b/doc/topics/autodevops/index.md
@@ -420,7 +420,7 @@ tests, it's up to you to add them.
### Auto Code Quality **(STARTER)**
Auto Code Quality uses the
-[Code Quality image](https://gitlab.com/gitlab-org/security-products/codequality) to run
+[Code Quality image](https://gitlab.com/gitlab-org/ci-cd/codequality) to run
static analysis and other code checks on the current code. The report is
created, and is uploaded as an artifact which you can later download and check
out.
diff --git a/doc/update/README.md b/doc/update/README.md
index 3ebe1d38d0f..93879efb19e 100644
--- a/doc/update/README.md
+++ b/doc/update/README.md
@@ -50,6 +50,7 @@ However, for this to work there are the following requirements:
migrations](../development/post_deployment_migrations.md) (included in
zero downtime update steps below).
- You are using PostgreSQL. Starting from GitLab 12.1, MySQL is not supported.
+- Multi-node GitLab instance. Single-node instances may experience brief interruptions as services restart.
Most of the time you can safely upgrade from a patch release to the next minor
release if the patch release is not the latest. For example, upgrading from
diff --git a/doc/user/group/epics/index.md b/doc/user/group/epics/index.md
index eae989b220b..861054c2a0a 100644
--- a/doc/user/group/epics/index.md
+++ b/doc/user/group/epics/index.md
@@ -23,7 +23,7 @@ graph TD
Parent_epic --> Issue1
Parent_epic --> Child_epic
Child_epic --> Issue2
-````
+```
## Use cases
@@ -184,6 +184,8 @@ have a [start or due date](#start-date-and-due-date), a
![Child epics roadmap](img/epic_view_roadmap_v12_9.png)
+---
+
## Reordering issues and child epics
> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/9367) in GitLab 12.5.
@@ -240,6 +242,8 @@ You can always reopen it using the reopen button.
![reopen epic - button](img/button_reopen_epic.png)
+---
+
### Using quick actions
You can close or reopen an epic using [Quick actions](../../project/quick_actions.md)
@@ -251,9 +255,12 @@ link in the issue sidebar.
![containing epic](img/containing_epic.png)
+---
+
## Promoting an issue to an epic
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/3777) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.6.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/3777) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 11.6.
+> - In [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/issues/37081), it was moved to the Premium tier.
If you have [permissions](../../permissions.md) to close an issue and create an
epic in the parent group, you can promote an issue to an epic with the `/promote`
@@ -276,10 +283,11 @@ The following issue metadata will be copied to the epic:
## Searching for an epic from epics list page
-> Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.5.
+> - Introduced in [GitLab Ultimate](https://about.gitlab.com/pricing/) 10.5.
+> - In [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/issues/37081), it was moved to the Premium tier.
You can search for an epic from the list of epics using filtered search bar (similar to
-that of Issues and Merge requests) based on following parameters:
+that of Issues and Merge Requests) based on following parameters:
- Title or description
- Author name / username
@@ -287,22 +295,26 @@ that of Issues and Merge requests) based on following parameters:
![epics search](img/epics_search.png)
-To search, go to the list of epics and click on the field **Search or filter results...**.
+To search, go to the list of epics and click on the field **Search or filter results**.
It will display a dropdown menu, from which you can add an author. You can also enter plain
text to search by epic title or description. When done, press <kbd>Enter</kbd> on your
keyboard to filter the list.
You can also sort epics list by:
-- **Created date**
-- **Last updated**
-- **Start date**
-- **Due date**
+- Created date
+- Last updated
+- Start date
+- Due date
-Each option contains a button that can toggle the order between **ascending** and **descending**. The sort option and order will be persisted to be used wherever epics are browsed including the [roadmap](../roadmap/index.md).
+Each option contains a button that can toggle the order between **Ascending** and **Descending**.
+The sort option and order is saved and used wherever you browse epics, including the
+[Roadmap](../roadmap/index.md).
![epics sort](img/epics_sort.png)
+---
+
## Permissions
If you have access to view an epic and have access to view an issue already
@@ -315,7 +327,7 @@ Note that for a given group, the visibility of all projects must be the same as
the group, or less restrictive. That means if you have access to a group's epic,
then you already have access to its projects' issues.
-You may also consult the [group permissions table](../../permissions.md#group-members-permissions).
+You can also consult the [group permissions table](../../permissions.md#group-members-permissions).
## Thread
@@ -323,20 +335,20 @@ You may also consult the [group permissions table](../../permissions.md#group-me
These text fields also fully support
[GitLab Flavored Markdown](../../markdown.md#gitlab-flavored-markdown-gfm).
-## Comment, or start a thread
+## Comment or start a thread
-Once you wrote your comment, you can either:
+Once you write your comment, you can either:
-- Click "Comment" and your comment will be published.
-- Click "Start thread": start a thread within that epic's discussion to discuss specific points.
+- Click **Comment**, and your comment will be published.
+- Click **Start thread**, and you will start a thread within that epic's discussion.
## Award emoji
-- You can [award an emoji](../../award_emojis.md) to that epic or its comments.
+You can [award an emoji](../../award_emojis.md) to that epic or its comments.
## Notifications
-- [Receive notifications](../../profile/notifications.md) for epic events.
+You can [turn on notifications](../../profile/notifications.md) to be alerted about epic events.
<!-- ## Troubleshooting
diff --git a/doc/user/markdown.md b/doc/user/markdown.md
index 72570848a61..29163f98fb4 100644
--- a/doc/user/markdown.md
+++ b/doc/user/markdown.md
@@ -408,7 +408,6 @@ GFM will recognize the following:
| merge request | `!123` | `namespace/project!123` | `project!123` |
| snippet | `$123` | `namespace/project$123` | `project$123` |
| epic **(ULTIMATE)** | `&123` | `group1/subgroup&123` | |
-| design **(PREMIUM)** | `#123[file.jpg]` or `#123["file.png"]` | `group1/subgroup#123[file.png]` | `project#123[file.png]` |
| label by ID | `~123` | `namespace/project~123` | `project~123` |
| one-word label by name | `~bug` | `namespace/project~bug` | `project~bug` |
| multi-word label by name | `~"feature request"` | `namespace/project~"feature request"` | `project~"feature request"` |
@@ -421,6 +420,12 @@ GFM will recognize the following:
| repository file references | `[README](doc/README)` | | |
| repository file line references | `[README](doc/README#L13)` | | |
+In addition to this, links to some objects are also recognized and formatted. Some examples of these are:
+
+- Comments on issues: `"https://gitlab.com/gitlab-org/gitlab/-/issues/1234#note_101075757"`, which will be rendered as `#1234 (note1)`
+- The issues designs tab: `"https://gitlab.com/gitlab-org/gitlab/issues/1234/designs"`, which will be rendered as `#1234 (designs)`.
+ **(PREMIUM)**
+
### Task lists
> If this is not rendered correctly, [view it in GitLab itself](https://gitlab.com/gitlab-org/gitlab/blob/master/doc/user/markdown.md#task-lists).
diff --git a/doc/user/project/issues/design_management.md b/doc/user/project/issues/design_management.md
index ba9796dc785..add466a91b1 100644
--- a/doc/user/project/issues/design_management.md
+++ b/doc/user/project/issues/design_management.md
@@ -39,13 +39,6 @@ Design Management requires that projects are using
If the requirements are not met, the **Designs** tab displays a message to the user.
-### Feature Flags
-
-- Reference Parsing
-
- Designs support short references in Markdown, but this needs to be enabled by setting
- the `:design_management_reference_filter_gfm_pipeline` feature flag.
-
## Supported files
Files uploaded must have a file extension of either `png`, `jpg`, `jpeg`,
@@ -169,32 +162,3 @@ Different discussions have different badge numbers:
From GitLab 12.5 on, new annotations will be outputted to the issue activity,
so that everyone involved can participate in the discussion.
-
-## References
-
-GitLab Flavored Markdown supports references to designs. The syntax for this is:
-
- `#123[file.jpg]` - the issue reference, with the filename in square braces
-
-File names may contain a variety of odd characters, so two escaping mechanisms are supported:
-
-### Quoting
-
-File names may be quoted with double quotation marks, eg:
-
- `#123["file.jpg"]`
-
-This is useful if, for instance, your filename has square braces in its name. In this scheme, all
-double quotation marks in the file name need to be escaped with backslashes, and backslashes need
-to be escaped likewise:
-
- `#123["with with \"quote\" marks and a backslash \\.png"]`
-
-### Base64 Encoding
-
-In the case of file names that include HTML elements, you will need to escape these names to avoid
-them being processed as HTML literals. To do this, we support base64 encoding, eg.
-
- The file `<a>.jpg` can be referenced as `#123[base64:PGE+LmpwZwo=]`
-
-Obviously we would advise against using such filenames.
diff --git a/doc/user/project/issues/img/issue_health_status_v12_9.png b/doc/user/project/issues/img/issue_health_status_v12_9.png
new file mode 100644
index 00000000000..f8922a74fc1
--- /dev/null
+++ b/doc/user/project/issues/img/issue_health_status_v12_9.png
Binary files differ
diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md
index fe50ec62d2c..628228adc1b 100644
--- a/doc/user/project/issues/index.md
+++ b/doc/user/project/issues/index.md
@@ -50,7 +50,8 @@ must be set.
</ul>
<li>State</li>
<ul>
- <li>Status (open/closed)</li>
+ <li>State (open or closed)</li>
+ <li>Status (On track, Needs attention, or At risk)</li>
<li>Confidentiality</li>
<li>Tasks (completed vs. outstanding)</li>
</ul>
@@ -109,8 +110,7 @@ view, you can also make certain changes [in bulk](../bulk_editing.md) to the dis
For more information, see the [Issue Data and Actions](issue_data_and_actions.md) page
for a rundown of all the fields and information in an issue.
-You can sort a list of issues several ways, including by issue creation date, milestone due date,
-etc. For more information, see the [Sorting and Ordering Issue Lists](sorting_issue_lists.md) page.
+You can sort a list of issues in several ways, for example by issue creation date, milestone due date. For more information, see the [Sorting and Ordering Issue Lists](sorting_issue_lists.md) page.
### Issue boards
@@ -157,12 +157,38 @@ To prevent duplication of issues for the same topic, GitLab searches for similar
when new issues are being created.
When typing in the title in the **New Issue** page, GitLab searches titles and descriptions
-across all issues the user has access to in the current project. Up 5 similar issues,
+across all issues the user has access to in the current project. Up to five similar issues,
sorted by most recently updated, are displayed below the title box. Note that this feature
requires [GraphQL](../../../api/graphql/index.md) to be enabled.
![Similar issues](img/similar_issues.png)
+---
+
+### Status **(ULTIMATE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/issues/36427) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9.
+
+To help you track the status of your issues, you can assign a status to each issue to flag work that's progressing as planned or needs attention to keep on schedule:
+
+- `On track` (green)
+- `Needs attention` (amber)
+- `At risk` (red)
+
+!["On track" health status on an issue](img/issue_health_status_v12_9.png)
+
+---
+
+#### Enable issue health status
+
+This feature comes with the `:save_issuable_health_status` feature flag disabled by default. However, in some cases
+this feature is incompatible with old configuration. To turn on the feature while configuration is
+migrated, ask a GitLab administrator with Rails console access to run the following command:
+
+```ruby
+Feature.enable(:save_issuable_health_status)
+```
+
## Other Issue actions
- [Create an issue from a template](../../project/description_templates.md#using-the-templates)
diff --git a/doc/user/project/merge_requests/code_quality.md b/doc/user/project/merge_requests/code_quality.md
index 5a8ce6a4f84..0525d17cca2 100644
--- a/doc/user/project/merge_requests/code_quality.md
+++ b/doc/user/project/merge_requests/code_quality.md
@@ -16,7 +16,7 @@ Code Quality:
subscription.
- Runs in [pipelines](../../../ci/pipelines/index.md) using a Docker image built in the
[GitLab Code
- Quality](https://gitlab.com/gitlab-org/security-products/codequality) project using [default Code Climate configurations](https://gitlab.com/gitlab-org/security-products/codequality/-/tree/master/codeclimate_defaults).
+ Quality](https://gitlab.com/gitlab-org/ci-cd/codequality) project using [default Code Climate configurations](https://gitlab.com/gitlab-org/ci-cd/codequality/-/tree/master/codeclimate_defaults).
- Can make use of a [template](#example-configuration).
- Is available with [Auto
DevOps](../../../topics/autodevops/index.md#auto-code-quality-starter).
@@ -135,14 +135,14 @@ code_quality:
--env SOURCE_CODE="$PWD"
--volume "$PWD":/code
--volume /var/run/docker.sock:/var/run/docker.sock
- "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
+ "registry.gitlab.com/gitlab-org/ci-cd/codequality:$SP_VERSION" /code
artifacts:
reports:
codequality: gl-code-quality-report.json
```
In GitLab 12.6, Code Quality switched to the
-[new versioning scheme](https://gitlab.com/gitlab-org/security-products/codequality/-/merge_requests/38).
+[new versioning scheme](https://gitlab.com/gitlab-org/ci-cd/codequality#versioning-and-release-cycle).
It is highly recommended to include the Code Quality template as shown in the
[example configuration](#example-configuration), which uses the new versioning scheme.
If not using the template, the `SP_VERSION` variable can be hardcoded to use the
@@ -162,7 +162,7 @@ code_quality:
--env SOURCE_CODE="$PWD"
--volume "$PWD":/code
--volume /var/run/docker.sock:/var/run/docker.sock
- "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
+ "registry.gitlab.com/gitlab-org/ci-cd/codequality:$SP_VERSION" /code
artifacts:
reports:
codequality: gl-code-quality-report.json
@@ -184,7 +184,7 @@ code_quality:
--env SOURCE_CODE="$PWD"
--volume "$PWD":/code
--volume /var/run/docker.sock:/var/run/docker.sock
- "registry.gitlab.com/gitlab-org/security-products/codequality:$SP_VERSION" /code
+ "registry.gitlab.com/gitlab-org/ci-cd/codequality:$SP_VERSION" /code
artifacts:
paths: [gl-code-quality-report.json]
```
@@ -216,7 +216,7 @@ The Code Quality job supports environment variables that users can set to
configure job execution at runtime.
For a list of available environment variables, see
-[Environment variables](https://gitlab.com/gitlab-org/security-products/codequality/blob/master/README.md#environment-variables).
+[Environment variables](https://gitlab.com/gitlab-org/ci-cd/codequality#environment-variables).
## Implementing a custom tool
diff --git a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
index 934ce2f9871..a6338ff6925 100644
--- a/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Jobs/Code-Quality.gitlab-ci.yml
@@ -7,7 +7,7 @@ code_quality:
variables:
DOCKER_DRIVER: overlay2
DOCKER_TLS_CERTDIR: ""
- CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/security-products/codequality:0.85.9"
+ CODE_QUALITY_IMAGE: "registry.gitlab.com/gitlab-org/ci-cd/codequality:0.85.9"
script:
- |
if ! docker info &>/dev/null; then
diff --git a/lib/gitlab/sidekiq_middleware/server_metrics.rb b/lib/gitlab/sidekiq_middleware/server_metrics.rb
index 9615febc5d8..60618787b24 100644
--- a/lib/gitlab/sidekiq_middleware/server_metrics.rb
+++ b/lib/gitlab/sidekiq_middleware/server_metrics.rb
@@ -46,7 +46,7 @@ module Gitlab
@metrics[:sidekiq_jobs_cpu_seconds].observe(labels, job_thread_cputime)
@metrics[:sidekiq_jobs_completion_seconds].observe(labels, monotonic_time)
@metrics[:sidekiq_jobs_db_seconds].observe(labels, ActiveRecord::LogSubscriber.runtime / 1000)
- @metrics[:sidekiq_jobs_gitaly_seconds].observe(labels, Gitlab::GitalyClient.query_time)
+ @metrics[:sidekiq_jobs_gitaly_seconds].observe(labels, get_gitaly_time(job))
end
end
@@ -69,6 +69,10 @@ module Gitlab
def get_thread_cputime
defined?(Process::CLOCK_THREAD_CPUTIME_ID) ? Process.clock_gettime(Process::CLOCK_THREAD_CPUTIME_ID) : 0
end
+
+ def get_gitaly_time(job)
+ job.fetch(:gitaly_duration, 0) / 1000.0
+ end
end
end
end
diff --git a/spec/factories/notes.rb b/spec/factories/notes.rb
index 848590efabc..a15c7625500 100644
--- a/spec/factories/notes.rb
+++ b/spec/factories/notes.rb
@@ -164,6 +164,10 @@ FactoryBot.define do
attachment { fixture_file_upload("spec/fixtures/git-cheat-sheet.pdf", "application/pdf") }
end
+ trait :confidential do
+ confidential { true }
+ end
+
transient do
in_reply_to { nil }
end
diff --git a/spec/factories/pages_domains.rb b/spec/factories/pages_domains.rb
index f914128ed3b..4efb5c7dbb1 100644
--- a/spec/factories/pages_domains.rb
+++ b/spec/factories/pages_domains.rb
@@ -7,39 +7,11 @@ FactoryBot.define do
enabled_until { 1.week.from_now }
certificate do
- '-----BEGIN CERTIFICATE-----
-MIICGzCCAYSgAwIBAgIBATANBgkqhkiG9w0BAQUFADAbMRkwFwYDVQQDExB0ZXN0
-LWNlcnRpZmljYXRlMB4XDTE2MDIxMjE0MzIwMFoXDTIwMDQxMjE0MzIwMFowGzEZ
-MBcGA1UEAxMQdGVzdC1jZXJ0aWZpY2F0ZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEApL4J9L0ZxFJ1hI1LPIflAlAGvm6ZEvoT4qKU5Xf2JgU7/2geNR1qlNFa
-SvCc08Knupp5yTgmvyK/Xi09U0N82vvp4Zvr/diSc4A/RA6Mta6egLySNT438kdT
-nY2tR5feoTLwQpX0t4IMlwGQGT5h6Of2fKmDxzuwuyffcIHqLdsCAwEAAaNvMG0w
-DAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUxl9WSxBprB0z0ibJs3rXEk0+95AwCwYD
-VR0PBAQDAgXgMBEGCWCGSAGG+EIBAQQEAwIGQDAeBglghkgBhvhCAQ0EERYPeGNh
-IGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAA4GBAGC4T8SlFHK0yPSa+idGLQFQ
-joZp2JHYvNlTPkRJ/J4TcXxBTJmArcQgTIuNoBtC+0A/SwdK4MfTCUY4vNWNdese
-5A4K65Nb7Oh1AdQieTBHNXXCdyFsva9/ScfQGEl7p55a52jOPs0StPd7g64uvjlg
-YHi2yesCrOvVXt+lgPTd
------END CERTIFICATE-----'
+ File.read(Rails.root.join('spec/fixtures/', 'ssl_certificate.pem'))
end
key do
- '-----BEGIN PRIVATE KEY-----
-MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKS+CfS9GcRSdYSN
-SzyH5QJQBr5umRL6E+KilOV39iYFO/9oHjUdapTRWkrwnNPCp7qaeck4Jr8iv14t
-PVNDfNr76eGb6/3YknOAP0QOjLWunoC8kjU+N/JHU52NrUeX3qEy8EKV9LeCDJcB
-kBk+Yejn9nypg8c7sLsn33CB6i3bAgMBAAECgYA2D26w80T7WZvazYr86BNMePpd
-j2mIAqx32KZHzt/lhh40J/SRtX9+Kl0Y7nBoRR5Ja9u/HkAIxNxLiUjwg9r6cpg/
-uITEF5nMt7lAk391BuI+7VOZZGbJDsq2ulPd6lO+C8Kq/PI/e4kXcIjeH6KwQsuR
-5vrXfBZ3sQfflaiN4QJBANBt8JY2LIGQF8o89qwUpRL5vbnKQ4IzZ5+TOl4RLR7O
-AQpJ81tGuINghO7aunctb6rrcKJrxmEH1whzComybrMCQQDKV49nOBudRBAIgG4K
-EnLzsRKISUHMZSJiYTYnablof8cKw1JaQduw7zgrUlLwnroSaAGX88+Jw1f5n2Lh
-Vlg5AkBDdUGnrDLtYBCDEQYZHblrkc7ZAeCllDOWjxUV+uMqlCv8A4Ey6omvY57C
-m6I8DkWVAQx8VPtozhvHjUw80rZHAkB55HWHAM3h13axKG0htCt7klhPsZHpx6MH
-EPjGlXIT+aW2XiPmK3ZlCDcWIenE+lmtbOpI159Wpk8BGXs/s/xBAkEAlAY3ymgx
-63BDJEwvOb2IaP8lDDxNsXx9XJNVvQbv5n15vNsLHbjslHfAhAbxnLQ1fLhUPqSi
-nNp/xedE1YxutQ==
------END PRIVATE KEY-----'
+ File.read(Rails.root.join('spec/fixtures/', 'ssl_key.pem'))
end
trait :disabled do
diff --git a/spec/factories/serverless/domain_cluster.rb b/spec/factories/serverless/domain_cluster.rb
index bc32552d4c7..40e0ecad5ad 100644
--- a/spec/factories/serverless/domain_cluster.rb
+++ b/spec/factories/serverless/domain_cluster.rb
@@ -7,39 +7,11 @@ FactoryBot.define do
creator { create(:user) }
certificate do
- '-----BEGIN CERTIFICATE-----
-MIICGzCCAYSgAwIBAgIBATANBgkqhkiG9w0BAQUFADAbMRkwFwYDVQQDExB0ZXN0
-LWNlcnRpZmljYXRlMB4XDTE2MDIxMjE0MzIwMFoXDTIwMDQxMjE0MzIwMFowGzEZ
-MBcGA1UEAxMQdGVzdC1jZXJ0aWZpY2F0ZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
-gYkCgYEApL4J9L0ZxFJ1hI1LPIflAlAGvm6ZEvoT4qKU5Xf2JgU7/2geNR1qlNFa
-SvCc08Knupp5yTgmvyK/Xi09U0N82vvp4Zvr/diSc4A/RA6Mta6egLySNT438kdT
-nY2tR5feoTLwQpX0t4IMlwGQGT5h6Of2fKmDxzuwuyffcIHqLdsCAwEAAaNvMG0w
-DAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUxl9WSxBprB0z0ibJs3rXEk0+95AwCwYD
-VR0PBAQDAgXgMBEGCWCGSAGG+EIBAQQEAwIGQDAeBglghkgBhvhCAQ0EERYPeGNh
-IGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAA4GBAGC4T8SlFHK0yPSa+idGLQFQ
-joZp2JHYvNlTPkRJ/J4TcXxBTJmArcQgTIuNoBtC+0A/SwdK4MfTCUY4vNWNdese
-5A4K65Nb7Oh1AdQieTBHNXXCdyFsva9/ScfQGEl7p55a52jOPs0StPd7g64uvjlg
-YHi2yesCrOvVXt+lgPTd
------END CERTIFICATE-----'
+ File.read(Rails.root.join('spec/fixtures/', 'ssl_certificate.pem'))
end
key do
- '-----BEGIN PRIVATE KEY-----
-MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKS+CfS9GcRSdYSN
-SzyH5QJQBr5umRL6E+KilOV39iYFO/9oHjUdapTRWkrwnNPCp7qaeck4Jr8iv14t
-PVNDfNr76eGb6/3YknOAP0QOjLWunoC8kjU+N/JHU52NrUeX3qEy8EKV9LeCDJcB
-kBk+Yejn9nypg8c7sLsn33CB6i3bAgMBAAECgYA2D26w80T7WZvazYr86BNMePpd
-j2mIAqx32KZHzt/lhh40J/SRtX9+Kl0Y7nBoRR5Ja9u/HkAIxNxLiUjwg9r6cpg/
-uITEF5nMt7lAk391BuI+7VOZZGbJDsq2ulPd6lO+C8Kq/PI/e4kXcIjeH6KwQsuR
-5vrXfBZ3sQfflaiN4QJBANBt8JY2LIGQF8o89qwUpRL5vbnKQ4IzZ5+TOl4RLR7O
-AQpJ81tGuINghO7aunctb6rrcKJrxmEH1whzComybrMCQQDKV49nOBudRBAIgG4K
-EnLzsRKISUHMZSJiYTYnablof8cKw1JaQduw7zgrUlLwnroSaAGX88+Jw1f5n2Lh
-Vlg5AkBDdUGnrDLtYBCDEQYZHblrkc7ZAeCllDOWjxUV+uMqlCv8A4Ey6omvY57C
-m6I8DkWVAQx8VPtozhvHjUw80rZHAkB55HWHAM3h13axKG0htCt7klhPsZHpx6MH
-EPjGlXIT+aW2XiPmK3ZlCDcWIenE+lmtbOpI159Wpk8BGXs/s/xBAkEAlAY3ymgx
-63BDJEwvOb2IaP8lDDxNsXx9XJNVvQbv5n15vNsLHbjslHfAhAbxnLQ1fLhUPqSi
-nNp/xedE1YxutQ==
------END PRIVATE KEY-----'
+ File.read(Rails.root.join('spec/fixtures/', 'ssl_key.pem'))
end
end
end
diff --git a/spec/factories/snippets.rb b/spec/factories/snippets.rb
index 8ab5c7f1fa5..3d99a04ea1a 100644
--- a/spec/factories/snippets.rb
+++ b/spec/factories/snippets.rb
@@ -48,6 +48,7 @@ FactoryBot.define do
trait :secret do
visibility_level { Snippet::PUBLIC }
secret { true }
+ project { nil }
end
end
end
diff --git a/spec/features/projects/pages_spec.rb b/spec/features/projects/pages_spec.rb
index c8da87041f9..f4f70e7efbc 100644
--- a/spec/features/projects/pages_spec.rb
+++ b/spec/features/projects/pages_spec.rb
@@ -135,43 +135,11 @@ shared_examples 'pages settings editing' do
context 'when pages are exposed on external HTTPS address', :https_pages_enabled, :js do
let(:certificate_pem) do
- <<~PEM
- -----BEGIN CERTIFICATE-----
- MIICGzCCAYSgAwIBAgIBATANBgkqhkiG9w0BAQUFADAbMRkwFwYDVQQDExB0ZXN0
- LWNlcnRpZmljYXRlMB4XDTE2MDIxMjE0MzIwMFoXDTIwMDQxMjE0MzIwMFowGzEZ
- MBcGA1UEAxMQdGVzdC1jZXJ0aWZpY2F0ZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
- gYkCgYEApL4J9L0ZxFJ1hI1LPIflAlAGvm6ZEvoT4qKU5Xf2JgU7/2geNR1qlNFa
- SvCc08Knupp5yTgmvyK/Xi09U0N82vvp4Zvr/diSc4A/RA6Mta6egLySNT438kdT
- nY2tR5feoTLwQpX0t4IMlwGQGT5h6Of2fKmDxzuwuyffcIHqLdsCAwEAAaNvMG0w
- DAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUxl9WSxBprB0z0ibJs3rXEk0+95AwCwYD
- VR0PBAQDAgXgMBEGCWCGSAGG+EIBAQQEAwIGQDAeBglghkgBhvhCAQ0EERYPeGNh
- IGNlcnRpZmljYXRlMA0GCSqGSIb3DQEBBQUAA4GBAGC4T8SlFHK0yPSa+idGLQFQ
- joZp2JHYvNlTPkRJ/J4TcXxBTJmArcQgTIuNoBtC+0A/SwdK4MfTCUY4vNWNdese
- 5A4K65Nb7Oh1AdQieTBHNXXCdyFsva9/ScfQGEl7p55a52jOPs0StPd7g64uvjlg
- YHi2yesCrOvVXt+lgPTd
- -----END CERTIFICATE-----
- PEM
+ attributes_for(:pages_domain)[:certificate]
end
let(:certificate_key) do
- <<~KEY
- -----BEGIN PRIVATE KEY-----
- MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKS+CfS9GcRSdYSN
- SzyH5QJQBr5umRL6E+KilOV39iYFO/9oHjUdapTRWkrwnNPCp7qaeck4Jr8iv14t
- PVNDfNr76eGb6/3YknOAP0QOjLWunoC8kjU+N/JHU52NrUeX3qEy8EKV9LeCDJcB
- kBk+Yejn9nypg8c7sLsn33CB6i3bAgMBAAECgYA2D26w80T7WZvazYr86BNMePpd
- j2mIAqx32KZHzt/lhh40J/SRtX9+Kl0Y7nBoRR5Ja9u/HkAIxNxLiUjwg9r6cpg/
- uITEF5nMt7lAk391BuI+7VOZZGbJDsq2ulPd6lO+C8Kq/PI/e4kXcIjeH6KwQsuR
- 5vrXfBZ3sQfflaiN4QJBANBt8JY2LIGQF8o89qwUpRL5vbnKQ4IzZ5+TOl4RLR7O
- AQpJ81tGuINghO7aunctb6rrcKJrxmEH1whzComybrMCQQDKV49nOBudRBAIgG4K
- EnLzsRKISUHMZSJiYTYnablof8cKw1JaQduw7zgrUlLwnroSaAGX88+Jw1f5n2Lh
- Vlg5AkBDdUGnrDLtYBCDEQYZHblrkc7ZAeCllDOWjxUV+uMqlCv8A4Ey6omvY57C
- m6I8DkWVAQx8VPtozhvHjUw80rZHAkB55HWHAM3h13axKG0htCt7klhPsZHpx6MH
- EPjGlXIT+aW2XiPmK3ZlCDcWIenE+lmtbOpI159Wpk8BGXs/s/xBAkEAlAY3ymgx
- 63BDJEwvOb2IaP8lDDxNsXx9XJNVvQbv5n15vNsLHbjslHfAhAbxnLQ1fLhUPqSi
- nNp/xedE1YxutQ==
- -----END PRIVATE KEY-----
- KEY
+ attributes_for(:pages_domain)[:key]
end
it 'adds new domain with certificate' do
diff --git a/spec/finders/award_emojis_finder_spec.rb b/spec/finders/award_emojis_finder_spec.rb
index bdfd2a9a3f4..975722e780b 100644
--- a/spec/finders/award_emojis_finder_spec.rb
+++ b/spec/finders/award_emojis_finder_spec.rb
@@ -20,6 +20,11 @@ describe AwardEmojisFinder do
)
end
+ it 'does not raise an error if `name` is numeric' do
+ subject = described_class.new(issue_1, { name: 100 })
+ expect { subject.execute }.not_to raise_error
+ end
+
it 'raises an error if `awarded_by` is invalid' do
expectation = [ArgumentError, 'Invalid awarded_by param']
diff --git a/spec/fixtures/ssl_certificate.pem b/spec/fixtures/ssl_certificate.pem
new file mode 100644
index 00000000000..6c9a8dd42c6
--- /dev/null
+++ b/spec/fixtures/ssl_certificate.pem
@@ -0,0 +1,12 @@
+-----BEGIN CERTIFICATE-----
+MIIBrzCCARgCCQDbfQx2zdkNYTANBgkqhkiG9w0BAQsFADAbMRkwFwYDVQQDDBB0
+ZXN0LWNlcnRpZmljYXRlMCAXDTIwMDMxNjE0MjAzNFoYDzIyMjAwMTI4MTQyMDM0
+WjAbMRkwFwYDVQQDDBB0ZXN0LWNlcnRpZmljYXRlMIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQCkvgn0vRnEUnWEjUs8h+UCUAa+bpkS+hPiopTld/YmBTv/aB41
+HWqU0VpK8JzTwqe6mnnJOCa/Ir9eLT1TQ3za++nhm+v92JJzgD9EDoy1rp6AvJI1
+PjfyR1Odja1Hl96hMvBClfS3ggyXAZAZPmHo5/Z8qYPHO7C7J99wgeot2wIDAQAB
+MA0GCSqGSIb3DQEBCwUAA4GBACc+chrTAuvnMBTedc4/dy16pEesK6oGjywYUd/0
+/FBr8Vry7QUXMSgfraza9S0V+JvFvZFqkkOyJKW+m30kThWzyc/2e+BRxTh/QrxP
+0j84QXtmnVtW4jsAwfBBfg78ST27eyp/WhruI6F/kZlXhfAed0RcPbRnbi3yvUPL
+Lo4T
+-----END CERTIFICATE-----
diff --git a/spec/fixtures/ssl_key.pem b/spec/fixtures/ssl_key.pem
new file mode 100644
index 00000000000..1b53126536e
--- /dev/null
+++ b/spec/fixtures/ssl_key.pem
@@ -0,0 +1,16 @@
+-----BEGIN PRIVATE KEY-----
+MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAKS+CfS9GcRSdYSN
+SzyH5QJQBr5umRL6E+KilOV39iYFO/9oHjUdapTRWkrwnNPCp7qaeck4Jr8iv14t
+PVNDfNr76eGb6/3YknOAP0QOjLWunoC8kjU+N/JHU52NrUeX3qEy8EKV9LeCDJcB
+kBk+Yejn9nypg8c7sLsn33CB6i3bAgMBAAECgYA2D26w80T7WZvazYr86BNMePpd
+j2mIAqx32KZHzt/lhh40J/SRtX9+Kl0Y7nBoRR5Ja9u/HkAIxNxLiUjwg9r6cpg/
+uITEF5nMt7lAk391BuI+7VOZZGbJDsq2ulPd6lO+C8Kq/PI/e4kXcIjeH6KwQsuR
+5vrXfBZ3sQfflaiN4QJBANBt8JY2LIGQF8o89qwUpRL5vbnKQ4IzZ5+TOl4RLR7O
+AQpJ81tGuINghO7aunctb6rrcKJrxmEH1whzComybrMCQQDKV49nOBudRBAIgG4K
+EnLzsRKISUHMZSJiYTYnablof8cKw1JaQduw7zgrUlLwnroSaAGX88+Jw1f5n2Lh
+Vlg5AkBDdUGnrDLtYBCDEQYZHblrkc7ZAeCllDOWjxUV+uMqlCv8A4Ey6omvY57C
+m6I8DkWVAQx8VPtozhvHjUw80rZHAkB55HWHAM3h13axKG0htCt7klhPsZHpx6MH
+EPjGlXIT+aW2XiPmK3ZlCDcWIenE+lmtbOpI159Wpk8BGXs/s/xBAkEAlAY3ymgx
+63BDJEwvOb2IaP8lDDxNsXx9XJNVvQbv5n15vNsLHbjslHfAhAbxnLQ1fLhUPqSi
+nNp/xedE1YxutQ==
+-----END PRIVATE KEY-----
diff --git a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
index 23c5b59922b..3343587beff 100644
--- a/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/server_metrics_spec.rb
@@ -67,7 +67,7 @@ describe Gitlab::SidekiqMiddleware::ServerMetrics do
allow(Gitlab::Metrics::System).to receive(:monotonic_time).and_return(monotonic_time_before, monotonic_time_after)
allow(Gitlab::InstrumentationHelper).to receive(:queue_duration_for_job).with(job).and_return(queue_duration_for_job)
allow(ActiveRecord::LogSubscriber).to receive(:runtime).and_return(db_duration * 1000)
- allow(Gitlab::GitalyClient).to receive(:query_time).and_return(gitaly_duration)
+ allow(subject).to receive(:get_gitaly_time).and_return(gitaly_duration)
expect(running_jobs_metric).to receive(:increment).with(labels, 1)
expect(running_jobs_metric).to receive(:increment).with(labels, -1)
diff --git a/spec/lib/gitlab/sidekiq_middleware_spec.rb b/spec/lib/gitlab/sidekiq_middleware_spec.rb
index 2f325fd5052..88f83ebc2ac 100644
--- a/spec/lib/gitlab/sidekiq_middleware_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware_spec.rb
@@ -8,6 +8,8 @@ describe Gitlab::SidekiqMiddleware do
include Sidekiq::Worker
def perform(_arg)
+ Gitlab::SafeRequestStore['gitaly_call_actual'] = 1
+ Gitlab::GitalyClient.query_time = 5
end
end
@@ -99,6 +101,24 @@ describe Gitlab::SidekiqMiddleware do
it "passes through server middlewares" do
worker_class.perform_async(*job_args)
end
+
+ context "server metrics" do
+ let(:gitaly_histogram) { double(:gitaly_histogram) }
+
+ before do
+ allow(Gitlab::Metrics).to receive(:histogram).and_call_original
+
+ allow(Gitlab::Metrics).to receive(:histogram)
+ .with(:sidekiq_jobs_gitaly_seconds, anything, anything, anything)
+ .and_return(gitaly_histogram)
+ end
+
+ it "records correct Gitaly duration" do
+ expect(gitaly_histogram).to receive(:observe).with(anything, 5.0)
+
+ worker_class.perform_async(*job_args)
+ end
+ end
end
end
diff --git a/spec/lib/gitlab/usage_data_spec.rb b/spec/lib/gitlab/usage_data_spec.rb
index 113cb4ba6bf..21117f11f63 100644
--- a/spec/lib/gitlab/usage_data_spec.rb
+++ b/spec/lib/gitlab/usage_data_spec.rb
@@ -387,6 +387,22 @@ describe Gitlab::UsageData do
expect(described_class.count(relation, fallback: 15, batch: false)).to eq(15)
end
end
+
+ describe '#distinct_count' do
+ let(:relation) { double(:relation) }
+
+ it 'returns the count when counting succeeds' do
+ allow(relation).to receive(:distinct_count_by).and_return(1)
+
+ expect(described_class.distinct_count(relation, batch: false)).to eq(1)
+ end
+
+ it 'returns the fallback value when counting fails' do
+ allow(relation).to receive(:distinct_count_by).and_raise(ActiveRecord::StatementInvalid.new(''))
+
+ expect(described_class.distinct_count(relation, fallback: 15, batch: false)).to eq(15)
+ end
+ end
end
end
end
diff --git a/spec/models/concerns/usage_statistics_spec.rb b/spec/models/concerns/usage_statistics_spec.rb
new file mode 100644
index 00000000000..f99f0a13317
--- /dev/null
+++ b/spec/models/concerns/usage_statistics_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+describe UsageStatistics do
+ describe '.distinct_count_by' do
+ let_it_be(:issue_1) { create(:issue) }
+ let_it_be(:issue_2) { create(:issue) }
+
+ context 'two records created by the same issue' do
+ let!(:models_created_by_issue) do
+ create(:zoom_meeting, :added_to_issue, issue: issue_1)
+ create(:zoom_meeting, :removed_from_issue, issue: issue_1)
+ end
+
+ it 'returns a count of 1' do
+ expect(::ZoomMeeting.distinct_count_by(:issue_id)).to eq(1)
+ end
+
+ context 'when given no column to count' do
+ it 'counts by :id and returns a count of 2' do
+ expect(::ZoomMeeting.distinct_count_by).to eq(2)
+ end
+ end
+ end
+
+ context 'one record created by each issue' do
+ let!(:model_created_by_issue_1) { create(:zoom_meeting, issue: issue_1) }
+ let!(:model_created_by_issue_2) { create(:zoom_meeting, issue: issue_2) }
+
+ it 'returns a count of 2' do
+ expect(::ZoomMeeting.distinct_count_by(:issue_id)).to eq(2)
+ end
+ end
+
+ context 'the count query times out' do
+ before do
+ allow_next_instance_of(ActiveRecord::Relation) do |instance|
+ allow(instance).to receive(:count).and_raise(ActiveRecord::StatementInvalid.new(''))
+ end
+ end
+
+ it 'does not raise an error' do
+ expect { ::ZoomMeeting.distinct_count_by(:issue_id) }.not_to raise_error
+ end
+
+ it 'returns -1' do
+ expect(::ZoomMeeting.distinct_count_by(:issue_id)).to eq(-1)
+ end
+ end
+ end
+end
diff --git a/spec/models/note_spec.rb b/spec/models/note_spec.rb
index 4da23c79944..74ec74e0def 100644
--- a/spec/models/note_spec.rb
+++ b/spec/models/note_spec.rb
@@ -270,18 +270,35 @@ describe Note do
end
end
- describe "confidential?" do
- it "delegates to noteable" do
- issue_note = build(:note, :on_issue)
- confidential_note = build(:note, noteable: create(:issue, confidential: true))
+ describe '#confidential?' do
+ context 'when note is not confidential' do
+ it 'is true when a noteable is confidential' do
+ issue = create(:issue, :confidential)
+ note = build(:note, noteable: issue, project: issue.project)
- expect(issue_note.confidential?).to be_falsy
- expect(confidential_note.confidential?).to be_truthy
+ expect(note.confidential?).to be_truthy
+ end
+
+ it 'is false when a noteable is not confidential' do
+ issue = create(:issue, confidential: false)
+ note = build(:note, noteable: issue, project: issue.project)
+
+ expect(note.confidential?).to be_falsy
+ end
+
+ it "is falsey when noteable can't be confidential" do
+ commit_note = build(:note_on_commit)
+
+ expect(commit_note.confidential?).to be_falsy
+ end
end
+ context 'when note is confidential' do
+ it 'is true even when a noteable is not confidential' do
+ issue = create(:issue, confidential: false)
+ note = build(:note, :confidential, noteable: issue, project: issue.project)
- it "is falsey when noteable can't be confidential" do
- commit_note = build(:note_on_commit)
- expect(commit_note.confidential?).to be_falsy
+ expect(note.confidential?).to be_truthy
+ end
end
end
@@ -1230,5 +1247,69 @@ describe Note do
expect(notes.second.id).to eq(note2.id)
end
end
+
+ describe '#noteable_assignee_or_author' do
+ let(:user) { create(:user) }
+ let(:noteable) { create(:issue) }
+ let(:note) { create(:note, project: noteable.project, noteable: noteable) }
+
+ subject { note.noteable_assignee_or_author?(user) }
+
+ shared_examples 'assignee check' do
+ context 'when the provided user is one of the assignees' do
+ before do
+ note.noteable.update(assignees: [user, create(:user)])
+ end
+
+ it 'returns true' do
+ expect(subject).to be_truthy
+ end
+ end
+ end
+
+ shared_examples 'author check' do
+ context 'when the provided user is the author' do
+ before do
+ note.noteable.update(author: user)
+ end
+
+ it 'returns true' do
+ expect(subject).to be_truthy
+ end
+ end
+
+ context 'when the provided user is neither author nor assignee' do
+ it 'returns true' do
+ expect(subject).to be_falsey
+ end
+ end
+ end
+
+ context 'when user is nil' do
+ let(:user) { nil }
+
+ it 'returns false' do
+ expect(subject).to be_falsey
+ end
+ end
+
+ context 'when noteable is an issue' do
+ it_behaves_like 'author check'
+ it_behaves_like 'assignee check'
+ end
+
+ context 'when noteable is a merge request' do
+ let(:noteable) { create(:merge_request) }
+
+ it_behaves_like 'author check'
+ it_behaves_like 'assignee check'
+ end
+
+ context 'when noteable is a snippet' do
+ let(:noteable) { create(:personal_snippet) }
+
+ it_behaves_like 'author check'
+ end
+ end
end
end
diff --git a/spec/models/pages_domain_spec.rb b/spec/models/pages_domain_spec.rb
index a4ed02c3254..4bf56e7b28b 100644
--- a/spec/models/pages_domain_spec.rb
+++ b/spec/models/pages_domain_spec.rb
@@ -7,11 +7,6 @@ describe PagesDomain do
subject(:pages_domain) { described_class.new }
- # Locking in date due to cert expiration date https://gitlab.com/gitlab-org/gitlab/-/issues/210557#note_304749257
- around do |example|
- Timecop.travel(Time.new(2020, 3, 12)) { example.run }
- end
-
describe 'associations' do
it { is_expected.to belong_to(:project) }
it { is_expected.to have_many(:serverless_domain_clusters) }
@@ -102,8 +97,8 @@ describe PagesDomain do
it 'saves validity time' do
domain.save
- expect(domain.certificate_valid_not_before).to be_like_time(Time.parse("2016-02-12 14:32:00 UTC"))
- expect(domain.certificate_valid_not_after).to be_like_time(Time.parse("2020-04-12 14:32:00 UTC"))
+ expect(domain.certificate_valid_not_before).to be_like_time(Time.parse("2020-03-16 14:20:34 UTC"))
+ expect(domain.certificate_valid_not_after).to be_like_time(Time.parse("2220-01-28 14:20:34 UTC"))
end
end
diff --git a/spec/models/zoom_meeting_spec.rb b/spec/models/zoom_meeting_spec.rb
index d496b968f1e..3dad957a1ce 100644
--- a/spec/models/zoom_meeting_spec.rb
+++ b/spec/models/zoom_meeting_spec.rb
@@ -151,51 +151,4 @@ describe ZoomMeeting do
it_behaves_like 'can remove meetings'
end
end
-
- describe '.distinct_count_by' do
- let(:issue_1) { create(:issue) }
- let(:issue_2) { create(:issue) }
-
- context 'two meetings for the same issue' do
- before do
- create(:zoom_meeting, issue: issue_1)
- create(:zoom_meeting, :removed_from_issue, issue: issue_1)
- end
-
- it 'returns a count of 1' do
- expect(described_class.distinct_count_by(:issue_id)).to eq(1)
- end
-
- context 'when given no colum to count' do
- it 'counts by :id and returns a count of 2' do
- expect(described_class.distinct_count_by).to eq(2)
- end
- end
- end
-
- context 'one meeting for each issue' do
- it 'returns a count of 2' do
- create(:zoom_meeting, issue: issue_1)
- create(:zoom_meeting, issue: issue_2)
-
- expect(described_class.distinct_count_by(:issue_id)).to eq(2)
- end
- end
-
- context 'the count query times out' do
- before do
- allow_next_instance_of(ActiveRecord::Relation) do |instance|
- allow(instance).to receive(:count).and_raise(ActiveRecord::StatementInvalid.new(''))
- end
- end
-
- it 'does not raise an error' do
- expect { described_class.distinct_count_by(:issue_id) }.not_to raise_error
- end
-
- it 'returns -1' do
- expect(described_class.distinct_count_by(:issue_id)).to eq(-1)
- end
- end
- end
end
diff --git a/spec/policies/note_policy_spec.rb b/spec/policies/note_policy_spec.rb
index 2619bb2fe3c..e480fc2a642 100644
--- a/spec/policies/note_policy_spec.rb
+++ b/spec/policies/note_policy_spec.rb
@@ -238,6 +238,101 @@ describe NotePolicy do
end
end
end
+
+ context 'with confidential notes' do
+ def permissions(user, note)
+ described_class.new(user, note)
+ end
+
+ let(:reporter) { create(:user) }
+ let(:developer) { create(:user) }
+ let(:maintainer) { create(:user) }
+ let(:guest) { create(:user) }
+ let(:non_member) { create(:user) }
+ let(:author) { create(:user) }
+ let(:assignee) { create(:user) }
+
+ before do
+ project.add_reporter(reporter)
+ project.add_developer(developer)
+ project.add_maintainer(maintainer)
+ project.add_guest(guest)
+ end
+
+ shared_examples_for 'confidential notes permissions' do
+ it 'does not allow non members to read confidential notes and replies' do
+ expect(permissions(non_member, confidential_note)).to be_disallowed(:read_note, :admin_note, :resolve_note, :award_emoji)
+ end
+
+ it 'does not allow guests to read confidential notes and replies' do
+ expect(permissions(guest, confidential_note)).to be_disallowed(:read_note, :admin_note, :resolve_note, :award_emoji)
+ end
+
+ it 'allows reporter to read all notes but not resolve and admin them' do
+ expect(permissions(reporter, confidential_note)).to be_allowed(:read_note, :award_emoji)
+ expect(permissions(reporter, confidential_note)).to be_disallowed(:admin_note, :resolve_note)
+ end
+
+ it 'allows developer to read and resolve all notes' do
+ expect(permissions(developer, confidential_note)).to be_allowed(:read_note, :award_emoji, :resolve_note)
+ expect(permissions(developer, confidential_note)).to be_disallowed(:admin_note)
+ end
+
+ it 'allows maintainers to read all notes and admin them' do
+ expect(permissions(maintainer, confidential_note)).to be_allowed(:read_note, :admin_note, :resolve_note, :award_emoji)
+ end
+
+ it 'allows noteable author to read and resolve all notes' do
+ expect(permissions(author, confidential_note)).to be_allowed(:read_note, :resolve_note, :award_emoji)
+ expect(permissions(author, confidential_note)).to be_disallowed(:admin_note)
+ end
+ end
+
+ context 'for issues' do
+ let(:issue) { create(:issue, project: project, author: author, assignees: [assignee]) }
+ let(:confidential_note) { create(:note, :confidential, project: project, noteable: issue) }
+
+ it_behaves_like 'confidential notes permissions'
+
+ it 'allows noteable assignees to read all notes' do
+ expect(permissions(assignee, confidential_note)).to be_allowed(:read_note, :award_emoji)
+ expect(permissions(assignee, confidential_note)).to be_disallowed(:admin_note, :resolve_note)
+ end
+ end
+
+ context 'for merge requests' do
+ let(:merge_request) { create(:merge_request, source_project: project, author: author, assignees: [assignee]) }
+ let(:confidential_note) { create(:note, :confidential, project: project, noteable: merge_request) }
+
+ it_behaves_like 'confidential notes permissions'
+
+ it 'allows noteable assignees to read all notes' do
+ expect(permissions(assignee, confidential_note)).to be_allowed(:read_note, :award_emoji)
+ expect(permissions(assignee, confidential_note)).to be_disallowed(:admin_note, :resolve_note)
+ end
+ end
+
+ context 'for project snippets' do
+ let(:project_snippet) { create(:project_snippet, project: project, author: author) }
+ let(:confidential_note) { create(:note, :confidential, project: project, noteable: project_snippet) }
+
+ it_behaves_like 'confidential notes permissions'
+ end
+
+ context 'for personal snippets' do
+ let(:personal_snippet) { create(:personal_snippet, author: author) }
+ let(:confidential_note) { create(:note, :confidential, project: nil, noteable: personal_snippet) }
+
+ it 'allows snippet author to read and resolve all notes' do
+ expect(permissions(author, confidential_note)).to be_allowed(:read_note, :resolve_note, :award_emoji)
+ expect(permissions(author, confidential_note)).to be_disallowed(:admin_note)
+ end
+
+ it 'does not allow maintainers to read confidential notes and replies' do
+ expect(permissions(maintainer, confidential_note)).to be_disallowed(:read_note, :admin_note, :resolve_note, :award_emoji)
+ end
+ end
+ end
end
end
end
diff --git a/spec/workers/pages_domain_ssl_renewal_cron_worker_spec.rb b/spec/workers/pages_domain_ssl_renewal_cron_worker_spec.rb
index ae66122b4de..736acc40371 100644
--- a/spec/workers/pages_domain_ssl_renewal_cron_worker_spec.rb
+++ b/spec/workers/pages_domain_ssl_renewal_cron_worker_spec.rb
@@ -7,11 +7,6 @@ describe PagesDomainSslRenewalCronWorker do
subject(:worker) { described_class.new }
- # Locking in date due to cert expiration date https://gitlab.com/gitlab-org/gitlab/-/issues/210557#note_304749257
- around do |example|
- Timecop.travel(Time.new(2020, 3, 12)) { example.run }
- end
-
before do
stub_lets_encrypt_settings
end