Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml1
-rw-r--r--.gitlab/issue_templates/Empty state.md80
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/assets/javascripts/boards/components/board_card.vue2
-rw-r--r--app/assets/javascripts/boards/components/issue_board_filtered_search.vue1
-rw-r--r--app/controllers/projects/ci/pipeline_editor_controller.rb3
-rw-r--r--app/finders/tags_finder.rb31
-rw-r--r--app/services/ci/job_artifacts/destroy_batch_service.rb10
-rw-r--r--config/feature_flags/development/tag_list_keyset_pagination.yml8
-rw-r--r--data/deprecations/14-0-nfs-fot-git-repository-storage.yml2
-rw-r--r--data/deprecations/14-2-deprecation-task-runner.yml2
-rw-r--r--doc/.vale/gitlab/spelling-exceptions.txt1
-rw-r--r--doc/integration/jira/dvcs.md4
-rw-r--r--doc/user/discussions/index.md11
-rw-r--r--lib/api/tags.rb11
-rw-r--r--lib/gitlab/database/load_balancing/connection_proxy.rb7
-rw-r--r--lib/gitlab/git.rb1
-rw-r--r--lib/gitlab/pagination/gitaly_keyset_pager.rb4
-rw-r--r--lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb6
-rw-r--r--locale/gitlab.pot6
-rw-r--r--scripts/rspec_helpers.sh1
-rw-r--r--spec/controllers/projects/ci/pipeline_editor_controller_spec.rb9
-rw-r--r--spec/controllers/projects/pipelines_controller_spec.rb2
-rw-r--r--spec/finders/tags_finder_spec.rb70
-rw-r--r--spec/frontend/boards/components/board_card_spec.js4
-rw-r--r--spec/frontend/boards/mock_data.js1
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap (renamed from spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/delete_button_spec.js (renamed from spec/frontend/registry/explorer/components/delete_button_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/delete_image_spec.js (renamed from spec/frontend/registry/explorer/components/delete_image_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap (renamed from spec/frontend/registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_alert_spec.js (renamed from spec/frontend/registry/explorer/components/details_page/delete_alert_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_modal_spec.js (renamed from spec/frontend/registry/explorer/components/details_page/delete_modal_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js (renamed from spec/frontend/registry/explorer/components/details_page/details_header_spec.js)2
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/empty_state_spec.js (renamed from spec/frontend/registry/explorer/components/details_page/empty_state_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert_spec.js (renamed from spec/frontend/registry/explorer/components/details_page/partial_cleanup_alert_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/status_alert_spec.js (renamed from spec/frontend/registry/explorer/components/details_page/status_alert_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js (renamed from spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js (renamed from spec/frontend/registry/explorer/components/details_page/tags_list_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js (renamed from spec/frontend/registry/explorer/components/details_page/tags_loader_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap (renamed from spec/frontend/registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap (renamed from spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status_spec.js (renamed from spec/frontend/registry/explorer/components/list_page/cleanup_status_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cli_commands_spec.js (renamed from spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state_spec.js (renamed from spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_row_spec.js (renamed from spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_spec.js (renamed from spec/frontend/registry/explorer/components/list_page/image_list_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state_spec.js (renamed from spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js (renamed from spec/frontend/registry/explorer/components/list_page/registry_header_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/registry_breadcrumb_spec.js (renamed from spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js (renamed from spec/frontend/registry/explorer/mock_data.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js (renamed from spec/frontend/registry/explorer/pages/details_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/pages/index_spec.js (renamed from spec/frontend/registry/explorer/pages/index_spec.js)0
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js (renamed from spec/frontend/registry/explorer/pages/list_spec.js)2
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/stubs.js (renamed from spec/frontend/registry/explorer/stubs.js)0
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/shared/mocks.js (renamed from spec/frontend/registry/shared/mocks.js)0
-rw-r--r--spec/frontend/packages_and_registries/shared/stubs.js (renamed from spec/frontend/registry/shared/stubs.js)0
-rw-r--r--spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb132
-rw-r--r--spec/requests/api/tags_spec.rb53
-rw-r--r--spec/support/database/cross-database-modification-allowlist.yml2
-rw-r--r--spec/support/flaky_tests.rb2
-rw-r--r--spec/support/shared_examples/requests/api/status_shared_examples.rb18
66 files changed, 412 insertions, 89 deletions
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index 1671a1da714..1fb1c887e56 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -579,6 +579,7 @@ rspec:skipped-flaky-tests-report:
variables:
SKIPPED_FLAKY_TESTS_REPORT: skipped_flaky_tests_report.txt
before_script:
+ - 'echo "SKIP_FLAKY_TESTS_AUTOMATICALLY: $SKIP_FLAKY_TESTS_AUTOMATICALLY"'
- mkdir -p rspec_flaky
script:
- find rspec_flaky/ -type f -name 'skipped_flaky_tests_*_report.txt' -exec cat {} + >> "${SKIPPED_FLAKY_TESTS_REPORT}"
diff --git a/.gitlab/issue_templates/Empty state.md b/.gitlab/issue_templates/Empty state.md
new file mode 100644
index 00000000000..d92ea8522e1
--- /dev/null
+++ b/.gitlab/issue_templates/Empty state.md
@@ -0,0 +1,80 @@
+<!-- Before implementing a new empty state solution, make sure to read the
+Empty State region docs in Pajamas: https://design.gitlab.com/regions/empty-states -->
+
+## Description
+
+<!-- Describe the solution you're proposing for your empty state region.
+Include links to user research (if applicable). -->
+
+## Location
+
+<!-- Provide a link and location of the new empty state solution.
+For example: https://gitlab.com/gitlab-org/gitlab-services/design.gitlab.com/-/issues -->
+
+## Use case
+
+<!-- What is the use case for the solution you're proposing?
+Read the Empty State docs and select the use case below: https://design.gitlab.com/regions/empty-states -->
+
+- [ ] Blank content
+- [ ] Empty search results
+- [ ] Configuration required
+- [ ] Higher tier
+
+## Checklist
+
+<!-- Follow the steps below that correspond with the use case selected above.
+Follow the steps to complete this issue -->
+
+### Blank content
+
+- [ ] The solution follows the `Blank content` specifications [in Pajamas](https://design.gitlab.com/regions/empty-states#blank-content).
+- [ ] Follow the instructions from the [`After merge` section](#after-merge) below to add Snowplow tracking.
+
+### Empty search results
+
+- [ ] The solution follows the `Empty search results` specifications [in Pajamas](https://design.gitlab.com/regions/empty-states#empty-search-results).
+- [ ] Follow the instructions from the [`After merge` section](#after-merge) below to add Snowplow tracking.
+
+### Configuration required
+
+- [ ] The solution follows the `Configuration required` specifications [in Pajamas](https://design.gitlab.com/regions/empty-states#configuration-required).
+- [ ] Ask a [Growth product manager or Designer](https://about.gitlab.com/handbook/engineering/development/growth/#stable-counterparts) to review your solution.
+- [ ] Is your solution introducing a new empty states or modifying an existing one?
+ - [ ] Introducing a new empty state: Follow the instructions from the [`After merge` section](#after-merge) below to add Snowplow tracking.
+ - [ ] Modifying an existing empty state: Follow the [`Experimentation` process](#experimentation) below. _Note_: If the empty state you want to replace hasn't been updated in a long time, doesn't pitch the value of the feature, or does not contain a next step action CTA, then we recommend you skip the experimentation process to implement and add tracking to your new empty state.
+
+<!-- IF experimentation -->
+#### Experimentation
+
+- [ ] Collaborate with a [Growth product manager](https://about.gitlab.com/handbook/engineering/development/growth/#stable-counterparts) to help you determine if you can validate your solution through an experiment on SaaS.
+- [ ] If an experiment is possible, create an issue using the [experiment idea template](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Experiment%20Idea) and follow the template intructions. Otherwise, follow the instructions from the [`After merge` section](#after-merge) below to add Snowplow tracking.
+- [ ] Ask a [Growth product manager or Designer](https://about.gitlab.com/handbook/engineering/development/growth/#stable-counterparts) to review your experiment set-up.
+- [ ] Implement and monitor the experiment following the [implementation guide](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/experiment_guide/gitlab_experiment.md#implement-an-experiment).
+- [ ] Review and discuss the findings.
+- [ ] Add the findings to the [Growth experimentation knowledge](https://about.gitlab.com/direction/growth/#growth-experiments-knowledge-base---concluded-experiments).
+
+### Higher tier
+
+- [ ] The solution follows the `Higher tier` specifications [in Pajamas](https://design.gitlab.com/regions/empty-states#higher-tier).
+- [ ] Ask a Product Manager or Designer from the [Conversion group](https://about.gitlab.com/handbook/engineering/development/growth/conversion/#group-members) to review your solution.
+- [ ] Is your solution introducing a new empty states or modifying an existing one?
+ - [ ] Introducing a new empty state: follow the instructions from the [`After merge` section](#after-merge) below to add Snowplow tracking.
+ - [ ] Modifying an existing empty state, follow the [`Experimentation` process](#experimentation) below.
+
+<!-- IF experimentation -->
+#### Experimentation
+
+- [ ] Collaborate with a [Growth product manager](https://about.gitlab.com/handbook/engineering/development/growth/#stable-counterparts) to help you determine if you can validate your solution through an experiment on SaaS.
+- [ ] If an experiment is possible, create an issue using the [experiment idea template](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Experiment%20Idea) and follow the template intructions. Otherwise, follow the instructions from the [`After merge` section](#after-merge) below to add Snowplow tracking.
+- [ ] Add a ~"Category:Conversion Experiment" label to the experiment idea issue.
+- [ ] Ask a Product Manager or Designer from the [Conversion group](https://about.gitlab.com/handbook/engineering/development/growth/conversion/#group-members) to review your experiment set-up.
+- [ ] Implement and monitor the experiment following the [implementation guide](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/development/experiment_guide/gitlab_experiment.md#implement-an-experiment) .
+- [ ] Review and discuss the findings.
+- [ ] Add the findings to the [Growth experimentation knowledge](https://about.gitlab.com/direction/growth/#growth-experiments-knowledge-base---concluded-experiments).
+
+
+## After merge
+
+- [ ] Use the `Snowplow event tracking` [issue template](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Snowplow%20event%20tracking) and open an issue to add Snowplow event tracking to your new empty state solution.
+ - [ ] Add your ~devops:: and ~group:: labels to the new issue.
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index bc2c01b8e1f..5a277f5259e 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-8f04e23b9f004d70635aaeecd30d837a584572f8
+284a2395b24fcbf1614f486a190379bf42eac6a6
diff --git a/app/assets/javascripts/boards/components/board_card.vue b/app/assets/javascripts/boards/components/board_card.vue
index 1e780f9ef84..563bed6a6b8 100644
--- a/app/assets/javascripts/boards/components/board_card.vue
+++ b/app/assets/javascripts/boards/components/board_card.vue
@@ -83,7 +83,7 @@ export default {
:data-item-path="item.referencePath"
data-testid="board_card"
class="board-card gl-p-5 gl-rounded-base"
- @mouseup="toggleIssue($event)"
+ @click="toggleIssue($event)"
>
<board-card-inner :list="list" :item="item" :update-filters="true" />
</li>
diff --git a/app/assets/javascripts/boards/components/issue_board_filtered_search.vue b/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
index dd4b2b23efc..bdb9c2be836 100644
--- a/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
+++ b/app/assets/javascripts/boards/components/issue_board_filtered_search.vue
@@ -160,7 +160,6 @@ export default {
icon: 'issues',
title: type,
type: 'types',
- operators: [{ value: '=', description: is }],
token: GlFilteredSearchToken,
unique: true,
options: [
diff --git a/app/controllers/projects/ci/pipeline_editor_controller.rb b/app/controllers/projects/ci/pipeline_editor_controller.rb
index 70a1a855e91..600516f95a2 100644
--- a/app/controllers/projects/ci/pipeline_editor_controller.rb
+++ b/app/controllers/projects/ci/pipeline_editor_controller.rb
@@ -19,8 +19,9 @@ class Projects::Ci::PipelineEditorController < Projects::ApplicationController
end
def setup_walkthrough_experiment
- experiment(:pipeline_editor_walkthrough, actor: current_user) do |e|
+ experiment(:pipeline_editor_walkthrough, namespace: @project.namespace, sticky_to: current_user) do |e|
e.candidate {}
+ e.record!
end
end
end
diff --git a/app/finders/tags_finder.rb b/app/finders/tags_finder.rb
index 36ca2c7f281..6bc5419e704 100644
--- a/app/finders/tags_finder.rb
+++ b/app/finders/tags_finder.rb
@@ -5,9 +5,36 @@ class TagsFinder < GitRefsFinder
super(repository, params)
end
- def execute
- tags = repository.tags_sorted_by(sort)
+ def execute(gitaly_pagination: false)
+ tags = if gitaly_pagination
+ repository.tags_sorted_by(sort, pagination_params)
+ else
+ repository.tags_sorted_by(sort)
+ end
by_search(tags)
+
+ rescue ArgumentError => e
+ raise Gitlab::Git::InvalidPageToken, "Invalid page token: #{page_token}" if e.message.include?('page token')
+
+ raise
+ end
+
+ def total
+ repository.tag_count
+ end
+
+ private
+
+ def per_page
+ params[:per_page].presence
+ end
+
+ def page_token
+ "#{Gitlab::Git::TAG_REF_PREFIX}#{@params[:page_token]}" if params[:page_token]
+ end
+
+ def pagination_params
+ { limit: per_page, page_token: page_token }
end
end
diff --git a/app/services/ci/job_artifacts/destroy_batch_service.rb b/app/services/ci/job_artifacts/destroy_batch_service.rb
index 8faecfbd4ee..866b40c32d8 100644
--- a/app/services/ci/job_artifacts/destroy_batch_service.rb
+++ b/app/services/ci/job_artifacts/destroy_batch_service.rb
@@ -26,12 +26,15 @@ module Ci
def execute(update_stats: true)
return success(destroyed_artifacts_count: 0, statistics_updates: {}) if @job_artifacts.empty?
+ destroy_related_records(@job_artifacts)
+
Ci::DeletedObject.transaction do
Ci::DeletedObject.bulk_import(@job_artifacts, @pick_up_at)
Ci::JobArtifact.id_in(@job_artifacts.map(&:id)).delete_all
- destroy_related_records(@job_artifacts)
end
+ after_batch_destroy_hook(@job_artifacts)
+
# This is executed outside of the transaction because it depends on Redis
update_project_statistics! if update_stats
increment_monitoring_statistics(artifacts_count, artifacts_bytes)
@@ -43,9 +46,12 @@ module Ci
private
- # This method is implemented in EE and it must do only database work
+ # Overriden in EE
def destroy_related_records(artifacts); end
+ # Overriden in EE
+ def after_batch_destroy_hook(artifacts); end
+
# using ! here since this can't be called inside a transaction
def update_project_statistics!
affected_project_statistics.each do |project, delta|
diff --git a/config/feature_flags/development/tag_list_keyset_pagination.yml b/config/feature_flags/development/tag_list_keyset_pagination.yml
new file mode 100644
index 00000000000..54bd96d82cf
--- /dev/null
+++ b/config/feature_flags/development/tag_list_keyset_pagination.yml
@@ -0,0 +1,8 @@
+---
+name: tag_list_keyset_pagination
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/74239
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345595
+milestone: '14.5'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/data/deprecations/14-0-nfs-fot-git-repository-storage.yml b/data/deprecations/14-0-nfs-fot-git-repository-storage.yml
index 3127720e709..6884f6e3f69 100644
--- a/data/deprecations/14-0-nfs-fot-git-repository-storage.yml
+++ b/data/deprecations/14-0-nfs-fot-git-repository-storage.yml
@@ -19,4 +19,4 @@
documentation_url: # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
- removal_date: "2022-06-22" # (optional - may be required in the future) YYYY-MM-DD format - the date of the milestone release when this feature is planned to be removed
+ removal_date: "2022-05-22" # (optional - may be required in the future) YYYY-MM-DD format - the date of the milestone release when this feature is planned to be removed
diff --git a/data/deprecations/14-2-deprecation-task-runner.yml b/data/deprecations/14-2-deprecation-task-runner.yml
index 3c600e5a0bf..52fd1f0f288 100644
--- a/data/deprecations/14-2-deprecation-task-runner.yml
+++ b/data/deprecations/14-2-deprecation-task-runner.yml
@@ -13,4 +13,4 @@
documentation_url: # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg
- removal_date: "2021-10-22" # (optional - may be required in the future) YYYY-MM-DD format - the date of the milestone release when this feature is planned to be removed
+ removal_date: "2021-11-22" # (optional - may be required in the future) YYYY-MM-DD format - the date of the milestone release when this feature is planned to be removed
diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt
index f1caf49e9aa..df228e61278 100644
--- a/doc/.vale/gitlab/spelling-exceptions.txt
+++ b/doc/.vale/gitlab/spelling-exceptions.txt
@@ -187,6 +187,7 @@ downvotes
Dpl
Dreamweaver
Ecto
+ElastiCache
Elasticsearch
enablement
enqueued
diff --git a/doc/integration/jira/dvcs.md b/doc/integration/jira/dvcs.md
index 68c1f1410ea..2b7cc5ff0a6 100644
--- a/doc/integration/jira/dvcs.md
+++ b/doc/integration/jira/dvcs.md
@@ -111,12 +111,12 @@ it completes, refreshes every 60 minutes:
1. To create a new integration, select the appropriate value for **Host**:
- *For Jira versions 8.14 and later:* Select **GitLab** or
**GitLab Self-Managed**.
- - *For Jira versions 8.13 and earlier:* Select **GitHub Enterprise**.
+ - *For Jira Cloud or Jira versions 8.13 and earlier:* Select **GitHub Enterprise**.
1. For **Team or User Account**, enter either:
- *For Jira versions 8.14 and later:*
- The relative path of a top-level GitLab group that
[the GitLab user](#configure-a-gitlab-application-for-dvcs) has access to.
- - *For Jira versions 8.13 and earlier:*
+ - *For Jira Cloud or Jira versions 8.13 and earlier:*
- The relative path of a top-level GitLab group that
[the GitLab user](#configure-a-gitlab-application-for-dvcs) has access to.
- The relative path of your personal namespace.
diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md
index c0227cca94d..4d6cff96169 100644
--- a/doc/user/discussions/index.md
+++ b/doc/user/discussions/index.md
@@ -10,7 +10,7 @@ type: reference, howto
GitLab encourages communication through comments, threads, and
[code suggestions](../project/merge_requests/reviews/suggestions.md).
-There are two types of comments:
+Two types of comments are available:
- A standard comment.
- A comment in a thread, which can be [resolved](#resolve-a-thread).
@@ -141,8 +141,6 @@ You can also make an [entire issue confidential](../project/issues/confidential_
## Show only comments
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/26723) in GitLab 11.5.
-
For issues and merge requests with many comments, you can filter the page to show comments only.
1. Open a merge request's **Discussion** tab, or epic or issue's **Overview** tab.
@@ -170,8 +168,6 @@ You can assign an issue to a user who made a comment.
## Create a thread by replying to a standard comment
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/30299) in GitLab 11.9.
-
When you reply to a standard comment, you create a thread.
Prerequisites:
@@ -185,7 +181,7 @@ To create a thread by replying to a comment:
![Reply to comment button](img/reply_to_comment_button.png)
- The reply area is displayed.
+ The reply section is displayed.
1. Enter your reply.
1. Select **Comment** or **Add comment now** (depending on where in the UI you are replying).
@@ -214,8 +210,7 @@ A threaded comment is created.
## Resolve a thread
-> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5022) in GitLab 8.11.
-> - Resolving comments individually was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/28750) in GitLab 13.6.
+> Resolving comments individually was [removed](https://gitlab.com/gitlab-org/gitlab/-/issues/28750) in GitLab 13.6.
In a merge request, you can resolve a thread when you want to finish a conversation.
diff --git a/lib/api/tags.rb b/lib/api/tags.rb
index 043d6d77f93..1b37d38ef06 100644
--- a/lib/api/tags.rb
+++ b/lib/api/tags.rb
@@ -21,14 +21,17 @@ module API
optional :order_by, type: String, values: %w[name updated], default: 'updated',
desc: 'Return tags ordered by `name` or `updated` fields.'
optional :search, type: String, desc: 'Return list of tags matching the search criteria'
+ optional :page_token, type: String, desc: 'Name of tag to start the paginaition from'
use :pagination
end
get ':id/repository/tags', feature_category: :source_code_management, urgency: :low do
- tags = ::TagsFinder.new(user_project.repository,
+ tags_finder = ::TagsFinder.new(user_project.repository,
sort: "#{params[:order_by]}_#{params[:sort]}",
- search: params[:search]).execute
+ search: params[:search],
+ page_token: params[:page_token],
+ per_page: params[:per_page])
- paginated_tags = paginate(::Kaminari.paginate_array(tags))
+ paginated_tags = Gitlab::Pagination::GitalyKeysetPager.new(self, user_project).paginate(tags_finder)
if Feature.enabled?(:api_caching_tags, user_project, type: :development)
present_cached paginated_tags, with: Entities::Tag, project: user_project, cache_context: -> (_tag) { user_project.cache_key }
@@ -36,6 +39,8 @@ module API
present paginated_tags, with: Entities::Tag, project: user_project
end
+ rescue Gitlab::Git::InvalidPageToken => e
+ unprocessable_entity!(e.message)
rescue Gitlab::Git::CommandError
service_unavailable!
end
diff --git a/lib/gitlab/database/load_balancing/connection_proxy.rb b/lib/gitlab/database/load_balancing/connection_proxy.rb
index 9c51fa21936..a91df2eccdd 100644
--- a/lib/gitlab/database/load_balancing/connection_proxy.rb
+++ b/lib/gitlab/database/load_balancing/connection_proxy.rb
@@ -13,15 +13,14 @@ module Gitlab
WriteInsideReadOnlyTransactionError = Class.new(StandardError)
READ_ONLY_TRANSACTION_KEY = :load_balacing_read_only_transaction
- # The load balancer is intentionally not exposed since the returned instance
- # might be different `model.connection.load_balancer` vs `model.load_balancer`
+ # The load balancer returned by connection might be different
+ # between `model.connection.load_balancer` vs `model.load_balancer`
#
# The used `model.connection` is dependent on `use_model_load_balancing`.
# See more in: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/73949.
#
# Always use `model.load_balancer` or `model.sticking`.
- #
- # attr_reader :load_balancer
+ attr_reader :load_balancer
# These methods perform writes after which we need to stick to the
# primary.
diff --git a/lib/gitlab/git.rb b/lib/gitlab/git.rb
index a1855132b0c..2da30b88d55 100644
--- a/lib/gitlab/git.rb
+++ b/lib/gitlab/git.rb
@@ -17,6 +17,7 @@ module Gitlab
OSError = Class.new(BaseError)
UnknownRef = Class.new(BaseError)
CommandTimedOut = Class.new(CommandError)
+ InvalidPageToken = Class.new(BaseError)
class << self
include Gitlab::EncodingHelper
diff --git a/lib/gitlab/pagination/gitaly_keyset_pager.rb b/lib/gitlab/pagination/gitaly_keyset_pager.rb
index a16bf7a379c..99a3145104a 100644
--- a/lib/gitlab/pagination/gitaly_keyset_pager.rb
+++ b/lib/gitlab/pagination/gitaly_keyset_pager.rb
@@ -30,6 +30,8 @@ module Gitlab
if finder.is_a?(BranchesFinder)
Feature.enabled?(:branch_list_keyset_pagination, project, default_enabled: :yaml)
+ elsif finder.is_a?(TagsFinder)
+ Feature.enabled?(:tag_list_keyset_pagination, project, default_enabled: :yaml)
elsif finder.is_a?(::Repositories::TreeFinder)
Feature.enabled?(:repository_tree_gitaly_pagination, project, default_enabled: :yaml)
else
@@ -42,6 +44,8 @@ module Gitlab
if finder.is_a?(BranchesFinder)
Feature.enabled?(:branch_list_keyset_pagination, project, default_enabled: :yaml)
+ elsif finder.is_a?(TagsFinder)
+ Feature.enabled?(:tag_list_keyset_pagination, project, default_enabled: :yaml)
elsif finder.is_a?(::Repositories::TreeFinder)
Feature.enabled?(:repository_tree_gitaly_pagination, project, default_enabled: :yaml)
else
diff --git a/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb b/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb
index b389ac368db..f31262bfcc9 100644
--- a/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb
+++ b/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job.rb
@@ -84,7 +84,11 @@ module Gitlab
Sidekiq.redis do |redis|
redis.multi do |multi|
job_wal_locations.each do |connection_name, location|
- multi.eval(LUA_SET_WAL_SCRIPT, keys: [wal_location_key(connection_name)], argv: [location, pg_wal_lsn_diff(connection_name).to_i, WAL_LOCATION_TTL])
+ multi.eval(
+ LUA_SET_WAL_SCRIPT,
+ keys: [wal_location_key(connection_name)],
+ argv: [location, pg_wal_lsn_diff(connection_name).to_i, WAL_LOCATION_TTL]
+ )
end
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index c4b0d77b128..792011abb1a 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -20748,9 +20748,6 @@ msgstr ""
msgid "Licenses|Detected licenses that are out-of-compliance with the project's assigned policies"
msgstr ""
-msgid "Licenses|Disallow Merge request if detected and will instruct the developer to remove"
-msgstr ""
-
msgid "Licenses|Displays licenses detected in the project, based on the %{linkStart}latest successful%{linkEnd} scan"
msgstr ""
@@ -20778,6 +20775,9 @@ msgstr ""
msgid "Licenses|The license list details information about the licenses used within your project."
msgstr ""
+msgid "Licenses|Unacceptable license, if detected it will disallow a merge request until it's removed"
+msgstr ""
+
msgid "Licenses|View license details for your project"
msgstr ""
diff --git a/scripts/rspec_helpers.sh b/scripts/rspec_helpers.sh
index 51ccf9895c2..8714f1c0060 100644
--- a/scripts/rspec_helpers.sh
+++ b/scripts/rspec_helpers.sh
@@ -159,6 +159,7 @@ function rspec_paralellized_job() {
fi
echo "KNAPSACK_TEST_FILE_PATTERN: ${KNAPSACK_TEST_FILE_PATTERN}"
+ echo "SKIP_FLAKY_TESTS_AUTOMATICALLY: ${SKIP_FLAKY_TESTS_AUTOMATICALLY}"
if [[ -d "ee/" ]]; then
export KNAPSACK_GENERATE_REPORT="true"
diff --git a/spec/controllers/projects/ci/pipeline_editor_controller_spec.rb b/spec/controllers/projects/ci/pipeline_editor_controller_spec.rb
index 7952c9774af..d55aad20689 100644
--- a/spec/controllers/projects/ci/pipeline_editor_controller_spec.rb
+++ b/spec/controllers/projects/ci/pipeline_editor_controller_spec.rb
@@ -42,13 +42,10 @@ RSpec.describe Projects::Ci::PipelineEditorController do
project.add_developer(user)
end
- it 'tracks the assignment', :experiment do
- expect(experiment(:pipeline_editor_walkthrough))
- .to track(:assignment)
- .with_context(actor: user)
- .on_next_instance
+ subject(:action) { show_request }
- show_request
+ it_behaves_like 'tracks assignment and records the subject', :pipeline_editor_walkthrough, :namespace do
+ subject { project.namespace }
end
end
end
diff --git a/spec/controllers/projects/pipelines_controller_spec.rb b/spec/controllers/projects/pipelines_controller_spec.rb
index 1354e894872..14c613ff9c4 100644
--- a/spec/controllers/projects/pipelines_controller_spec.rb
+++ b/spec/controllers/projects/pipelines_controller_spec.rb
@@ -44,7 +44,7 @@ RSpec.describe Projects::PipelinesController do
end
end
- it 'does not execute N+1 queries' do
+ it 'does not execute N+1 queries', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/345470' do
get_pipelines_index_json
control_count = ActiveRecord::QueryRecorder.new do
diff --git a/spec/finders/tags_finder_spec.rb b/spec/finders/tags_finder_spec.rb
index 790e1cad570..acc86547271 100644
--- a/spec/finders/tags_finder_spec.rb
+++ b/spec/finders/tags_finder_spec.rb
@@ -7,8 +7,8 @@ RSpec.describe TagsFinder do
let_it_be(:project) { create(:project, :repository) }
let_it_be(:repository) { project.repository }
- def load_tags(params)
- described_class.new(repository, params).execute
+ def load_tags(params, gitaly_pagination: false)
+ described_class.new(repository, params).execute(gitaly_pagination: gitaly_pagination)
end
describe '#execute' do
@@ -96,6 +96,72 @@ RSpec.describe TagsFinder do
end
end
+ context 'with Gitaly pagination' do
+ subject { load_tags(params, gitaly_pagination: true) }
+
+ context 'by page_token and per_page' do
+ let(:params) { { page_token: 'v1.0.0', per_page: 1 } }
+
+ it 'filters tags' do
+ result = subject
+
+ expect(result.map(&:name)).to eq(%w(v1.1.0))
+ end
+ end
+
+ context 'by next page_token and per_page' do
+ let(:params) { { page_token: 'v1.1.0', per_page: 2 } }
+
+ it 'filters branches' do
+ result = subject
+
+ expect(result.map(&:name)).to eq(%w(v1.1.1))
+ end
+ end
+
+ context 'by per_page only' do
+ let(:params) { { per_page: 2 } }
+
+ it 'filters branches' do
+ result = subject
+
+ expect(result.map(&:name)).to eq(%w(v1.0.0 v1.1.0))
+ end
+ end
+
+ context 'by page_token only' do
+ let(:params) { { page_token: 'feature' } }
+
+ it 'raises an error' do
+ expect do
+ subject
+ end.to raise_error(Gitlab::Git::InvalidPageToken, 'Invalid page token: refs/tags/feature')
+ end
+ end
+
+ context 'pagination and sort' do
+ context 'by per_page' do
+ let(:params) { { sort: 'updated_desc', per_page: 5 } }
+
+ it 'filters branches' do
+ result = subject
+
+ expect(result.map(&:name)).to eq(%w(v1.1.1 v1.1.0 v1.0.0))
+ end
+ end
+
+ context 'by page_token and per_page' do
+ let(:params) { { sort: 'updated_desc', page_token: 'v1.1.1', per_page: 2 } }
+
+ it 'filters branches' do
+ result = subject
+
+ expect(result.map(&:name)).to eq(%w(v1.1.0 v1.0.0))
+ end
+ end
+ end
+ end
+
context 'when Gitaly is unavailable' do
it 'raises an exception' do
expect(Gitlab::GitalyClient).to receive(:call).and_raise(GRPC::Unavailable)
diff --git a/spec/frontend/boards/components/board_card_spec.js b/spec/frontend/boards/components/board_card_spec.js
index 25ec568e48d..5742dfdc5d2 100644
--- a/spec/frontend/boards/components/board_card_spec.js
+++ b/spec/frontend/boards/components/board_card_spec.js
@@ -64,12 +64,12 @@ describe('Board card', () => {
};
const selectCard = async () => {
- wrapper.trigger('mouseup');
+ wrapper.trigger('click');
await wrapper.vm.$nextTick();
};
const multiSelectCard = async () => {
- wrapper.trigger('mouseup', { ctrlKey: true });
+ wrapper.trigger('click', { ctrlKey: true });
await wrapper.vm.$nextTick();
};
diff --git a/spec/frontend/boards/mock_data.js b/spec/frontend/boards/mock_data.js
index bba8b9ecc15..8fcad99f8a7 100644
--- a/spec/frontend/boards/mock_data.js
+++ b/spec/frontend/boards/mock_data.js
@@ -615,7 +615,6 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, hasEmoji)
icon: 'issues',
title: __('Type'),
type: 'types',
- operators: [{ value: '=', description: 'is' }],
token: GlFilteredSearchToken,
unique: true,
options: [
diff --git a/spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap b/spec/frontend/packages_and_registries/container_registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap
index 7044c1285d8..7044c1285d8 100644
--- a/spec/frontend/registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/__snapshots__/registry_breadcrumb_spec.js.snap
diff --git a/spec/frontend/registry/explorer/components/delete_button_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_button_spec.js
index 6d7bf528495..6d7bf528495 100644
--- a/spec/frontend/registry/explorer/components/delete_button_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_button_spec.js
diff --git a/spec/frontend/registry/explorer/components/delete_image_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_image_spec.js
index 620c96e8c9e..620c96e8c9e 100644
--- a/spec/frontend/registry/explorer/components/delete_image_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/delete_image_spec.js
diff --git a/spec/frontend/registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap
index 5f191ef5561..5f191ef5561 100644
--- a/spec/frontend/registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/__snapshots__/tags_loader_spec.js.snap
diff --git a/spec/frontend/registry/explorer/components/details_page/delete_alert_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_alert_spec.js
index e25162f4da5..e25162f4da5 100644
--- a/spec/frontend/registry/explorer/components/details_page/delete_alert_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_alert_spec.js
diff --git a/spec/frontend/registry/explorer/components/details_page/delete_modal_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_modal_spec.js
index 16c9485e69e..16c9485e69e 100644
--- a/spec/frontend/registry/explorer/components/details_page/delete_modal_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/delete_modal_spec.js
diff --git a/spec/frontend/registry/explorer/components/details_page/details_header_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js
index c44f47a6152..f06300efa29 100644
--- a/spec/frontend/registry/explorer/components/details_page/details_header_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/details_header_spec.js
@@ -1,11 +1,11 @@
import { GlDropdownItem, GlIcon } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
+import { GlDropdown } from 'jest/packages_and_registries/container_registry/explorer/stubs';
import { useFakeDate } from 'helpers/fake_date';
import createMockApollo from 'helpers/mock_apollo_helper';
import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import waitForPromises from 'helpers/wait_for_promises';
-import { GlDropdown } from 'jest/registry/explorer/stubs';
import component from '~/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue';
import {
UNSCHEDULED_STATUS,
diff --git a/spec/frontend/registry/explorer/components/details_page/empty_state_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/empty_state_spec.js
index f14284e9efe..f14284e9efe 100644
--- a/spec/frontend/registry/explorer/components/details_page/empty_state_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/empty_state_spec.js
diff --git a/spec/frontend/registry/explorer/components/details_page/partial_cleanup_alert_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert_spec.js
index 1a27481a828..1a27481a828 100644
--- a/spec/frontend/registry/explorer/components/details_page/partial_cleanup_alert_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert_spec.js
diff --git a/spec/frontend/registry/explorer/components/details_page/status_alert_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/status_alert_spec.js
index a11b102d9a6..a11b102d9a6 100644
--- a/spec/frontend/registry/explorer/components/details_page/status_alert_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/status_alert_spec.js
diff --git a/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js
index 00b1d03b7c2..00b1d03b7c2 100644
--- a/spec/frontend/registry/explorer/components/details_page/tags_list_row_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row_spec.js
diff --git a/spec/frontend/registry/explorer/components/details_page/tags_list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
index 9a42c82d7e0..9a42c82d7e0 100644
--- a/spec/frontend/registry/explorer/components/details_page/tags_list_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_list_spec.js
diff --git a/spec/frontend/registry/explorer/components/details_page/tags_loader_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js
index 060dc9dc5f3..060dc9dc5f3 100644
--- a/spec/frontend/registry/explorer/components/details_page/tags_loader_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/details_page/tags_loader_spec.js
diff --git a/spec/frontend/registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap
index 56579847468..56579847468 100644
--- a/spec/frontend/registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/__snapshots__/group_empty_state_spec.js.snap
diff --git a/spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap
index 46b07b4c2d6..46b07b4c2d6 100644
--- a/spec/frontend/registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/__snapshots__/project_empty_state_spec.js.snap
diff --git a/spec/frontend/registry/explorer/components/list_page/cleanup_status_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status_spec.js
index e8ddad2d8ca..e8ddad2d8ca 100644
--- a/spec/frontend/registry/explorer/components/list_page/cleanup_status_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cleanup_status_spec.js
diff --git a/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cli_commands_spec.js
index 4039fba869b..4039fba869b 100644
--- a/spec/frontend/registry/explorer/components/list_page/cli_commands_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/cli_commands_spec.js
diff --git a/spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state_spec.js
index 027cdf732bc..027cdf732bc 100644
--- a/spec/frontend/registry/explorer/components/list_page/group_empty_state_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/group_empty_state_spec.js
diff --git a/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_row_spec.js
index 411bef54e40..411bef54e40 100644
--- a/spec/frontend/registry/explorer/components/list_page/image_list_row_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_row_spec.js
diff --git a/spec/frontend/registry/explorer/components/list_page/image_list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_spec.js
index e0119954ed4..e0119954ed4 100644
--- a/spec/frontend/registry/explorer/components/list_page/image_list_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_spec.js
diff --git a/spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state_spec.js
index 21748ae2813..21748ae2813 100644
--- a/spec/frontend/registry/explorer/components/list_page/project_empty_state_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/project_empty_state_spec.js
diff --git a/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js
index 92cfeb7633e..92cfeb7633e 100644
--- a/spec/frontend/registry/explorer/components/list_page/registry_header_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/registry_header_spec.js
diff --git a/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/components/registry_breadcrumb_spec.js
index e5a8438f23f..e5a8438f23f 100644
--- a/spec/frontend/registry/explorer/components/registry_breadcrumb_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/components/registry_breadcrumb_spec.js
diff --git a/spec/frontend/registry/explorer/mock_data.js b/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
index 6a835a28807..6a835a28807 100644
--- a/spec/frontend/registry/explorer/mock_data.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
diff --git a/spec/frontend/registry/explorer/pages/details_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
index adc9a64e5c9..adc9a64e5c9 100644
--- a/spec/frontend/registry/explorer/pages/details_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
diff --git a/spec/frontend/registry/explorer/pages/index_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/pages/index_spec.js
index 5f4cb8969bc..5f4cb8969bc 100644
--- a/spec/frontend/registry/explorer/pages/index_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/pages/index_spec.js
diff --git a/spec/frontend/registry/explorer/pages/list_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js
index 8457b51bf63..051d1e2a169 100644
--- a/spec/frontend/registry/explorer/pages/list_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/pages/list_spec.js
@@ -25,7 +25,7 @@ import Tracking from '~/tracking';
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
-import { $toast } from '../../shared/mocks';
+import { $toast } from 'jest/packages_and_registries/shared/mocks';
import {
graphQLImageListMock,
graphQLImageDeleteMock,
diff --git a/spec/frontend/registry/explorer/stubs.js b/spec/frontend/packages_and_registries/container_registry/explorer/stubs.js
index 7d281a53a59..7d281a53a59 100644
--- a/spec/frontend/registry/explorer/stubs.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/stubs.js
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js
index c56244a9138..5c9ade7f785 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_dropdown_spec.js
@@ -1,5 +1,5 @@
import { shallowMount } from '@vue/test-utils';
-import { GlFormGroup, GlFormSelect } from 'jest/registry/shared/stubs';
+import { GlFormGroup, GlFormSelect } from 'jest/packages_and_registries/shared/stubs';
import component from '~/packages_and_registries/settings/project/components/expiration_dropdown.vue';
describe('ExpirationDropdown', () => {
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js
index dd876d1d295..6b681924fcf 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_input_spec.js
@@ -1,6 +1,6 @@
import { GlSprintf, GlFormInput, GlLink } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { GlFormGroup } from 'jest/registry/shared/stubs';
+import { GlFormGroup } from 'jest/packages_and_registries/shared/stubs';
import component from '~/packages_and_registries/settings/project/components/expiration_input.vue';
import { NAME_REGEX_LENGTH } from '~/packages_and_registries/settings/project/constants';
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js
index 854830391c5..94f7783afe7 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_run_text_spec.js
@@ -1,6 +1,6 @@
import { GlFormInput } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { GlFormGroup } from 'jest/registry/shared/stubs';
+import { GlFormGroup } from 'jest/packages_and_registries/shared/stubs';
import component from '~/packages_and_registries/settings/project/components/expiration_run_text.vue';
import {
NEXT_CLEANUP_LABEL,
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js
index 3a3eb089b43..45039614e49 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/expiration_toggle_spec.js
@@ -1,6 +1,6 @@
import { GlToggle, GlSprintf } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
-import { GlFormGroup } from 'jest/registry/shared/stubs';
+import { GlFormGroup } from 'jest/packages_and_registries/shared/stubs';
import component from '~/packages_and_registries/settings/project/components/expiration_toggle.vue';
import {
ENABLED_TOGGLE_DESCRIPTION,
diff --git a/spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js b/spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js
index 3a71af94d5a..bc104a25ef9 100644
--- a/spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js
+++ b/spec/frontend/packages_and_registries/settings/project/settings/components/settings_form_spec.js
@@ -2,7 +2,7 @@ import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
-import { GlCard, GlLoadingIcon } from 'jest/registry/shared/stubs';
+import { GlCard, GlLoadingIcon } from 'jest/packages_and_registries/shared/stubs';
import component from '~/packages_and_registries/settings/project/components/settings_form.vue';
import {
UPDATE_SETTINGS_ERROR_MESSAGE,
diff --git a/spec/frontend/registry/shared/mocks.js b/spec/frontend/packages_and_registries/shared/mocks.js
index fdef38b6f10..fdef38b6f10 100644
--- a/spec/frontend/registry/shared/mocks.js
+++ b/spec/frontend/packages_and_registries/shared/mocks.js
diff --git a/spec/frontend/registry/shared/stubs.js b/spec/frontend/packages_and_registries/shared/stubs.js
index ad41eb42df4..ad41eb42df4 100644
--- a/spec/frontend/registry/shared/stubs.js
+++ b/spec/frontend/packages_and_registries/shared/stubs.js
diff --git a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb
index d3af4590b3a..833de6ae624 100644
--- a/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb
+++ b/spec/lib/gitlab/sidekiq_middleware/duplicate_jobs/duplicate_job_spec.rb
@@ -174,26 +174,21 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob, :clean_gi
end
describe '#update_latest_wal_location!' do
- let(:offset) { '1024' }
-
before do
- allow(duplicate_job).to receive(:pg_wal_lsn_diff).with(:main).and_return(offset)
- allow(duplicate_job).to receive(:pg_wal_lsn_diff).with(:ci).and_return(offset)
- end
+ allow(Gitlab::Database).to receive(:database_base_models).and_return(
+ { main: ::ActiveRecord::Base,
+ ci: ::ActiveRecord::Base })
- shared_examples 'updates wal location' do
- it 'updates a wal location to redis with an offset' do
- expect { duplicate_job.update_latest_wal_location! }
- .to change { read_range_from_redis(wal_location_key(idempotency_key, :main)) }
- .from(existing_wal_with_offset[:main])
- .to(new_wal_with_offset[:main])
- .and change { read_range_from_redis(wal_location_key(idempotency_key, :ci)) }
- .from(existing_wal_with_offset[:ci])
- .to(new_wal_with_offset[:ci])
- end
+ set_idempotency_key(existing_wal_location_key(idempotency_key, :main), existing_wal[:main])
+ set_idempotency_key(existing_wal_location_key(idempotency_key, :ci), existing_wal[:ci])
+
+ # read existing_wal_locations
+ duplicate_job.check!
end
context 'when preserve_latest_wal_locations_for_idempotent_jobs feature flag is disabled' do
+ let(:existing_wal) { {} }
+
before do
stub_feature_flags(preserve_latest_wal_locations_for_idempotent_jobs: false)
end
@@ -214,42 +209,107 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob, :clean_gi
end
context "when the key doesn't exists in redis" do
- include_examples 'updates wal location' do
- let(:existing_wal_with_offset) { { main: [], ci: [] } }
- let(:new_wal_with_offset) { wal_locations.transform_values { |v| [v, offset] } }
+ let(:existing_wal) do
+ {
+ main: '0/D525E3A0',
+ ci: 'AB/12340'
+ }
end
- end
- context "when the key exists in redis" do
- let(:existing_offset) { '1023'}
- let(:existing_wal_locations) do
+ let(:new_wal_location_with_offset) do
{
- main: '0/D525E3NM',
- ci: 'AB/111112'
+ # offset is relative to `existing_wal`
+ main: ['0/D525E3A8', '8'],
+ ci: ['AB/12345', '5']
}
end
+ let(:wal_locations) { new_wal_location_with_offset.transform_values(&:first) }
+
+ it 'stores a wal location to redis with an offset relative to existing wal location' do
+ expect { duplicate_job.update_latest_wal_location! }
+ .to change { read_range_from_redis(wal_location_key(idempotency_key, :main)) }
+ .from([])
+ .to(new_wal_location_with_offset[:main])
+ .and change { read_range_from_redis(wal_location_key(idempotency_key, :ci)) }
+ .from([])
+ .to(new_wal_location_with_offset[:ci])
+ end
+ end
+
+ context "when the key exists in redis" do
before do
- rpush_to_redis_key(wal_location_key(idempotency_key, :main), existing_wal_locations[:main], existing_offset)
- rpush_to_redis_key(wal_location_key(idempotency_key, :ci), existing_wal_locations[:ci], existing_offset)
+ rpush_to_redis_key(wal_location_key(idempotency_key, :main), *stored_wal_location_with_offset[:main])
+ rpush_to_redis_key(wal_location_key(idempotency_key, :ci), *stored_wal_location_with_offset[:ci])
end
+ let(:wal_locations) { new_wal_location_with_offset.transform_values(&:first) }
+
context "when the new offset is bigger then the existing one" do
- include_examples 'updates wal location' do
- let(:existing_wal_with_offset) { existing_wal_locations.transform_values { |v| [v, existing_offset] } }
- let(:new_wal_with_offset) { wal_locations.transform_values { |v| [v, offset] } }
+ let(:existing_wal) do
+ {
+ main: '0/D525E3A0',
+ ci: 'AB/12340'
+ }
+ end
+
+ let(:stored_wal_location_with_offset) do
+ {
+ # offset is relative to `existing_wal`
+ main: ['0/D525E3A3', '3'],
+ ci: ['AB/12342', '2']
+ }
+ end
+
+ let(:new_wal_location_with_offset) do
+ {
+ # offset is relative to `existing_wal`
+ main: ['0/D525E3A8', '8'],
+ ci: ['AB/12345', '5']
+ }
+ end
+
+ it 'updates a wal location to redis with an offset' do
+ expect { duplicate_job.update_latest_wal_location! }
+ .to change { read_range_from_redis(wal_location_key(idempotency_key, :main)) }
+ .from(stored_wal_location_with_offset[:main])
+ .to(new_wal_location_with_offset[:main])
+ .and change { read_range_from_redis(wal_location_key(idempotency_key, :ci)) }
+ .from(stored_wal_location_with_offset[:ci])
+ .to(new_wal_location_with_offset[:ci])
end
end
context "when the old offset is not bigger then the existing one" do
- let(:existing_offset) { offset }
+ let(:existing_wal) do
+ {
+ main: '0/D525E3A0',
+ ci: 'AB/12340'
+ }
+ end
+
+ let(:stored_wal_location_with_offset) do
+ {
+ # offset is relative to `existing_wal`
+ main: ['0/D525E3A8', '8'],
+ ci: ['AB/12345', '5']
+ }
+ end
+
+ let(:new_wal_location_with_offset) do
+ {
+ # offset is relative to `existing_wal`
+ main: ['0/D525E3A2', '2'],
+ ci: ['AB/12342', '2']
+ }
+ end
it "does not update a wal location to redis with an offset" do
expect { duplicate_job.update_latest_wal_location! }
.to not_change { read_range_from_redis(wal_location_key(idempotency_key, :main)) }
- .from([existing_wal_locations[:main], existing_offset])
+ .from(stored_wal_location_with_offset[:main])
.and not_change { read_range_from_redis(wal_location_key(idempotency_key, :ci)) }
- .from([existing_wal_locations[:ci], existing_offset])
+ .from(stored_wal_location_with_offset[:ci])
end
end
end
@@ -619,12 +679,12 @@ RSpec.describe Gitlab::SidekiqMiddleware::DuplicateJobs::DuplicateJob, :clean_gi
end
end
- def existing_wal_location_key(idempotency_key, config_name)
- "#{idempotency_key}:#{config_name}:existing_wal_location"
+ def existing_wal_location_key(idempotency_key, connection_name)
+ "#{idempotency_key}:#{connection_name}:existing_wal_location"
end
- def wal_location_key(idempotency_key, config_name)
- "#{idempotency_key}:#{config_name}:wal_location"
+ def wal_location_key(idempotency_key, connection_name)
+ "#{idempotency_key}:#{connection_name}:wal_location"
end
def set_idempotency_key(key, value = '1')
diff --git a/spec/requests/api/tags_spec.rb b/spec/requests/api/tags_spec.rb
index cf58809f7cd..bb56192a2ff 100644
--- a/spec/requests/api/tags_spec.rb
+++ b/spec/requests/api/tags_spec.rb
@@ -17,6 +17,10 @@ RSpec.describe API::Tags do
end
describe 'GET /projects/:id/repository/tags' do
+ before do
+ stub_feature_flags(tag_list_keyset_pagination: false)
+ end
+
shared_examples "get repository tags" do
let(:route) { "/projects/#{project_id}/repository/tags" }
@@ -143,6 +147,55 @@ RSpec.describe API::Tags do
expect(expected_tag['release']['description']).to eq(description)
end
end
+
+ context 'with keyset pagination on', :aggregate_errors do
+ before do
+ stub_feature_flags(tag_list_keyset_pagination: true)
+ end
+
+ context 'with keyset pagination option' do
+ let(:base_params) { { pagination: 'keyset' } }
+
+ context 'with gitaly pagination params' do
+ context 'with high limit' do
+ let(:params) { base_params.merge(per_page: 100) }
+
+ it 'returns all repository tags' do
+ get api(route, user), params: params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('public_api/v4/tags')
+ expect(response.headers).not_to include('Link')
+ tag_names = json_response.map { |x| x['name'] }
+ expect(tag_names).to match_array(project.repository.tag_names)
+ end
+ end
+
+ context 'with low limit' do
+ let(:params) { base_params.merge(per_page: 2) }
+
+ it 'returns limited repository tags' do
+ get api(route, user), params: params
+
+ expect(response).to have_gitlab_http_status(:ok)
+ expect(response).to match_response_schema('public_api/v4/tags')
+ expect(response.headers).to include('Link')
+ tag_names = json_response.map { |x| x['name'] }
+ expect(tag_names).to match_array(%w(v1.1.0 v1.1.1))
+ end
+ end
+
+ context 'with missing page token' do
+ let(:params) { base_params.merge(page_token: 'unknown') }
+
+ it_behaves_like '422 response' do
+ let(:request) { get api(route, user), params: params }
+ let(:message) { 'Invalid page token: refs/tags/unknown' }
+ end
+ end
+ end
+ end
+ end
end
context ":api_caching_tags flag enabled", :use_clean_rails_memory_store_caching do
diff --git a/spec/support/database/cross-database-modification-allowlist.yml b/spec/support/database/cross-database-modification-allowlist.yml
index e4dc958830f..d05812a64eb 100644
--- a/spec/support/database/cross-database-modification-allowlist.yml
+++ b/spec/support/database/cross-database-modification-allowlist.yml
@@ -13,7 +13,6 @@
- "./ee/spec/services/ci/subscribe_bridge_service_spec.rb"
- "./ee/spec/services/deployments/auto_rollback_service_spec.rb"
- "./ee/spec/services/ee/ci/job_artifacts/destroy_all_expired_service_spec.rb"
-- "./ee/spec/services/ee/ci/job_artifacts/destroy_batch_service_spec.rb"
- "./ee/spec/services/ee/users/destroy_service_spec.rb"
- "./ee/spec/services/projects/transfer_service_spec.rb"
- "./ee/spec/services/security/security_orchestration_policies/rule_schedule_service_spec.rb"
@@ -76,7 +75,6 @@
- "./spec/services/ci/expire_pipeline_cache_service_spec.rb"
- "./spec/services/ci/job_artifacts/destroy_all_expired_service_spec.rb"
- "./spec/services/ci/job_artifacts/destroy_associations_service_spec.rb"
-- "./spec/services/ci/job_artifacts/destroy_batch_service_spec.rb"
- "./spec/services/ci/pipeline_bridge_status_service_spec.rb"
- "./spec/services/ci/pipelines/add_job_service_spec.rb"
- "./spec/services/ci/retry_build_service_spec.rb"
diff --git a/spec/support/flaky_tests.rb b/spec/support/flaky_tests.rb
index 535df64f890..30a064d8705 100644
--- a/spec/support/flaky_tests.rb
+++ b/spec/support/flaky_tests.rb
@@ -4,7 +4,7 @@ return unless ENV['CI']
return unless ENV['SKIP_FLAKY_TESTS_AUTOMATICALLY'] == "true"
return if ENV['CI_MERGE_REQUEST_LABELS'].to_s.include?('pipeline:run-flaky-tests')
-require_relative '../tooling/rspec_flaky/report'
+require_relative '../../tooling/rspec_flaky/report'
RSpec.configure do |config|
$flaky_test_example_ids = begin # rubocop:disable Style/GlobalVars
diff --git a/spec/support/shared_examples/requests/api/status_shared_examples.rb b/spec/support/shared_examples/requests/api/status_shared_examples.rb
index b2d50599264..40843ccbd15 100644
--- a/spec/support/shared_examples/requests/api/status_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/status_shared_examples.rb
@@ -77,6 +77,24 @@ RSpec.shared_examples '412 response' do
end
end
+RSpec.shared_examples '422 response' do
+ let(:message) { nil }
+
+ before do
+ # Fires the request
+ request
+ end
+
+ it 'returns 422' do
+ expect(response).to have_gitlab_http_status(:unprocessable_entity)
+ expect(json_response).to be_an Object
+
+ if message.present?
+ expect(json_response['message']).to eq(message)
+ end
+ end
+end
+
RSpec.shared_examples '503 response' do
before do
# Fires the request