diff --git a/app/models/integrations/hangouts_chat.rb b/app/models/integrations/hangouts_chat.rb
index df112ad6ca8..6e7f31aa030 100644
--- a/app/models/integrations/hangouts_chat.rb
+++ b/app/models/integrations/hangouts_chat.rb
@@ -47,8 +47,31 @@ module Integrations
private
def notify(message, opts)
+ url = webhook.dup
+
+ key = parse_thread_key(message)
+ url = Gitlab::Utils.add_url_parameters(url, { threadKey: key }) if key
+
simple_text = parse_simple_text_message(message)
- ::HangoutsChat::Sender.new(webhook).simple(simple_text)
+ ::HangoutsChat::Sender.new(url).simple(simple_text)
+ end
+
+ # Returns an appropriate key for threading messages in google chat
+ def parse_thread_key(message)
+ case message
+ when Integrations::ChatMessage::NoteMessage
+ message.target
+ when Integrations::ChatMessage::IssueMessage
+ "issue #{Issue.reference_prefix}#{message.issue_iid}"
+ when Integrations::ChatMessage::MergeMessage
+ "merge request #{MergeRequest.reference_prefix}#{message.merge_request_iid}"
+ when Integrations::ChatMessage::PushMessage
+ "push #{message.project_name}_#{message.ref}"
+ when Integrations::ChatMessage::PipelineMessage
+ "pipeline #{message.pipeline_id}"
+ when Integrations::ChatMessage::WikiPageMessage
+ "wiki_page #{message.wiki_page_url}"
+ end
end
def parse_simple_text_message(message)
diff --git a/app/views/shared/access_tokens/_created_container.html.haml b/app/views/shared/access_tokens/_created_container.html.haml
index c5a18d98b89..c0aaa46e761 100644
--- a/app/views/shared/access_tokens/_created_container.html.haml
+++ b/app/views/shared/access_tokens/_created_container.html.haml
@@ -3,7 +3,7 @@
= _('Your new %{type}') % { type: type }
.form-group
.input-group
- = text_field_tag 'created-personal-access-token', new_token_value, readonly: true, class: 'qa-created-access-token form-control js-select-on-focus', 'aria-describedby' => 'created-token-help-block'
+ = text_field_tag 'created-personal-access-token', new_token_value, readonly: true, class: 'form-control js-select-on-focus', data: { qa_selector: 'created_access_token_field' }, 'aria-describedby' => 'created-token-help-block'
%span.input-group-append
= clipboard_button(text: new_token_value, title: _('Copy %{type}') % { type: type }, placement: 'left', class: 'input-group-text btn-default btn-clipboard')
%span#created-token-help-block.form-text.text-muted.text-danger
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index b053da7ac9b..e36516107d2 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -660,7 +660,14 @@ The code removed from GitLab during the Gitaly migration project affected these
performance workaround for these NFS-based deployments, we re-introduced some of the old Rugged
code. This re-introduced code is informally referred to as the "Rugged patches".
-### How it works
+### Automatic detection
+
+> Automatic detection for Rugged [disabled](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95445) in GitLab 15.3.
+
+FLAG:
+On self-managed GitLab, by default automatic detection of whether Rugged should be used (per storage) is not available.
+To make it available, ask an administrator to [disable the feature flag](../../administration/feature_flags.md) named
+`skip_rugged_auto_detect`.
The Ruby methods that perform direct Git access are behind
[feature flags](../../development/gitaly.md#legacy-rugged-code), disabled by default. It wasn't
@@ -685,12 +692,13 @@ To see if GitLab can access the repository file system directly, we use the foll
- GitLab Rails tries to read the metadata file directly. If it exists, and if the UUID's match,
assume we have direct access.
-Versions of GitLab 15.3 and later disable direct Git access by default.
+Direct Git access is:
-For versions of GitLab prior to 15.3, direct Git access is enabled by
-default in Omnibus GitLab because it fills in the correct repository
-paths in the GitLab configuration file `config/gitlab.yml`. This
-satisfies the UUID check.
+- [Disabled](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95445) by default in GitLab 15.3 and later for
+ compatibility with [Praefect-generated replica paths](#praefect-generated-replica-paths-gitlab-150-and-later). It
+ can be enabled if Rugged [feature flags](../../development/gitaly.md#legacy-rugged-code) are enabled.
+- Enabled by default in GitLab 15.2 and earlier because it fills in the correct repository paths in the GitLab
+ configuration file `config/gitlab.yml`. This satisfies the UUID check.
### Transition to Gitaly Cluster
diff --git a/doc/administration/nfs.md b/doc/administration/nfs.md
index 29f00fec3f7..9967cce5b73 100644
--- a/doc/administration/nfs.md
+++ b/doc/administration/nfs.md
@@ -95,34 +95,22 @@ We are investigating the use of
## Improving NFS performance with GitLab
NFS performance with GitLab can in some cases be improved with
-[direct Git access](gitaly/index.md#direct-access-to-git-in-gitlab) using
-[Rugged](https://github.com/libgit2/rugged).
+[direct Git access](gitaly/index.md#direct-access-to-git-in-gitlab) using [Rugged](https://github.com/libgit2/rugged).
-Versions of GitLab after 12.2 and prior to 15.3 automatically detect if
-Rugged can and should be used per storage.
+Depending on the GitLab version, GitLab [automatically detects](gitaly/index.md#automatic-detection) if Rugged can and should
+be used per storage.
-NOTE:
-GitLab 15.3 and later disables this automatic detection. Auto-detection can be enabled via the
-`skip_rugged_auto_detect` feature flag:
-
-```ruby
-Feature.disable(:skip_rugged_auto_detect)
-```
-
-In addition, if you previously enabled Rugged using the feature flag and
-you want to use automatic detection instead, you must unset the feature
-flag:
+If the Rugged feature flag is explicitly set to either `true` or `false`, GitLab uses the value explicitly set. If you
+previously enabled Rugged using the feature flag and you want to use automatic detection instead, you must unset
+the feature flag:
```shell
sudo gitlab-rake gitlab:features:unset_rugged
```
-If the Rugged feature flag is explicitly set to either `true` or `false`, GitLab uses the value explicitly set.
-
-From GitLab 12.7, Rugged is only automatically enabled for use with Puma
-if the [Puma thread count is set to `1`](../install/requirements.md#puma-settings).
-
-To use Rugged with a Puma thread count of more than `1`, enable Rugged using the [feature flag](../development/gitaly.md#legacy-rugged-code).
+From GitLab 12.7, Rugged is only automatically enabled for use with Puma if the
+[Puma thread count is set to `1`](../install/requirements.md#puma-settings). To use Rugged with a Puma thread count of
+more than `1`, enable Rugged using the [feature flag](../development/gitaly.md#legacy-rugged-code).
## NFS server
diff --git a/doc/administration/operations/puma.md b/doc/administration/operations/puma.md
index 5ce469d3e63..8e7594dfc2d 100644
--- a/doc/administration/operations/puma.md
+++ b/doc/administration/operations/puma.md
@@ -156,10 +156,8 @@ For deployments where NFS is used to store Git repositories, GitLab uses
[direct Git access](../gitaly/index.md#direct-access-to-git-in-gitlab) to improve performance by using
[Rugged](https://github.com/libgit2/rugged).
-Rugged usage is automatically enabled if direct Git access
-[is available](../gitaly/index.md#how-it-works)
-and Puma is running single threaded, unless it is disabled by a
-[feature flag](../../development/gitaly.md#legacy-rugged-code).
+Rugged usage is automatically enabled if direct Git access [is available](../gitaly/index.md#automatic-detection) and
+Puma is running single threaded, unless it is disabled by a [feature flag](../../development/gitaly.md#legacy-rugged-code).
MRI Ruby uses a Global VM Lock (GVL). GVL allows MRI Ruby to be multi-threaded, but running at
most on a single core.
diff --git a/doc/api/groups.md b/doc/api/groups.md
index 588ab2a5821..9cbd12e664c 100644
--- a/doc/api/groups.md
+++ b/doc/api/groups.md
@@ -1444,7 +1444,7 @@ response attributes:
| Attribute | Type | Description |
|:-------------------|:-------|:-------------------------------------------------------------------------------------|
| `[].name` | string | Name of the SAML group |
-| `[].access_level` | string | Minimum [access level](members.md#valid-access-levels) for members of the SAML group |
+| `[].access_level` | integer | Minimum [access level](members.md#valid-access-levels) for members of the SAML group |
Example request:
@@ -1458,11 +1458,11 @@ Example response:
[
{
"name": "saml-group-1",
- "access_level": "Guest"
+ "access_level": 10
},
{
"name": "saml-group-2",
- "access_level": "Maintainer"
+ "access_level": 40
}
]
```
@@ -1488,7 +1488,7 @@ response attributes:
| Attribute | Type | Description |
|:---------------|:-------|:-------------------------------------------------------------------------------------|
| `name` | string | Name of the SAML group |
-| `access_level` | string | Minimum [access level](members.md#valid-access-levels) for members of the SAML group |
+| `access_level` | integer | Minimum [access level](members.md#valid-access-levels) for members of the SAML group |
Example request:
@@ -1501,7 +1501,7 @@ Example response:
```json
{
"name": "saml-group-1",
-"access_level": "Guest"
+"access_level": 10
}
```
@@ -1519,7 +1519,7 @@ Supported attributes:
|:-------------------|:---------------|:---------|:-------------------------------------------------------------------------------------|
| `id` | integer/string | yes | ID or [URL-encoded path of the group](index.md#namespaced-path-encoding) |
| `saml_group_name` | string | yes | Name of a SAML group |
-| `access_level` | string | yes | Minimum [access level](members.md#valid-access-levels) for members of the SAML group |
+| `access_level` | integer | yes | Minimum [access level](members.md#valid-access-levels) for members of the SAML group |
If successful, returns [`201`](index.md#status-codes) and the following
response attributes:
@@ -1527,7 +1527,7 @@ response attributes:
| Attribute | Type | Description |
|:---------------|:-------|:-------------------------------------------------------------------------------------|
| `name` | string | Name of the SAML group |
-| `access_level` | string | Minimum [access level](members.md#valid-access-levels) for members of the SAML group |
+| `access_level` | integer | Minimum [access level](members.md#valid-access-levels) for members of the SAML group |
Example request:
@@ -1540,7 +1540,7 @@ Example response:
```json
{
"name": "saml-group-1",
-"access_level": "Guest"
+"access_level": 10
}
```
diff --git a/doc/api/settings.md b/doc/api/settings.md
index c736c0df1da..d11269113a1 100644
--- a/doc/api/settings.md
+++ b/doc/api/settings.md
@@ -274,6 +274,7 @@ listed in the descriptions of the relevant settings.
| `container_registry_token_expire_delay` | integer | no | Container Registry token duration in minutes. |
| `package_registry_cleanup_policies_worker_capacity` | integer | no | Number of workers assigned to the packages cleanup policies. |
| `deactivate_dormant_users` | boolean | no | Enable [automatic deactivation of dormant users](../user/admin_area/moderate_users.md#automatically-deactivate-dormant-users). |
+| `deactivate_dormant_users_period` | integer | no | Length of time (in days) after which a user is considered dormant. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/336747) in GitLab 15.3. |
| `default_artifacts_expire_in` | string | no | Set the default expiration time for each job's artifacts. |
| `default_branch_name` | string | no | [Instance-level custom initial branch name](../user/project/repository/branches/default.md#instance-level-custom-initial-branch-name) ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225258) in GitLab 13.2). |
| `default_branch_protection` | integer | no | Determine if developers can push to the default branch. Can take: `0` _(not protected, both users with the Developer role or Maintainer role can push new commits and force push)_, `1` _(partially protected, users with the Developer role or Maintainer role can push new commits, but cannot force push)_ or `2` _(fully protected, users with the Developer or Maintainer role cannot push new commits, but users with the Developer or Maintainer role can; no one can force push)_ as a parameter. Default is `2`. |
diff --git a/doc/user/group/import/index.md b/doc/user/group/import/index.md
index 18a88f3aff8..63bc8f8473a 100644
--- a/doc/user/group/import/index.md
+++ b/doc/user/group/import/index.md
@@ -121,6 +121,8 @@ On self-managed GitLab, migrating project resources are not available by default
- Members ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/341886) in GitLab 14.8)
- Merge Requests ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339403) in GitLab 14.5)
- Multiple merge request assignees ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339520) in GitLab 15.3)
+ - Merge request reviewers ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339520) in GitLab 15.3)
+ - Merge request approvers ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339520) in GitLab 15.3)
- Migrate Push Rules ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339403) in GitLab 14.6)
- Pull Requests (including external pull requests) ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339409) in GitLab 14.5)
- Pipeline History ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/339412) in GitLab 14.6)
diff --git a/doc/user/group/settings/group_access_tokens.md b/doc/user/group/settings/group_access_tokens.md
index c3098bb56c2..16f248e3537 100644
--- a/doc/user/group/settings/group_access_tokens.md
+++ b/doc/user/group/settings/group_access_tokens.md
@@ -43,7 +43,8 @@ configured for personal access tokens.
## Create a group access token using UI
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214045) in GitLab 14.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214045) in GitLab 14.7.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/348660) in GitLab 15.3, default expiration of 30 days and default role of Guest is populated in the UI.
To create a group access token:
diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md
index 427c412219a..a561ed9bc5f 100644
--- a/doc/user/profile/personal_access_tokens.md
+++ b/doc/user/profile/personal_access_tokens.md
@@ -40,6 +40,8 @@ Use impersonation tokens to automate authentication as a specific user.
## Create a personal access token
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/348660) in GitLab 15.3, default expiration of 30 days is populated in the UI.
+
You can create as many personal access tokens as you like.
1. In the top-right corner, select your avatar.
diff --git a/doc/user/project/settings/project_access_tokens.md b/doc/user/project/settings/project_access_tokens.md
index 77a53874777..487d9389ecb 100644
--- a/doc/user/project/settings/project_access_tokens.md
+++ b/doc/user/project/settings/project_access_tokens.md
@@ -43,7 +43,8 @@ configured for personal access tokens.
## Create a project access token
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89114) in GitLab 15.1, Owners can select Owner role for project access tokens.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89114) in GitLab 15.1, Owners can select Owner role for project access tokens.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/348660) in GitLab 15.3, default expiration of 30 days and default role of Guest is populated in the UI.
To create a project access token:
diff --git a/glfm_specification/input/gitlab_flavored_markdown/glfm_example_normalizations.yml b/glfm_specification/input/gitlab_flavored_markdown/glfm_example_normalizations.yml
index afa099571d0..d576a8ddb51 100644
--- a/glfm_specification/input/gitlab_flavored_markdown/glfm_example_normalizations.yml
+++ b/glfm_specification/input/gitlab_flavored_markdown/glfm_example_normalizations.yml
@@ -9,19 +9,3 @@
00_uri: &00_uri
- regex: '(href|data-src)(=")(.*?)(test-file\.(png|zip)")'
replacement: '\1\2URI_PREFIX\4'
-07_01_00__gitlab_specific_markdown__footnotes__001:
- html:
- static:
- shared:
- 07_01_00_href: &07_01_00_href
- - regex: '(href)(=")(.+?)(")'
- replacement: '\1\2REF\4'
- 07_01_00_id: &07_01_00_id
- - regex: '(id)(=")(.+?)(")'
- replacement: '\1\2ID\4'
- canonical:
- 07_01_00_href: *07_01_00_href
- 07_01_00_id: *07_01_00_id
- snapshot:
- 07_01_00_href: *07_01_00_href
- 07_01_00_id: *07_01_00_id
diff --git a/lib/gitlab/gitaly_client/server_service.rb b/lib/gitlab/gitaly_client/server_service.rb
index 36bda67c26e..48fd0e66354 100644
--- a/lib/gitlab/gitaly_client/server_service.rb
+++ b/lib/gitlab/gitaly_client/server_service.rb
@@ -26,6 +26,19 @@ module Gitlab
storage_specific(disk_statistics)
end
+ def readiness_check
+ request = Gitaly::ReadinessCheckRequest.new(timeout: GitalyClient.medium_timeout)
+ response = GitalyClient.call(@storage, :server_service, :readiness_check, request, timeout: GitalyClient.default_timeout)
+
+ return { success: true } if response.ok_response
+
+ failed_checks = response.failure_response.failed_checks.map do |failed_check|
+ ["#{failed_check.name}: #{failed_check.error_message}"]
+ end
+
+ { success: false, message: failed_checks.join("\n") }
+ end
+
private
def storage_specific(response)
diff --git a/lib/gitlab/health_checks/gitaly_check.rb b/lib/gitlab/health_checks/gitaly_check.rb
index f5f142c251f..2bd8ea711b5 100644
--- a/lib/gitlab/health_checks/gitaly_check.rb
+++ b/lib/gitlab/health_checks/gitaly_check.rb
@@ -27,17 +27,35 @@ module Gitlab
end
def check(storage_name)
- serv = Gitlab::GitalyClient::HealthCheckService.new(storage_name)
- result = serv.check
+ storage_healthy = healthy(storage_name)
+ unless storage_healthy[:success]
+ return HealthChecks::Result.new(
+ name,
+ storage_healthy[:success],
+ storage_healthy[:message],
+ shard: storage_name
+ )
+ end
+ storage_ready = ready(storage_name)
HealthChecks::Result.new(
name,
- result[:success],
- result[:message],
+ storage_ready[:success],
+ storage_ready[:message],
shard: storage_name
)
end
+ def healthy(storage_name)
+ serv = Gitlab::GitalyClient::HealthCheckService.new(storage_name)
+ serv.check
+ end
+
+ def ready(storage_name)
+ serv = Gitlab::GitalyClient::ServerService.new(storage_name)
+ serv.readiness_check
+ end
+
private
def metric_prefix
diff --git a/qa/qa/page/component/access_tokens.rb b/qa/qa/page/component/access_tokens.rb
index 36c0f8c2f00..3c8a608cdc2 100644
--- a/qa/qa/page/component/access_tokens.rb
+++ b/qa/qa/page/component/access_tokens.rb
@@ -18,6 +18,10 @@ module QA
element :expiry_date_field
end
+ base.view 'app/views/shared/access_tokens/_created_container.html.haml' do
+ element :created_access_token_field
+ end
+
base.view 'app/views/shared/access_tokens/_form.html.haml' do
element :access_token_name_field
element :create_token_button
@@ -32,7 +36,7 @@ module QA
end
base.view 'app/assets/javascripts/access_tokens/components/new_access_token_app.vue' do
- element :created_access_token
+ element :created_access_token_field
end
base.view 'app/assets/javascripts/access_tokens/components/access_token_table_app.vue' do
@@ -53,7 +57,7 @@ module QA
end
def created_access_token
- find_element(:created_access_token, wait: 30).value
+ find_element(:created_access_token_field, wait: 30).value
end
def fill_expiry_date(date)
diff --git a/qa/qa/page/component/ci_badge_link.rb b/qa/qa/page/component/ci_badge_link.rb
index 2ba198621fc..485e363d960 100644
--- a/qa/qa/page/component/ci_badge_link.rb
+++ b/qa/qa/page/component/ci_badge_link.rb
@@ -32,12 +32,12 @@ module QA
super
base.view 'app/assets/javascripts/vue_shared/components/ci_badge_link.vue' do
- element :status_badge
+ element :status_badge_link
end
end
def status_badge
- find_element(:status_badge).text
+ find_element(:status_badge_link).text
end
def completed?(timeout: 60)
diff --git a/qa/qa/page/component/web_ide/modal/create_new_file.rb b/qa/qa/page/component/web_ide/modal/create_new_file.rb
index 7c55f775476..2869bb9c331 100644
--- a/qa/qa/page/component/web_ide/modal/create_new_file.rb
+++ b/qa/qa/page/component/web_ide/modal/create_new_file.rb
@@ -9,7 +9,7 @@ module QA
view 'app/assets/javascripts/ide/components/new_dropdown/modal.vue' do
element :file_name_field, required: true
element :new_file_modal, required: true
- element :template_list
+ element :template_list_content
end
end
end
diff --git a/qa/qa/page/file/shared/commit_message.rb b/qa/qa/page/file/shared/commit_message.rb
index a3658fa11af..12154cdb728 100644
--- a/qa/qa/page/file/shared/commit_message.rb
+++ b/qa/qa/page/file/shared/commit_message.rb
@@ -14,6 +14,10 @@ module QA
element :commit_message_field
end
+ base.view 'app/assets/javascripts/repository/components/last_commit.vue' do
+ element :commit_content
+ end
+
base.view 'app/views/shared/_commit_message_container.html.haml' do
element :commit_message_field
end
diff --git a/qa/qa/page/project/show.rb b/qa/qa/page/project/show.rb
index e048afee8b3..26c2da07b34 100644
--- a/qa/qa/page/project/show.rb
+++ b/qa/qa/page/project/show.rb
@@ -58,8 +58,8 @@ module QA
end
view 'app/assets/javascripts/repository/components/breadcrumbs.vue' do
- element :add_to_tree
- element :new_file_option
+ element :add_to_tree_dropdown
+ element :new_file_menu_item
end
view 'app/assets/javascripts/vue_shared/components/web_ide_link.vue' do
@@ -90,8 +90,8 @@ module QA
end
def create_new_file!
- click_element :add_to_tree
- click_element :new_file_option
+ click_element :add_to_tree_dropdown
+ click_element :new_file_menu_item
end
def fork_project
diff --git a/qa/qa/page/project/web_ide/edit.rb b/qa/qa/page/project/web_ide/edit.rb
index e572569e496..293fcd1e676 100644
--- a/qa/qa/page/project/web_ide/edit.rb
+++ b/qa/qa/page/project/web_ide/edit.rb
@@ -163,7 +163,7 @@ module QA
def create_new_file_from_template(file_name, template)
click_element(:new_file_button, Page::Component::WebIDE::Modal::CreateNewFile)
- within_element(:template_list) do
+ within_element(:template_list_content) do
click_on file_name
rescue Capybara::ElementNotFound
raise ElementNotFound, %Q(Couldn't find file template named "#{file_name}". Please confirm that it is a valid option.)
diff --git a/spec/features/projects/show/user_sees_collaboration_links_spec.rb b/spec/features/projects/show/user_sees_collaboration_links_spec.rb
index fb2f0539558..1440db141a6 100644
--- a/spec/features/projects/show/user_sees_collaboration_links_spec.rb
+++ b/spec/features/projects/show/user_sees_collaboration_links_spec.rb
@@ -39,7 +39,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
# The dropdown above the tree
page.within('.repo-breadcrumb') do
- find('.qa-add-to-tree').click # rubocop:disable QA/SelectorUsage
+ find('[data-testid="add-to-tree"]').click
aggregate_failures 'dropdown links above the repo tree' do
expect(page).to have_link('New file')
@@ -71,7 +71,7 @@ RSpec.describe 'Projects > Show > Collaboration links', :js do
find_new_menu_toggle.click
end
- expect(page).not_to have_selector('.qa-add-to-tree') # rubocop:disable QA/SelectorUsage
+ expect(page).not_to have_selector('[data-testid="add-to-tree"]')
expect(page).not_to have_link('Web IDE')
end
diff --git a/spec/frontend/access_tokens/components/new_access_token_app_spec.js b/spec/frontend/access_tokens/components/new_access_token_app_spec.js
index 9ccadbebf7a..008096f02e9 100644
--- a/spec/frontend/access_tokens/components/new_access_token_app_spec.js
+++ b/spec/frontend/access_tokens/components/new_access_token_app_spec.js
@@ -78,7 +78,6 @@ describe('~/access_tokens/components/new_access_token_app', () => {
.findByLabelText(sprintf(__('Your new %{accessTokenType}'), { accessTokenType }))
.attributes();
expect(inputAttributes).toMatchObject({
- class: expect.stringContaining('qa-created-access-token'),
'data-qa-selector': 'created_access_token_field',
});
});
diff --git a/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap b/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap
index cb56f392ec9..01494cb6a24 100644
--- a/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap
+++ b/spec/frontend/repository/components/__snapshots__/last_commit_spec.js.snap
@@ -20,7 +20,8 @@ exports[`Repository last commit component renders commit widget 1`] = `
class="commit-detail flex-list gl-display-flex gl-justify-content-space-between gl-align-items-flex-start gl-flex-grow-1 gl-min-w-0"
>
/push .*?/ }))
+ .once
+ end
+ end
+
+ context 'with issue events' do
+ let(:issues_sample_data) { create(:issue).to_hook_data(user) }
+
+ it "adds thread key for issue events" do
+ expect(chat_integration.execute(issues_sample_data)).to be(true)
+
+ expect(WebMock).to have_requested(:post, webhook_url)
+ .with(query: hash_including({ "threadKey" => /issue .*?/ }))
+ .once
+ end
+ end
+
+ context 'with merge events' do
+ let(:merge_sample_data) { create(:merge_request).to_hook_data(user) }
+
+ it "adds thread key for merge events" do
+ expect(chat_integration.execute(merge_sample_data)).to be(true)
+
+ expect(WebMock).to have_requested(:post, webhook_url)
+ .with(query: hash_including({ "threadKey" => /merge request .*?/ }))
+ .once
+ end
+ end
+
+ context 'with wiki page events' do
+ let(:wiki_page_sample_data) do
+ Gitlab::DataBuilder::WikiPage.build(create(:wiki_page, message: 'foo'), user, 'create')
+ end
+
+ it "adds thread key for wiki page events" do
+ expect(chat_integration.execute(wiki_page_sample_data)).to be(true)
+
+ expect(WebMock).to have_requested(:post, webhook_url)
+ .with(query: hash_including({ "threadKey" => /wiki_page .*?/ }))
+ .once
+ end
+ end
+
+ context 'with pipeline events' do
+ let(:pipeline) do
+ create(:ci_pipeline, :failed, project: project, sha: project.commit.sha, ref: project.default_branch)
+ end
+
+ let(:pipeline_sample_data) { Gitlab::DataBuilder::Pipeline.build(pipeline) }
+
+ it "adds thread key for pipeline events" do
+ expect(chat_integration.execute(pipeline_sample_data)).to be(true)
+
+ expect(WebMock).to have_requested(:post, webhook_url)
+ .with(query: hash_including({ "threadKey" => /pipeline .*?/ }))
+ .once
+ end
+ end
+ end
+
+ describe "Note events" do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository, creator: user) }
+
+ before do
+ allow(chat_integration).to receive_messages(
+ project: project,
+ project_id: project.id,
+ webhook: webhook_url
+ )
+
+ WebMock.stub_request(:post, webhook_url_regex)
+ end
+
+ context 'when commit comment event executed' do
+ let(:commit_note) do
+ create(:note_on_commit, author: user,
+ project: project,
+ commit_id: project.repository.commit.id,
+ note: 'a comment on a commit')
+ end
+
+ it "adds thread key" do
+ data = Gitlab::DataBuilder::Note.build(commit_note, user)
+
+ expect(chat_integration.execute(data)).to be(true)
+
+ expect(WebMock).to have_requested(:post, webhook_url)
+ .with(query: hash_including({ "threadKey" => /commit .*?/ }))
+ .once
+ end
+ end
+
+ context 'when merge request comment event executed' do
+ let(:merge_request_note) do
+ create(:note_on_merge_request, project: project,
+ note: "merge request note")
+ end
+
+ it "adds thread key" do
+ data = Gitlab::DataBuilder::Note.build(merge_request_note, user)
+
+ expect(chat_integration.execute(data)).to be(true)
+
+ expect(WebMock).to have_requested(:post, webhook_url)
+ .with(query: hash_including({ "threadKey" => /merge request .*?/ }))
+ .once
+ end
+ end
+
+ context 'when issue comment event executed' do
+ let(:issue_note) do
+ create(:note_on_issue, project: project, note: "issue note")
+ end
+
+ it "adds thread key" do
+ data = Gitlab::DataBuilder::Note.build(issue_note, user)
+
+ expect(chat_integration.execute(data)).to be(true)
+
+ expect(WebMock).to have_requested(:post, webhook_url)
+ .with(query: hash_including({ "threadKey" => /issue .*?/ }))
+ .once
+ end
+ end
+
+ context 'when snippet comment event executed' do
+ let(:snippet_note) do
+ create(:note_on_project_snippet, project: project,
+ note: "snippet note")
+ end
+
+ it "adds thread key" do
+ data = Gitlab::DataBuilder::Note.build(snippet_note, user)
+
+ expect(chat_integration.execute(data)).to be(true)
+
+ expect(WebMock).to have_requested(:post, webhook_url)
+ .with(query: hash_including({ "threadKey" => /snippet .*?/ }))
+ .once
+ end
+ end
+ end
end
diff --git a/spec/requests/health_controller_spec.rb b/spec/requests/health_controller_spec.rb
index f70faf5bb9c..fb1c0f85215 100644
--- a/spec/requests/health_controller_spec.rb
+++ b/spec/requests/health_controller_spec.rb
@@ -127,6 +127,10 @@ RSpec.describe HealthController do
end
it 'responds with readiness checks data' do
+ expect_next_instance_of(Gitlab::GitalyClient::ServerService) do |service|
+ expect(service).to receive(:readiness_check).and_return({ success: true })
+ end
+
subject
expect(json_response['db_check']).to contain_exactly({ 'status' => 'ok' })
diff --git a/spec/support/shared_contexts/markdown_snapshot_shared_examples.rb b/spec/support/shared_contexts/markdown_snapshot_shared_examples.rb
index 3eb43cee0af..57d31be8792 100644
--- a/spec/support/shared_contexts/markdown_snapshot_shared_examples.rb
+++ b/spec/support/shared_contexts/markdown_snapshot_shared_examples.rb
@@ -10,6 +10,14 @@ RSpec.shared_context 'with API::Markdown Snapshot shared context' do |glfm_speci
let_it_be(:user) { create(:user) }
let_it_be(:api_url) { api('/markdown', user) }
+ before do
+ # Set 'GITLAB_TEST_FOOTNOTE_ID' in order to override random number generation in
+ # Banzai::Filter::FootnoteFilter#random_number, and thus avoid the need to
+ # perform normalization on the value. See:
+ # https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/#normalization
+ stub_env('GITLAB_TEST_FOOTNOTE_ID', 42)
+ end
+
markdown_examples, html_examples = %w[markdown.yml html.yml].map do |file_name|
yaml = File.read("#{glfm_specification_dir}/example_snapshots/#{file_name}")
YAML.safe_load(yaml, symbolize_names: true, aliases: true)
diff --git a/spec/support/shared_examples/models/chat_integration_shared_examples.rb b/spec/support/shared_examples/models/chat_integration_shared_examples.rb
index 30d8517943c..6cfeeabc952 100644
--- a/spec/support/shared_examples/models/chat_integration_shared_examples.rb
+++ b/spec/support/shared_examples/models/chat_integration_shared_examples.rb
@@ -36,6 +36,7 @@ RSpec.shared_examples "chat integration" do |integration_name|
let_it_be_with_reload(:project) { create(:project, :repository) }
let(:webhook_url) { "https://example.gitlab.com/" }
+ let(:webhook_url_regex) { /\A#{webhook_url}.*/ }
before do
allow(subject).to receive_messages(
@@ -45,7 +46,7 @@ RSpec.shared_examples "chat integration" do |integration_name|
webhook: webhook_url
)
- WebMock.stub_request(:post, webhook_url)
+ WebMock.stub_request(:post, webhook_url_regex)
end
shared_examples "triggered #{integration_name} integration" do |branches_to_be_notified: nil|
@@ -57,7 +58,7 @@ RSpec.shared_examples "chat integration" do |integration_name|
result = subject.execute(sample_data)
expect(result).to be(true)
- expect(WebMock).to have_requested(:post, webhook_url).once.with { |req|
+ expect(WebMock).to have_requested(:post, webhook_url_regex).once.with { |req|
json_body = Gitlab::Json.parse(req.body).with_indifferent_access
expect(json_body).to include(payload)
}
@@ -73,7 +74,7 @@ RSpec.shared_examples "chat integration" do |integration_name|
result = subject.execute(sample_data)
expect(result).to be_falsy
- expect(WebMock).not_to have_requested(:post, webhook_url)
+ expect(WebMock).not_to have_requested(:post, webhook_url_regex)
end
end
diff --git a/spec/workers/repository_check/dispatch_worker_spec.rb b/spec/workers/repository_check/dispatch_worker_spec.rb
index 829abc7d895..146228c0852 100644
--- a/spec/workers/repository_check/dispatch_worker_spec.rb
+++ b/spec/workers/repository_check/dispatch_worker_spec.rb
@@ -22,6 +22,10 @@ RSpec.describe RepositoryCheck::DispatchWorker do
end
it 'dispatches work to RepositoryCheck::BatchWorker' do
+ expect_next_instance_of(Gitlab::GitalyClient::ServerService) do |service|
+ expect(service).to receive(:readiness_check).and_return({ success: true })
+ end
+
expect(RepositoryCheck::BatchWorker).to receive(:perform_async).at_least(:once)
subject.perform