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--GITALY_SERVER_VERSION2
-rw-r--r--app/assets/javascripts/analytics/devops_reports/components/devops_score.vue2
-rw-r--r--app/assets/javascripts/groups/service/archived_projects_service.js1
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue27
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list.vue9
-rw-r--r--app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue12
-rw-r--r--app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifests_list.vue6
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue5
-rw-r--r--app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue4
-rw-r--r--app/services/ml/experiment_tracking/candidate_repository.rb14
-rw-r--r--app/views/profiles/emails/index.html.haml2
-rw-r--r--config/README.md2
-rw-r--r--config/feature_flags/development/verify_push_rules_for_first_commit.yml (renamed from config/feature_flags/development/pipeline_name_in_api.yml)10
-rw-r--r--doc/api/pipelines.md26
-rw-r--r--doc/update/index.md9
-rw-r--r--lib/api/ci/pipelines.rb4
-rw-r--r--lib/api/entities/ci/pipeline_basic_with_metadata.rb3
-rw-r--r--lib/api/entities/ci/pipeline_with_metadata.rb3
-rw-r--r--lib/gitlab/checks/diff_check.rb28
-rw-r--r--lib/gitlab/database/migrations/batched_background_migration_helpers.rb2
-rw-r--r--lib/gitlab/git/commit.rb6
-rw-r--r--lib/gitlab/git/diff_tree.rb30
-rw-r--r--lib/gitlab/git/repository.rb10
-rw-r--r--lib/gitlab/gitaly_client/commit_service.rb29
-rw-r--r--lib/gitlab/rack_attack.rb2
-rw-r--r--qa/qa/page/profile/emails.rb7
-rw-r--r--spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js2
-rw-r--r--spec/frontend/groups/service/archived_projects_service_spec.js2
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/components/list_page/image_list_spec.js22
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js2
-rw-r--r--spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js19
-rw-r--r--spec/frontend/packages_and_registries/dependency_proxy/components/manifest_list_spec.js6
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js16
-rw-r--r--spec/frontend/packages_and_registries/shared/components/registry_list_spec.js20
-rw-r--r--spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb2
-rw-r--r--spec/lib/gitlab/git/commit_spec.rb14
-rw-r--r--spec/lib/gitlab/git/diff_tree_spec.rb30
-rw-r--r--spec/lib/gitlab/git/repository_spec.rb26
-rw-r--r--spec/lib/gitlab/gitaly_client/commit_service_spec.rb38
-rw-r--r--spec/requests/api/ci/pipelines_spec.rb39
-rw-r--r--spec/requests/api/merge_requests_spec.rb5
-rw-r--r--spec/services/ml/experiment_tracking/candidate_repository_spec.rb9
42 files changed, 285 insertions, 222 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 36c103a1482..d4079cee254 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-119bc72eed2618fa5fbd21f35c290c6106275301
+bf0be1ad00e3c2657c2e5d66ec86824d859aa2fb
diff --git a/app/assets/javascripts/analytics/devops_reports/components/devops_score.vue b/app/assets/javascripts/analytics/devops_reports/components/devops_score.vue
index fd966425920..593de1dcee7 100644
--- a/app/assets/javascripts/analytics/devops_reports/components/devops_score.vue
+++ b/app/assets/javascripts/analytics/devops_reports/components/devops_score.vue
@@ -40,7 +40,7 @@ export default {
return this.devopsScoreMetrics.averageScore === undefined;
},
},
- devopsReportDocsPath: helpPagePath('user/admin_area/analytics/dev_ops_reports'),
+ devopsReportDocsPath: helpPagePath('administration/analytics/dev_ops_reports'),
tableHeaderFields: [
{
key: 'title',
diff --git a/app/assets/javascripts/groups/service/archived_projects_service.js b/app/assets/javascripts/groups/service/archived_projects_service.js
index 326ae8ad1b6..b9d48cc660e 100644
--- a/app/assets/javascripts/groups/service/archived_projects_service.js
+++ b/app/assets/javascripts/groups/service/archived_projects_service.js
@@ -17,6 +17,7 @@ export default class ArchivedProjectsService {
const { data: projects, headers } = await Api.groupProjects(this.groupId, query, {
archived: true,
+ include_subgroups: true,
page,
order_by: supportedOrderBy[orderBy],
sort,
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue
index 9ea1958a0d1..bb2ca838279 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue
@@ -2,6 +2,7 @@
import { GlEmptyState } from '@gitlab/ui';
import { createAlert } from '~/alert';
import { n__ } from '~/locale';
+import { fetchPolicies } from '~/lib/graphql';
import { joinPaths } from '~/lib/utils/url_utility';
import Tracking from '~/tracking';
import RegistryList from '~/packages_and_registries/shared/components/registry_list.vue';
@@ -69,6 +70,7 @@ export default {
apollo: {
containerRepository: {
query: getContainerRepositoryTagsQuery,
+ fetchPolicy: fetchPolicies.CACHE_AND_NETWORK,
skip() {
return !this.sort;
},
@@ -87,6 +89,7 @@ export default {
itemsToBeDeleted: [],
mutationLoading: false,
sort: null,
+ pageParams: {},
};
},
computed: {
@@ -108,6 +111,7 @@ export default {
first: GRAPHQL_PAGE_SIZE,
name: this.filters?.name,
sort: this.sort,
+ ...this.pageParams,
};
},
hasNoTags() {
@@ -180,23 +184,20 @@ export default {
}
},
fetchNextPage() {
- this.$apollo.queries.containerRepository.fetchMore({
- variables: {
- after: this.tagsPageInfo?.endCursor,
- first: GRAPHQL_PAGE_SIZE,
- },
- });
+ this.pageParams = {
+ after: this.tagsPageInfo?.endCursor,
+ first: GRAPHQL_PAGE_SIZE,
+ };
},
fetchPreviousPage() {
- this.$apollo.queries.containerRepository.fetchMore({
- variables: {
- first: null,
- before: this.tagsPageInfo?.startCursor,
- last: GRAPHQL_PAGE_SIZE,
- },
- });
+ this.pageParams = {
+ first: null,
+ before: this.tagsPageInfo?.startCursor,
+ last: GRAPHQL_PAGE_SIZE,
+ };
},
handleSearchUpdate({ sort, filters }) {
+ this.pageParams = {};
this.sort = sort;
const parsed = {
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list.vue
index 6f1f67e251f..9ecb037c257 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/components/list_page/image_list.vue
@@ -28,11 +28,6 @@ export default {
required: false,
},
},
- computed: {
- showPagination() {
- return this.pageInfo.hasPreviousPage || this.pageInfo.hasNextPage;
- },
- },
};
</script>
@@ -48,9 +43,7 @@ export default {
/>
<div class="gl-display-flex gl-justify-content-center">
<gl-keyset-pagination
- v-if="showPagination"
- :has-next-page="pageInfo.hasNextPage"
- :has-previous-page="pageInfo.hasPreviousPage"
+ v-bind="pageInfo"
class="gl-mt-3"
@prev="$emit('prev-page')"
@next="$emit('next-page')"
diff --git a/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue
index 3126af69c2c..c266dbf7e98 100644
--- a/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue
+++ b/app/assets/javascripts/packages_and_registries/container_registry/explorer/pages/details.vue
@@ -1,11 +1,10 @@
<script>
-import { GlResizeObserverDirective, GlEmptyState } from '@gitlab/ui';
+import { GlResizeObserverDirective, GlEmptyState, GlSkeletonLoader } from '@gitlab/ui';
import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
import { createAlert } from '~/alert';
import axios from '~/lib/utils/axios_utils';
import { joinPaths } from '~/lib/utils/url_utility';
import Tracking from '~/tracking';
-import TagsLoader from '~/packages_and_registries/shared/components/tags_loader.vue';
import DeleteImage from '../components/delete_image.vue';
import DeleteAlert from '../components/details_page/delete_alert.vue';
import DeleteModal from '../components/delete_modal.vue';
@@ -28,12 +27,12 @@ export default {
name: 'RegistryDetailsPage',
components: {
GlEmptyState,
+ GlSkeletonLoader,
DeleteAlert,
PartialCleanupAlert,
DetailsHeader,
DeleteModal,
TagsList,
- TagsLoader,
StatusAlert,
DeleteImage,
},
@@ -151,16 +150,17 @@ export default {
<status-alert v-if="containerRepository.status" :status="containerRepository.status" />
+ <div v-if="isLoading" class="gl-my-6">
+ <gl-skeleton-loader />
+ </div>
<details-header
- v-if="!isLoading"
+ v-else
:image="containerRepository"
:disabled="pageActionsAreDisabled"
@delete="deleteImage"
/>
- <tags-loader v-if="isLoading" />
<tags-list
- v-else
:id="$route.params.id"
:is-image-loading="isLoading"
:is-mobile="isMobile"
diff --git a/app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifests_list.vue b/app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifests_list.vue
index 94c958308dd..462de03d19f 100644
--- a/app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifests_list.vue
+++ b/app/assets/javascripts/packages_and_registries/dependency_proxy/components/manifests_list.vue
@@ -37,11 +37,6 @@ export default {
i18n: {
listTitle: s__('DependencyProxy|Image list'),
},
- computed: {
- showPagination() {
- return this.pagination.hasNextPage || this.pagination.hasPreviousPage;
- },
- },
};
</script>
@@ -68,7 +63,6 @@ export default {
</div>
<div class="gl-display-flex gl-justify-content-center">
<gl-keyset-pagination
- v-if="showPagination"
v-bind="pagination"
class="gl-mt-3"
@prev="$emit('prev-page')"
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue
index 96d097eff38..c8924e6548b 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/package_files.vue
@@ -178,10 +178,6 @@ export default {
first: GRAPHQL_PACKAGE_FILES_PAGE_SIZE,
};
},
- showPagination() {
- const { hasPreviousPage, hasNextPage } = this.pageInfo;
- return hasPreviousPage || hasNextPage;
- },
tracking() {
return {
category: packageTypeToTrackCategory(this.packageType),
@@ -490,7 +486,6 @@ export default {
</gl-table>
<div class="gl-display-flex gl-justify-content-center">
<gl-keyset-pagination
- v-if="showPagination"
:disabled="isLoading"
v-bind="pageInfo"
:prev-text="$options.i18n.prev"
diff --git a/app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue b/app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue
index 1c8f80972df..f67bee77eb6 100644
--- a/app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue
+++ b/app/assets/javascripts/packages_and_registries/shared/components/registry_list.vue
@@ -47,9 +47,6 @@ export default {
};
},
computed: {
- showPagination() {
- return this.pagination.hasPreviousPage || this.pagination.hasNextPage;
- },
disableDeleteButton() {
return this.isLoading || this.selectedItems.length === 0;
},
@@ -131,7 +128,6 @@ export default {
<div class="gl-display-flex gl-justify-content-center">
<gl-keyset-pagination
- v-if="showPagination"
v-bind="pagination"
class="gl-mt-3"
@prev="$emit('prev-page')"
diff --git a/app/services/ml/experiment_tracking/candidate_repository.rb b/app/services/ml/experiment_tracking/candidate_repository.rb
index 2399da3e182..436f06e3ca5 100644
--- a/app/services/ml/experiment_tracking/candidate_repository.rb
+++ b/app/services/ml/experiment_tracking/candidate_repository.rb
@@ -5,7 +5,7 @@ module Ml
class CandidateRepository
attr_accessor :project, :user, :experiment, :candidate
- def initialize(project, user)
+ def initialize(project, user = nil)
@project = project
@user = user
end
@@ -103,10 +103,16 @@ module Ml
end
def candidate_name(name, tags)
- return name if name.present?
- return unless tags.present?
+ name.presence || candidate_name_from_tags(tags) || random_candidate_name
+ end
+
+ def candidate_name_from_tags(tags)
+ tags&.detect { |t| t[:key] == 'mlflow.runName' }&.dig(:value)
+ end
- tags.detect { |t| t[:key] == 'mlflow.runName' }&.dig(:value)
+ def random_candidate_name
+ parts = Array.new(3).map { FFaker::Animal.common_name.downcase.delete(' ') } << rand(10000)
+ parts.join('-').truncate(255)
end
end
end
diff --git a/app/views/profiles/emails/index.html.haml b/app/views/profiles/emails/index.html.haml
index e78c6c12c62..04a5ae7eb69 100644
--- a/app/views/profiles/emails/index.html.haml
+++ b/app/views/profiles/emails/index.html.haml
@@ -24,7 +24,7 @@
= sprite_icon('mail', css_class: 'gl-mr-2')
= @emails.load.size
.gl-new-card-actions
- = render Pajamas::ButtonComponent.new(size: :small, button_options: { class: "js-toggle-button js-toggle-content" }) do
+ = render Pajamas::ButtonComponent.new(size: :small, button_options: { class: "js-toggle-button js-toggle-content", data: { testid: 'toggle_email_address_field' } }) do
= s_('Profiles|Add new email')
- c.with_body do
.gl-new-card-add-form.gl-m-3.gl-mb-4.gl-display-none.js-toggle-content
diff --git a/config/README.md b/config/README.md
index 70d66f3f96d..9a8672a7ada 100644
--- a/config/README.md
+++ b/config/README.md
@@ -73,7 +73,7 @@ An example configuration file for Redis is in this directory under the name
| `queues` | | Background job processing queues |
| `shared_state` | | Persistent application state |
| `trace_chunks` | `shared_state` | [CI trace chunks](https://docs.gitlab.com/ee/administration/job_logs.html#incremental-logging-architecture) |
-| `rate_limiting` | `cache` | [Rate limiting](https://docs.gitlab.com/ee/user/admin_area/settings/user_and_ip_rate_limits.html) state |
+| `rate_limiting` | `cache` | [Rate limiting](https://docs.gitlab.com/ee/administration/settings/user_and_ip_rate_limits.html) state |
| `sessions` | `shared_state` | [Sessions](https://docs.gitlab.com/ee/development/session.html#redis) |
| `repository_cache` | `cache` | Repository related information |
| `db_load_balancing` | `shared_state` | [Database Load Balancing](https://docs.gitlab.com/ee/administration/postgresql/database_load_balancing.html) |
diff --git a/config/feature_flags/development/pipeline_name_in_api.yml b/config/feature_flags/development/verify_push_rules_for_first_commit.yml
index cb22fca2932..a09142b06d3 100644
--- a/config/feature_flags/development/pipeline_name_in_api.yml
+++ b/config/feature_flags/development/verify_push_rules_for_first_commit.yml
@@ -1,8 +1,8 @@
---
-name: pipeline_name_in_api
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115310
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/398131
-milestone: '15.11'
+name: verify_push_rules_for_first_commit
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/123950
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/419128
+milestone: '16.3'
type: development
-group: group::delivery
+group: group::source code
default_enabled: false
diff --git a/doc/api/pipelines.md b/doc/api/pipelines.md
index 4fca878fcec..892c8354033 100644
--- a/doc/api/pipelines.md
+++ b/doc/api/pipelines.md
@@ -16,13 +16,15 @@ Read more on [pagination](rest/index.md#pagination).
## List project pipelines
> - `iid` in response [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/342223) in GitLab 14.6.
-> - `name` in request and response [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115310) in GitLab 15.11 [with a flag](../administration/feature_flags.md) named `pipeline_name_in_api`. Disabled by default.
+> - `name` in response [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115310) in GitLab 15.11 [with a flag](../administration/feature_flags.md) named `pipeline_name_in_api`. Disabled by default.
+> - `name` in request [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115310) in 15.11 [with a flag](../administration/feature_flags.md) named `pipeline_name_search`. Disabled by default.
+> - `name` in response [generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/398131) in GitLab 16.3. Feature flag `pipeline_name_in_api` removed.
FLAG:
-On self-managed GitLab, by default the `name` field is not available.
+On self-managed GitLab, by default the `name` field in a request is ignored.
To make it available, an administrator can [enable the feature flag](../administration/feature_flags.md)
-named `pipeline_name_in_api`. This feature is not ready for production use.
-On GitLab.com, this feature is not available.
+named `pipeline_name_search`.
+On GitLab.com, this feature is available.
List pipelines in a project. Child pipelines are not included in the results,
but you can [get child pipeline](pipelines.md#get-a-single-pipeline) individually.
@@ -88,12 +90,7 @@ Example of response
> - `iid` in response [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/342223) in GitLab 14.6.
> - `name` in response [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115310) in GitLab 15.11 [with a flag](../administration/feature_flags.md) named `pipeline_name_in_api`. Disabled by default.
-
-FLAG:
-On self-managed GitLab, by default the `name` field is not available.
-To make it available, an administrator can [enable the feature flag](../administration/feature_flags.md)
-named `pipeline_name_in_api`. This feature is not ready for production use.
-On GitLab.com, this feature is not available.
+> - `name` in response [generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/398131) in GitLab 16.3. Feature flag `pipeline_name_in_api` removed.
Get one pipeline from a project.
@@ -286,13 +283,8 @@ Sample response:
## Get the latest pipeline
-> `name` in response [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115310) in GitLab 15.11 [with a flag](../administration/feature_flags.md) named `pipeline_name_in_api`. Disabled by default.
-
-FLAG:
-On self-managed GitLab, by default the `name` field is not available.
-To make it available, an administrator can [enable the feature flag](../administration/feature_flags.md)
-named `pipeline_name_in_api`. This feature is not ready for production use.
-On GitLab.com, this feature is not available.
+> - `name` in response [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115310) in GitLab 15.11 [with a flag](../administration/feature_flags.md) named `pipeline_name_in_api`. Disabled by default.
+> - `name` in response [generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/398131) in GitLab 16.3. Feature flag `pipeline_name_in_api` removed.
Get the latest pipeline for a specific ref in a project.
diff --git a/doc/update/index.md b/doc/update/index.md
index 8760dbbd406..257f0a5b4cb 100644
--- a/doc/update/index.md
+++ b/doc/update/index.md
@@ -271,6 +271,15 @@ NOTE:
Specific information that follow related to Ruby and Git versions do not apply to [Omnibus installations](https://docs.gitlab.com/omnibus/)
and [Helm Chart deployments](https://docs.gitlab.com/charts/). They come with appropriate Ruby and Git versions and are not using system binaries for Ruby and Git. There is no need to install Ruby or Git when utilizing these two approaches.
+### 16.2.0
+
+- Legacy LDAP configuration settings may cause
+ [`NoMethodError: undefined method 'devise' for User:Class` errors](https://gitlab.com/gitlab-org/gitlab/-/issues/419485).
+ This error occurs if you have TLS options (such as `ca_file`) not specified
+ in the `tls_options` hash, or use the legacy `gitlab_rails['ldap_host']` option.
+ See the [configuration workarounds](https://gitlab.com/gitlab-org/gitlab/-/issues/419485#workarounds)
+ for more details.
+
### 16.1.0
- A `MigrateHumanUserType` background migration will be finalized with
diff --git a/lib/api/ci/pipelines.rb b/lib/api/ci/pipelines.rb
index 809a9bd781b..bd5c04f401b 100644
--- a/lib/api/ci/pipelines.rb
+++ b/lib/api/ci/pipelines.rb
@@ -76,10 +76,8 @@ module API
authorize! :read_pipeline, user_project
authorize! :read_build, user_project
- params.delete(:name) unless ::Feature.enabled?(:pipeline_name_in_api, user_project)
-
pipelines = ::Ci::PipelinesFinder.new(user_project, current_user, params).execute
- pipelines = pipelines.preload_pipeline_metadata if ::Feature.enabled?(:pipeline_name_in_api, user_project)
+ pipelines = pipelines.preload_pipeline_metadata
present paginate(pipelines), with: Entities::Ci::PipelineBasicWithMetadata, project: user_project
end
diff --git a/lib/api/entities/ci/pipeline_basic_with_metadata.rb b/lib/api/entities/ci/pipeline_basic_with_metadata.rb
index 4eeba3aec41..a352da05b2d 100644
--- a/lib/api/entities/ci/pipeline_basic_with_metadata.rb
+++ b/lib/api/entities/ci/pipeline_basic_with_metadata.rb
@@ -5,8 +5,7 @@ module API
module Ci
class PipelineBasicWithMetadata < PipelineBasic
expose :name,
- documentation: { type: 'string', example: 'Build pipeline' },
- if: ->(pipeline, _) { ::Feature.enabled?(:pipeline_name_in_api, pipeline.project) }
+ documentation: { type: 'string', example: 'Build pipeline' }
end
end
end
diff --git a/lib/api/entities/ci/pipeline_with_metadata.rb b/lib/api/entities/ci/pipeline_with_metadata.rb
index a8b1d81a053..31604f33fc1 100644
--- a/lib/api/entities/ci/pipeline_with_metadata.rb
+++ b/lib/api/entities/ci/pipeline_with_metadata.rb
@@ -5,8 +5,7 @@ module API
module Ci
class PipelineWithMetadata < Pipeline
expose :name,
- documentation: { type: 'string', example: 'Build pipeline' },
- if: ->(pipeline, _) { ::Feature.enabled?(:pipeline_name_in_api, pipeline.project) }
+ documentation: { type: 'string', example: 'Build pipeline' }
end
end
end
diff --git a/lib/gitlab/checks/diff_check.rb b/lib/gitlab/checks/diff_check.rb
index bce4f969284..faf5a764725 100644
--- a/lib/gitlab/checks/diff_check.rb
+++ b/lib/gitlab/checks/diff_check.rb
@@ -18,10 +18,7 @@ module Gitlab
return unless should_run_validations?
return if commits.empty?
- paths = project.repository.find_changed_paths(
- commits.map(&:sha), merge_commit_diff_mode: :all_parents
- )
-
+ paths = project.repository.find_changed_paths(treeish_objects, merge_commit_diff_mode: :all_parents)
paths.each do |path|
validate_path(path)
end
@@ -31,6 +28,29 @@ module Gitlab
private
+ def treeish_objects
+ objects = commits
+
+ return objects unless project.repository.empty? &&
+ Feature.enabled?(:verify_push_rules_for_first_commit, project)
+
+ # It's a special case for the push to the empty repository
+ #
+ # Git doesn't display a diff of the initial commit of the repository
+ # if we just provide a commit sha.
+ #
+ # To fix that we can use TreeRequest to check the difference
+ # between empty tree sha and the tree sha of the initial commit
+ #
+ # `commits` are sorted in reverse order, the initial commit is the last one.
+ init_commit = objects.last
+
+ diff_tree = Gitlab::Git::DiffTree.from_commit(init_commit)
+ objects.prepend(diff_tree) if diff_tree
+
+ objects
+ end
+
def validate_lfs_file_locks?
strong_memoize(:validate_lfs_file_locks) do
project.lfs_enabled? && project.any_lfs_file_locks?
diff --git a/lib/gitlab/database/migrations/batched_background_migration_helpers.rb b/lib/gitlab/database/migrations/batched_background_migration_helpers.rb
index cb2a98b553f..efb1957d5e7 100644
--- a/lib/gitlab/database/migrations/batched_background_migration_helpers.rb
+++ b/lib/gitlab/database/migrations/batched_background_migration_helpers.rb
@@ -242,7 +242,7 @@ module Gitlab
"\n\n" \
"For more information, check the documentation" \
"\n\n" \
- "\thttps://docs.gitlab.com/ee/user/admin_area/monitoring/background_migrations.html#database-migrations-failing-because-of-batched-background-migration-not-finished"
+ "\thttps://docs.gitlab.com/ee/update/background_migrations.html#database-migrations-failing-because-of-batched-background-migration-not-finished"
end
end
end
diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb
index c0601c7795c..b104610038c 100644
--- a/lib/gitlab/git/commit.rb
+++ b/lib/gitlab/git/commit.rb
@@ -226,6 +226,12 @@ module Gitlab
id.to_s[0..length]
end
+ def tree_id
+ return unless raw_commit
+
+ raw_commit.tree_id
+ end
+
def safe_message
@safe_message ||= message
end
diff --git a/lib/gitlab/git/diff_tree.rb b/lib/gitlab/git/diff_tree.rb
new file mode 100644
index 00000000000..df48baeb1c3
--- /dev/null
+++ b/lib/gitlab/git/diff_tree.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+module Gitlab
+ module Git
+ # Represents a tree-ish object for git diff-tree command
+ # See: https://git-scm.com/docs/git-diff-tree
+ class DiffTree
+ attr_reader :left_tree_id, :right_tree_id
+
+ def initialize(left_tree_id, right_tree_id)
+ @left_tree_id = left_tree_id
+ @right_tree_id = right_tree_id
+ end
+
+ def self.from_commit(commit)
+ return unless commit.tree_id
+
+ parent_tree_id =
+ if commit.parent_ids.blank?
+ Gitlab::Git::EMPTY_TREE_ID
+ else
+ parent_id = commit.parent_ids.first
+ commit.repository.commit(parent_id).tree_id
+ end
+
+ new(parent_tree_id, commit.tree_id)
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
index b573bbbc1f5..cb95af69b00 100644
--- a/lib/gitlab/git/repository.rb
+++ b/lib/gitlab/git/repository.rb
@@ -536,15 +536,13 @@ module Gitlab
empty_diff_stats
end
- def find_changed_paths(commits, merge_commit_diff_mode: nil)
- processed_commits = commits.reject { |ref| ref.blank? || Gitlab::Git.blank_ref?(ref) }
+ def find_changed_paths(treeish_objects, merge_commit_diff_mode: nil)
+ processed_objects = treeish_objects.compact
- return [] if processed_commits.empty?
+ return [] if processed_objects.empty?
wrapped_gitaly_errors do
- gitaly_commit_client.find_changed_paths(
- processed_commits, merge_commit_diff_mode: merge_commit_diff_mode
- )
+ gitaly_commit_client.find_changed_paths(processed_objects, merge_commit_diff_mode: merge_commit_diff_mode)
end
rescue CommandError, TypeError, NoRepository
[]
diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb
index c10f780665c..0b0cf19752f 100644
--- a/lib/gitlab/gitaly_client/commit_service.rb
+++ b/lib/gitlab/gitaly_client/commit_service.rb
@@ -274,8 +274,10 @@ module Gitlab
# else # defaults to :include_merges behavior
# ['foo_bar.rb', 'bar_baz.rb'],
#
- def find_changed_paths(commits, merge_commit_diff_mode: nil)
- request = find_changed_paths_request(commits, merge_commit_diff_mode)
+ def find_changed_paths(objects, merge_commit_diff_mode: nil)
+ request = find_changed_paths_request(objects, merge_commit_diff_mode)
+
+ return [] if request.nil?
response = gitaly_client_call(@repository.storage, :diff_service, :find_changed_paths, request, timeout: GitalyClient.medium_timeout)
response.flat_map do |msg|
@@ -646,16 +648,27 @@ module Gitlab
response.commit
end
- def find_changed_paths_request(commits, merge_commit_diff_mode)
+ def find_changed_paths_request(objects, merge_commit_diff_mode)
diff_mode = MERGE_COMMIT_DIFF_MODES[merge_commit_diff_mode] if Feature.enabled?(:merge_commit_diff_modes)
- commit_requests = commits.map do |commit|
- Gitaly::FindChangedPathsRequest::Request.new(
- commit_request: Gitaly::FindChangedPathsRequest::Request::CommitRequest.new(commit_revision: commit)
- )
+ requests = objects.filter_map do |object|
+ case object
+ when Gitlab::Git::DiffTree
+ Gitaly::FindChangedPathsRequest::Request.new(
+ tree_request: Gitaly::FindChangedPathsRequest::Request::TreeRequest.new(left_tree_revision: object.left_tree_id, right_tree_revision: object.right_tree_id)
+ )
+ when Commit, Gitlab::Git::Commit
+ next if object.sha.blank? || Gitlab::Git.blank_ref?(object.sha)
+
+ Gitaly::FindChangedPathsRequest::Request.new(
+ commit_request: Gitaly::FindChangedPathsRequest::Request::CommitRequest.new(commit_revision: object.sha)
+ )
+ end
end
- Gitaly::FindChangedPathsRequest.new(repository: @gitaly_repo, requests: commit_requests, merge_commit_diff_mode: diff_mode)
+ return if requests.blank?
+
+ Gitaly::FindChangedPathsRequest.new(repository: @gitaly_repo, requests: requests, merge_commit_diff_mode: diff_mode)
end
def path_error_message(path_error)
diff --git a/lib/gitlab/rack_attack.rb b/lib/gitlab/rack_attack.rb
index d999b706d6c..829b305d1ee 100644
--- a/lib/gitlab/rack_attack.rb
+++ b/lib/gitlab/rack_attack.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
# When adding new user-configurable throttles, remember to update the documentation
-# in doc/user/admin_area/settings/user_and_ip_rate_limits.md
+# in doc/administration/settings/user_and_ip_rate_limits.md
#
# Integration specs for throttling can be found in:
# spec/requests/rack_attack_global_spec.rb
diff --git a/qa/qa/page/profile/emails.rb b/qa/qa/page/profile/emails.rb
index f8aeea50513..1e6b7518e55 100644
--- a/qa/qa/page/profile/emails.rb
+++ b/qa/qa/page/profile/emails.rb
@@ -11,9 +11,16 @@ module QA
element :add_email_address_button
element :email_row_content
element :delete_email_link
+ element :toggle_email_address_field
+ end
+
+ def expand_email_input
+ click_element(:toggle_email_address_field) if has_no_element?(:email_address_field)
+ has_element?(:email_address_field)
end
def add_email_address(email_address)
+ expand_email_input
find_element(:email_address_field).set email_address
click_element(:add_email_address_button)
end
diff --git a/spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js b/spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js
index de56e843eb9..019027be6c6 100644
--- a/spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js
+++ b/spec/frontend/admin/analytics/devops_score/components/devops_score_spec.js
@@ -52,7 +52,7 @@ describe('DevopsScore', () => {
it('contains a link to the feature documentation', () => {
expect(findDocsLink().exists()).toBe(true);
expect(findDocsLink().attributes('href')).toBe(
- '/help/user/admin_area/analytics/dev_ops_reports',
+ '/help/administration/analytics/dev_ops_reports',
);
});
});
diff --git a/spec/frontend/groups/service/archived_projects_service_spec.js b/spec/frontend/groups/service/archived_projects_service_spec.js
index 8e9dfb0f971..6bc46e4799c 100644
--- a/spec/frontend/groups/service/archived_projects_service_spec.js
+++ b/spec/frontend/groups/service/archived_projects_service_spec.js
@@ -54,6 +54,7 @@ describe('ArchivedProjectsService', () => {
expect(Api.groupProjects).toHaveBeenCalledWith(groupId, query, {
archived: true,
+ include_subgroups: true,
page,
order_by: 'created_at',
sort: 'asc',
@@ -108,6 +109,7 @@ describe('ArchivedProjectsService', () => {
expect(Api.groupProjects).toHaveBeenCalledWith(groupId, query, {
archived: true,
+ include_subgroups: true,
page,
order_by: expectedOrderByParameter,
sort: expectedSortParameter,
diff --git a/spec/frontend/packages_and_registries/container_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 6c771887b88..714f8d97839 100644
--- a/spec/frontend/packages_and_registries/container_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
@@ -3,7 +3,7 @@ import { shallowMount } from '@vue/test-utils';
import Component from '~/packages_and_registries/container_registry/explorer/components/list_page/image_list.vue';
import ImageListRow from '~/packages_and_registries/container_registry/explorer/components/list_page/image_list_row.vue';
-import { imagesListResponse, pageInfo as defaultPageInfo } from '../../mock_data';
+import { imagesListResponse, pageInfo } from '../../mock_data';
describe('Image List', () => {
let wrapper;
@@ -11,6 +11,8 @@ describe('Image List', () => {
const findRow = () => wrapper.findAllComponents(ImageListRow);
const findPagination = () => wrapper.findComponent(GlKeysetPagination);
+ const { __typename, ...defaultPageInfo } = pageInfo;
+
const mountComponent = (props) => {
wrapper = shallowMount(Component, {
propsData: {
@@ -45,25 +47,9 @@ describe('Image List', () => {
it('exists', () => {
mountComponent();
- expect(findPagination().exists()).toBe(true);
+ expect(findPagination().props()).toMatchObject({ ...defaultPageInfo });
});
- it.each`
- hasNextPage | hasPreviousPage | isVisible
- ${true} | ${true} | ${true}
- ${true} | ${false} | ${true}
- ${false} | ${true} | ${true}
- `(
- 'when hasNextPage is $hasNextPage and hasPreviousPage is $hasPreviousPage: is $isVisible that the component is visible',
- ({ hasNextPage, hasPreviousPage, isVisible }) => {
- mountComponent({ pageInfo: { ...defaultPageInfo, hasNextPage, hasPreviousPage } });
-
- expect(findPagination().exists()).toBe(isVisible);
- expect(findPagination().props('hasPreviousPage')).toBe(hasPreviousPage);
- expect(findPagination().props('hasNextPage')).toBe(hasNextPage);
- },
- );
-
it('emits "prev-page" when the user clicks the back page button', () => {
mountComponent();
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js b/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
index 8ca74f5077e..5ee1b4315ff 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/mock_data.js
@@ -40,7 +40,7 @@ export const pageInfo = {
hasPreviousPage: true,
startCursor: 'eyJpZCI6IjI2In0',
endCursor: 'eyJpZCI6IjgifQ',
- __typename: 'ContainerRepositoryConnection',
+ __typename: 'PageInfo',
};
export const graphQLImageListMock = {
diff --git a/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js b/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
index 7fed81acead..9dbdf57b587 100644
--- a/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
+++ b/spec/frontend/packages_and_registries/container_registry/explorer/pages/details_spec.js
@@ -1,4 +1,4 @@
-import { GlKeysetPagination, GlEmptyState } from '@gitlab/ui';
+import { GlKeysetPagination, GlEmptyState, GlSkeletonLoader } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import Vue, { nextTick } from 'vue';
import VueApollo from 'vue-apollo';
@@ -12,7 +12,6 @@ import DetailsHeader from '~/packages_and_registries/container_registry/explorer
import PartialCleanupAlert from '~/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert.vue';
import StatusAlert from '~/packages_and_registries/container_registry/explorer/components/details_page/status_alert.vue';
import TagsList from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue';
-import TagsLoader from '~/packages_and_registries/shared/components/tags_loader.vue';
import {
UNFINISHED_STATUS,
@@ -40,7 +39,7 @@ describe('Details Page', () => {
const findDeleteModal = () => wrapper.findComponent(DeleteModal);
const findPagination = () => wrapper.findComponent(GlKeysetPagination);
- const findTagsLoader = () => wrapper.findComponent(TagsLoader);
+ const findLoader = () => wrapper.findComponent(GlSkeletonLoader);
const findTagsList = () => wrapper.findComponent(TagsList);
const findDeleteAlert = () => wrapper.findComponent(DeleteAlert);
const findDetailsHeader = () => wrapper.findComponent(DetailsHeader);
@@ -109,13 +108,13 @@ describe('Details Page', () => {
it('shows the loader', () => {
mountComponent();
- expect(findTagsLoader().exists()).toBe(true);
+ expect(findLoader().exists()).toBe(true);
});
- it('does not show the list', () => {
+ it('sets loading prop on tags list component', () => {
mountComponent();
- expect(findTagsList().exists()).toBe(false);
+ expect(findTagsList().props('isImageLoading')).toBe(true);
});
});
@@ -125,7 +124,7 @@ describe('Details Page', () => {
await waitForApolloRequestRender();
- expect(findTagsLoader().exists()).toBe(false);
+ expect(findLoader().exists()).toBe(false);
expect(findDetailsHeader().exists()).toBe(false);
expect(findTagsList().exists()).toBe(false);
expect(findPagination().exists()).toBe(false);
@@ -424,13 +423,15 @@ describe('Details Page', () => {
await waitForPromises();
- expect(findTagsLoader().exists()).toBe(true);
+ expect(findLoader().exists()).toBe(true);
+ expect(findTagsList().props('isImageLoading')).toBe(true);
findDeleteImage().vm.$emit('end');
await nextTick();
- expect(findTagsLoader().exists()).toBe(false);
+ expect(findLoader().exists()).toBe(false);
+ expect(findTagsList().props('isImageLoading')).toBe(false);
});
it('binds correctly to delete-image error event', async () => {
diff --git a/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_list_spec.js b/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_list_spec.js
index 8f445843aa8..521a38bee70 100644
--- a/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_list_spec.js
+++ b/spec/frontend/packages_and_registries/dependency_proxy/components/manifest_list_spec.js
@@ -91,12 +91,6 @@ describe('Manifests List', () => {
});
describe('pagination', () => {
- it('is hidden when there is no next or prev pages', () => {
- createComponent({ ...defaultProps, pagination: {} });
-
- expect(findPagination().exists()).toBe(false);
- });
-
it('has the correct props', () => {
createComponent();
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js
index 2c712feac86..5ba4b1f687e 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/package_files_spec.js
@@ -176,22 +176,6 @@ describe('Package Files', () => {
disabled: false,
});
});
-
- it('hides pagination when only one page', async () => {
- createComponent({
- resolver: jest.fn().mockResolvedValue(
- packageFilesQuery({
- extendPagination: {
- hasNextPage: false,
- hasPreviousPage: false,
- },
- }),
- ),
- });
- await waitForPromises();
-
- expect(findPagination().exists()).toBe(false);
- });
});
describe('link', () => {
diff --git a/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js b/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js
index 66fca2ce12e..43dca2e6bf2 100644
--- a/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js
+++ b/spec/frontend/packages_and_registries/shared/components/registry_list_spec.js
@@ -185,7 +185,7 @@ describe('Registry List', () => {
pagination = { hasPreviousPage: false, hasNextPage: true };
});
- it('has a pagination', () => {
+ it('has pagination', () => {
mountComponent({
propsData: { ...defaultPropsData, pagination },
});
@@ -193,24 +193,6 @@ describe('Registry List', () => {
expect(findPagination().props()).toMatchObject(pagination);
});
- it.each`
- hasPreviousPage | hasNextPage | visible
- ${true} | ${true} | ${true}
- ${true} | ${false} | ${true}
- ${false} | ${true} | ${true}
- ${false} | ${false} | ${false}
- `(
- 'when hasPreviousPage is $hasPreviousPage and hasNextPage is $hasNextPage is $visible that the pagination is shown',
- ({ hasPreviousPage, hasNextPage, visible }) => {
- pagination = { hasPreviousPage, hasNextPage };
- mountComponent({
- propsData: { ...defaultPropsData, pagination },
- });
-
- expect(findPagination().exists()).toBe(visible);
- },
- );
-
it('pagination emits the correct events', () => {
mountComponent({
propsData: { ...defaultPropsData, pagination },
diff --git a/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb b/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb
index 82f77d2bb19..158497b1fef 100644
--- a/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migrations/batched_background_migration_helpers_spec.rb
@@ -473,7 +473,7 @@ RSpec.describe Gitlab::Database::Migrations::BatchedBackgroundMigrationHelpers d
"\n\n" \
"For more information, check the documentation" \
"\n\n" \
- "\thttps://docs.gitlab.com/ee/user/admin_area/monitoring/background_migrations.html#database-migrations-failing-because-of-batched-background-migration-not-finished"
+ "\thttps://docs.gitlab.com/ee/update/background_migrations.html#database-migrations-failing-because-of-batched-background-migration-not-finished"
end
it 'does not raise error when migration exists and is marked as finished' do
diff --git a/spec/lib/gitlab/git/commit_spec.rb b/spec/lib/gitlab/git/commit_spec.rb
index dd9f77f0211..3b1dbf7d602 100644
--- a/spec/lib/gitlab/git/commit_spec.rb
+++ b/spec/lib/gitlab/git/commit_spec.rb
@@ -3,15 +3,16 @@
require "spec_helper"
RSpec.describe Gitlab::Git::Commit, feature_category: :source_code_management do
- let(:repository) { create(:project, :repository).repository.raw }
+ let_it_be(:repository) { create(:project, :repository).repository.raw }
let(:commit) { described_class.find(repository, SeedRepo::Commit::ID) }
describe "Commit info from gitaly commit" do
let(:subject) { (+"My commit").force_encoding('ASCII-8BIT') }
let(:body) { subject + (+"My body").force_encoding('ASCII-8BIT') }
let(:body_size) { body.length }
- let(:gitaly_commit) { build(:gitaly_commit, subject: subject, body: body, body_size: body_size) }
+ let(:gitaly_commit) { build(:gitaly_commit, subject: subject, body: body, body_size: body_size, tree_id: tree_id) }
let(:id) { gitaly_commit.id }
+ let(:tree_id) { 'd7f32d821c9cc7b1a9166ca7c4ba95b5c2d0d000' }
let(:committer) { gitaly_commit.committer }
let(:author) { gitaly_commit.author }
let(:commit) { described_class.new(repository, gitaly_commit) }
@@ -26,6 +27,7 @@ RSpec.describe Gitlab::Git::Commit, feature_category: :source_code_management do
it { expect(commit.committer_name).to eq(committer.name) }
it { expect(commit.committer_email).to eq(committer.email) }
it { expect(commit.parent_ids).to eq(gitaly_commit.parent_ids) }
+ it { expect(commit.tree_id).to eq(tree_id) }
context 'non-UTC dates' do
let(:seconds) { Time.now.to_i }
@@ -577,6 +579,14 @@ RSpec.describe Gitlab::Git::Commit, feature_category: :source_code_management do
it { is_expected.to eq(sample_commit_hash[:message]) }
end
+
+ describe '#tree_id' do
+ subject { super().tree_id }
+
+ it "doesn't return tree id for non-Gitaly commits" do
+ is_expected.to be_nil
+ end
+ end
end
describe '#stats' do
diff --git a/spec/lib/gitlab/git/diff_tree_spec.rb b/spec/lib/gitlab/git/diff_tree_spec.rb
new file mode 100644
index 00000000000..614a8f03dd8
--- /dev/null
+++ b/spec/lib/gitlab/git/diff_tree_spec.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+require "spec_helper"
+
+RSpec.describe Gitlab::Git::DiffTree, feature_category: :source_code_management do
+ let_it_be(:project) { create(:project, :repository) }
+ let_it_be(:repository) { project.repository }
+
+ describe '.from_commit' do
+ subject(:diff_tree) { described_class.from_commit(commit) }
+
+ context 'when commit is an initial commit' do
+ let(:commit) { repository.commit('1a0b36b3cdad1d2ee32457c102a8c0b7056fa863') }
+
+ it 'returns the expected diff tree object' do
+ expect(diff_tree.left_tree_id).to eq(Gitlab::Git::EMPTY_TREE_ID)
+ expect(diff_tree.right_tree_id).to eq(commit.tree_id)
+ end
+ end
+
+ context 'when commit is a regular commit' do
+ let(:commit) { repository.commit('60ecb67744cb56576c30214ff52294f8ce2def98') }
+
+ it 'returns the expected diff tree object' do
+ expect(diff_tree.left_tree_id).to eq(commit.parent.tree_id)
+ expect(diff_tree.right_tree_id).to eq(commit.tree_id)
+ end
+ end
+ end
+end
diff --git a/spec/lib/gitlab/git/repository_spec.rb b/spec/lib/gitlab/git/repository_spec.rb
index 9c7f393490e..7ab56956068 100644
--- a/spec/lib/gitlab/git/repository_spec.rb
+++ b/spec/lib/gitlab/git/repository_spec.rb
@@ -1705,9 +1705,13 @@ RSpec.describe Gitlab::Git::Repository, feature_category: :source_code_managemen
end
describe '#find_changed_paths' do
- let(:commit_1) { TestEnv::BRANCH_SHA['with-executables'] }
- let(:commit_2) { TestEnv::BRANCH_SHA['master'] }
- let(:commit_3) { '6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9' }
+ let_it_be(:commit_1) { repository.commit(TestEnv::BRANCH_SHA['with-executables']) }
+ let_it_be(:commit_2) { repository.commit(TestEnv::BRANCH_SHA['master']) }
+ let_it_be(:commit_3) { repository.commit('6f6d7e7ed97bb5f0054f2b1df789b39ca89b6ff9') }
+
+ let_it_be(:initial_commit) { repository.commit('1a0b36b3cdad1d2ee32457c102a8c0b7056fa863') }
+ let_it_be(:diff_tree) { Gitlab::Git::DiffTree.from_commit(initial_commit) }
+
let(:commit_1_files) do
[Gitlab::Git::ChangedPath.new(status: :ADDED, path: "files/executables/ls")]
end
@@ -1723,18 +1727,26 @@ RSpec.describe Gitlab::Git::Repository, feature_category: :source_code_managemen
]
end
+ let(:diff_tree_files) do
+ [
+ Gitlab::Git::ChangedPath.new(status: :ADDED, path: ".gitignore"),
+ Gitlab::Git::ChangedPath.new(status: :ADDED, path: "LICENSE"),
+ Gitlab::Git::ChangedPath.new(status: :ADDED, path: "README.md")
+ ]
+ end
+
it 'returns a list of paths' do
- collection = repository.find_changed_paths([commit_1, commit_2, commit_3])
+ collection = repository.find_changed_paths([commit_1, commit_2, commit_3, diff_tree])
expect(collection).to be_a(Enumerable)
- expect(collection.as_json).to eq((commit_1_files + commit_2_files + commit_3_files).as_json)
+ expect(collection.as_json).to eq((commit_1_files + commit_2_files + commit_3_files + diff_tree_files).as_json)
end
- it 'returns no paths when SHAs are invalid' do
+ it 'returns only paths with valid SHAs' do
collection = repository.find_changed_paths(['invalid', commit_1])
expect(collection).to be_a(Enumerable)
- expect(collection.to_a).to be_empty
+ expect(collection.as_json).to eq(commit_1_files.as_json)
end
it 'returns a list of paths even when containing a blank ref' do
diff --git a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
index fd66efe12c8..740073d5e4e 100644
--- a/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
+++ b/spec/lib/gitlab/gitaly_client/commit_service_spec.rb
@@ -192,7 +192,9 @@ RSpec.describe Gitlab::GitalyClient::CommitService, feature_category: :gitaly do
Gitaly::FindChangedPathsRequest.new(repository: repository_message, requests: requests, merge_commit_diff_mode: merge_commit_diff_mode)
end
- subject { described_class.new(repository).find_changed_paths(commits, merge_commit_diff_mode: merge_commit_diff_mode).as_json }
+ let(:treeish_objects) { repository.commits_by(oids: commits) }
+
+ subject { described_class.new(repository).find_changed_paths(treeish_objects, merge_commit_diff_mode: merge_commit_diff_mode).as_json }
before do
allow(Gitaly::FindChangedPathsRequest).to receive(:new).and_call_original
@@ -334,6 +336,40 @@ RSpec.describe Gitlab::GitalyClient::CommitService, feature_category: :gitaly do
include_examples 'uses requests format'
end
end
+
+ context 'when all requested objects are invalid' do
+ it 'does not send RPC request' do
+ expect_any_instance_of(Gitaly::DiffService::Stub).not_to receive(:find_changed_paths)
+
+ returned_value = described_class.new(repository).find_changed_paths(%w[wrong values])
+
+ expect(returned_value).to eq([])
+ end
+ end
+
+ context 'when commit has an empty SHA' do
+ let(:empty_commit) { build(:commit, project: project, sha: '0000000000000000000000000000000000000000') }
+
+ it 'does not send RPC request' do
+ expect_any_instance_of(Gitaly::DiffService::Stub).not_to receive(:find_changed_paths)
+
+ returned_value = described_class.new(repository).find_changed_paths([empty_commit])
+
+ expect(returned_value).to eq([])
+ end
+ end
+
+ context 'when commit sha is not set' do
+ let(:empty_commit) { build(:commit, project: project, sha: nil) }
+
+ it 'does not send RPC request' do
+ expect_any_instance_of(Gitaly::DiffService::Stub).not_to receive(:find_changed_paths)
+
+ returned_value = described_class.new(repository).find_changed_paths([empty_commit])
+
+ expect(returned_value).to eq([])
+ end
+ end
end
describe '#tree_entries' do
diff --git a/spec/requests/api/ci/pipelines_spec.rb b/spec/requests/api/ci/pipelines_spec.rb
index 869b0ec9dca..3544a6dd72a 100644
--- a/spec/requests/api/ci/pipelines_spec.rb
+++ b/spec/requests/api/ci/pipelines_spec.rb
@@ -43,19 +43,6 @@ RSpec.describe API::Ci::Pipelines, feature_category: :continuous_integration do
expect(json_response.first.keys).to contain_exactly(*%w[id iid project_id sha ref status web_url created_at updated_at source name])
end
-
- context 'when pipeline_name_in_api feature flag is off' do
- before do
- stub_feature_flags(pipeline_name_in_api: false)
- end
-
- it 'does not include pipeline name in response and ignores name parameter' do
- get api("/projects/#{project.id}/pipelines", user), params: { name: 'Chatops pipeline' }
-
- expect(json_response.length).to eq(1)
- expect(json_response.first.keys).not_to include('name')
- end
- end
end
it 'avoids N+1 queries' do
@@ -894,19 +881,6 @@ RSpec.describe API::Ci::Pipelines, feature_category: :continuous_integration do
expect(json_response["coverage"]).to eq('30.00')
end
end
-
- context 'with pipeline_name_in_api disabled' do
- before do
- stub_feature_flags(pipeline_name_in_api: false)
- end
-
- it 'does not return name', :aggregate_failures do
- get api("/projects/#{project.id}/pipelines/#{pipeline.id}", user)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response.keys).not_to include('name')
- end
- end
end
context 'unauthorized user' do
@@ -971,19 +945,6 @@ RSpec.describe API::Ci::Pipelines, feature_category: :continuous_integration do
expect(json_response['sha']).to eq(second_branch.target)
end
end
-
- context 'with pipeline_name_in_api disabled' do
- before do
- stub_feature_flags(pipeline_name_in_api: false)
- end
-
- it 'does not return name', :aggregate_failures do
- get api("/projects/#{project.id}/pipelines/latest", user)
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(json_response.keys).not_to include('name')
- end
- end
end
context 'unauthorized user' do
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index 702c8885155..4edcd66e91a 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -2,15 +2,14 @@
require "spec_helper"
-RSpec.describe API::MergeRequests, :aggregate_failures, feature_category: :source_code_management,
- quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/418757' do
+RSpec.describe API::MergeRequests, :aggregate_failures, feature_category: :source_code_management do
include ProjectForksHelper
let_it_be(:base_time) { Time.now }
let_it_be(:user) { create(:user) }
let_it_be(:user2) { create(:user) }
let_it_be(:admin) { create(:user, :admin) }
- let_it_be(:project) { create(:project, :public, :repository, creator: user, namespace: user.namespace, only_allow_merge_if_pipeline_succeeds: false) }
+ let_it_be_with_refind(:project) { create(:project, :public, :repository, creator: user, namespace: user.namespace, only_allow_merge_if_pipeline_succeeds: false) }
let(:milestone1) { create(:milestone, title: '0.9', project: project) }
let(:milestone) { create(:milestone, title: '1.0.0', project: project) }
diff --git a/spec/services/ml/experiment_tracking/candidate_repository_spec.rb b/spec/services/ml/experiment_tracking/candidate_repository_spec.rb
index 079c36c9613..9b46675a08e 100644
--- a/spec/services/ml/experiment_tracking/candidate_repository_spec.rb
+++ b/spec/services/ml/experiment_tracking/candidate_repository_spec.rb
@@ -61,6 +61,15 @@ RSpec.describe ::Ml::ExperimentTracking::CandidateRepository, feature_category:
expect(subject.name).to eq('blah')
end
end
+
+ context 'when name is nil and no mlflow.runName is not present' do
+ let(:tags) { nil }
+ let(:name) { nil }
+
+ it 'gives the candidate a random name' do
+ expect(subject.name).to match(/[a-z]+-[a-z]+-[a-z]+-\d+/)
+ end
+ end
end
end