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/CODEOWNERS34
-rw-r--r--.rubocop_todo/cop/user_admin.yml1
-rw-r--r--.rubocop_todo/layout/hash_alignment.yml20
-rw-r--r--app/assets/javascripts/graphql_shared/possible_types.json1
-rw-r--r--app/assets/javascripts/notes/components/note_form.vue4
-rw-r--r--app/assets/javascripts/runner/admin_runners/admin_runners_app.vue4
-rw-r--r--app/assets/javascripts/runner/components/runner_stacked_layout_banner.vue71
-rw-r--r--app/assets/javascripts/runner/group_runners/group_runners_app.vue4
-rw-r--r--app/assets/javascripts/work_items/components/work_item_assignees.vue2
-rw-r--r--app/assets/javascripts/work_items/components/work_item_labels.vue2
-rw-r--r--app/assets/stylesheets/page_bundles/work_items.scss6
-rw-r--r--app/assets/stylesheets/pages/notes.scss6
-rw-r--r--app/helpers/projects_helper.rb1
-rw-r--r--app/models/ci/build.rb18
-rw-r--r--app/models/commit_status.rb2
-rw-r--r--app/services/ci/resource_groups/assign_resource_from_resource_group_service.rb6
-rw-r--r--app/services/projects/destroy_service.rb20
-rw-r--r--config/feature_flags/development/escape_gitaly_refs.yml2
-rw-r--r--config/feature_flags/development/extract_mr_diff_deletions.yml8
-rw-r--r--doc/.vale/gitlab/Markdown_emoji.yml13
-rw-r--r--doc/api/graphql/reference/index.md22
-rw-r--r--doc/api/personal_access_tokens.md8
-rw-r--r--doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md5
-rw-r--r--doc/development/code_review.md2
-rw-r--r--doc/user/permissions.md2
-rw-r--r--lib/api/api.rb1
-rw-r--r--lib/api/helpers/personal_access_tokens_helpers.rb35
-rw-r--r--lib/api/personal_access_tokens.rb34
-rw-r--r--lib/api/personal_access_tokens/self_revocation.rb26
-rw-r--r--lib/gitlab/ci/trace.rb11
-rw-r--r--locale/gitlab.pot9
-rw-r--r--spec/controllers/projects/jobs_controller_spec.rb134
-rw-r--r--spec/features/projects/show/user_interacts_with_stars_spec.rb38
-rw-r--r--spec/frontend/runner/admin_runners/admin_runners_app_spec.js7
-rw-r--r--spec/frontend/runner/components/runner_stacked_layout_banner_spec.js57
-rw-r--r--spec/frontend/runner/group_runners/group_runners_app_spec.js7
-rw-r--r--spec/lib/gitlab/ci/config/external/mapper_spec.rb4
-rw-r--r--spec/lib/gitlab/ci/lint_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb3
-rw-r--r--spec/lib/gitlab/ci/trace_spec.rb1
-rw-r--r--spec/lib/gitlab/ci/variables/builder_spec.rb6
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb26
-rw-r--r--spec/lib/gitlab/data_builder/issuable_spec.rb2
-rw-r--r--spec/lib/gitlab/data_builder/note_spec.rb32
-rw-r--r--spec/lib/gitlab/database/migration_helpers_spec.rb2
-rw-r--r--spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb13
-rw-r--r--spec/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table_spec.rb6
-rw-r--r--spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb4
-rw-r--r--spec/lib/gitlab/diff/highlight_cache_spec.rb48
-rw-r--r--spec/lib/gitlab/diff/lines_unfolder_spec.rb16
-rw-r--r--spec/lib/gitlab/diff/position_spec.rb2
-rw-r--r--spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb8
-rw-r--r--spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb2
-rw-r--r--spec/lib/gitlab/etag_caching/middleware_spec.rb10
-rw-r--r--spec/lib/gitlab/etag_caching/router/graphql_spec.rb2
-rw-r--r--spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb2
-rw-r--r--spec/lib/gitlab/import_export/attributes_finder_spec.rb12
-rw-r--r--spec/models/ci/build_spec.rb64
-rw-r--r--spec/models/ci/processable_spec.rb3
-rw-r--r--spec/requests/api/graphql/group/work_item_types_spec.rb2
-rw-r--r--spec/requests/api/personal_access_tokens/self_revocation_spec.rb69
-rw-r--r--spec/requests/api/personal_access_tokens_spec.rb58
-rw-r--r--spec/services/ci/resource_groups/assign_resource_from_resource_group_service_spec.rb15
-rw-r--r--spec/services/projects/destroy_service_spec.rb27
-rw-r--r--spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb116
65 files changed, 664 insertions, 520 deletions
diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS
index b25977cf5d2..56f91732c91 100644
--- a/.gitlab/CODEOWNERS
+++ b/.gitlab/CODEOWNERS
@@ -151,7 +151,7 @@ Dangerfile @gl-quality/eng-prod
/lib/gitlab/ci/templates/ @gitlab-org/maintainers/cicd-templates
/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml @DylanGriffith @mayra-cabrera @tkuah
/lib/gitlab/ci/templates/Security/ @gonzoyumo @twoodham @sethgitlab @thiagocsf
-/lib/gitlab/ci/templates/Security/Container-Scanning.*.yml @gitlab-org/protect/container-security-backend
+/lib/gitlab/ci/templates/Security/Container-Scanning.*.yml @gitlab-org/govern/security-policies-backend
^[Project Alias]
/ee/app/models/project_alias.rb @patrickbajao
@@ -183,23 +183,23 @@ Dangerfile @gl-quality/eng-prod
/ee/app/services/app_sec/dast/ @gitlab-org/secure/dynamic-analysis-be
^[Container Security]
-/ee/app/views/projects/threat_monitoring/** @gitlab-org/protect/container-security-frontend
-/ee/app/views/projects/security/policies/** @gitlab-org/protect/container-security-frontend
-/ee/spec/views/projects/security/policies/** @gitlab-org/protect/container-security-frontend
-/ee/app/assets/javascripts/pages/projects/threat_monitoring/** @gitlab-org/protect/container-security-frontend
-/ee/app/assets/javascripts/threat_monitoring/** @gitlab-org/protect/container-security-frontend
-/ee/spec/frontend/threat_monitoring/** @gitlab-org/protect/container-security-frontend
+/ee/app/views/projects/threat_monitoring/** @gitlab-org/govern/security-policies-frontend
+/ee/app/views/projects/security/policies/** @gitlab-org/govern/security-policies-frontend
+/ee/spec/views/projects/security/policies/** @gitlab-org/govern/security-policies-frontend
+/ee/app/assets/javascripts/pages/projects/threat_monitoring/** @gitlab-org/govern/security-policies-frontend
+/ee/app/assets/javascripts/threat_monitoring/** @gitlab-org/govern/security-policies-frontend
+/ee/spec/frontend/threat_monitoring/** @gitlab-org/govern/security-policies-frontend
-/ee/app/controllers/projects/threat_monitoring_controller.rb @gitlab-org/protect/container-security-backend
-/ee/spec/controllers/projects/threat_monitoring_controller_spec.rb @gitlab-org/protect/container-security-backend
-/ee/app/controllers/projects/security/policies_controller.rb @gitlab-org/protect/container-security-backend
-/ee/spec/requests/projects/security/policies_controller_spec.rb @gitlab-org/protect/container-security-backend
-/ee/app/models/security/orchestration_policy_configuration.rb @gitlab-org/protect/container-security-backend
-/ee/spec/models/security/orchestration_policy_configuration_spec.rb @gitlab-org/protect/container-security-backend
-/app/models/clusters/applications/cilium.rb @gitlab-org/protect/container-security-backend
-/spec/models/clusters/applications/cilium_spec.rb @gitlab-org/protect/container-security-backend
-/ee/app/services/security/orchestration/** @gitlab-org/protect/container-security-backend
-/ee/spec/services/security/orchestration/** @gitlab-org/protect/container-security-backend
+/ee/app/controllers/projects/threat_monitoring_controller.rb @gitlab-org/govern/security-policies-backend
+/ee/spec/controllers/projects/threat_monitoring_controller_spec.rb @gitlab-org/govern/container-security-backend
+/ee/app/controllers/projects/security/policies_controller.rb @gitlab-org/govern/security-policies-backend
+/ee/spec/requests/projects/security/policies_controller_spec.rb @gitlab-org/govern/security-policies-backend
+/ee/app/models/security/orchestration_policy_configuration.rb @gitlab-org/govern/security-policies-backend
+/ee/spec/models/security/orchestration_policy_configuration_spec.rb @gitlab-org/govern/security-policies-backend
+/app/models/clusters/applications/cilium.rb @gitlab-org/govern/security-policies-backend
+/spec/models/clusters/applications/cilium_spec.rb @gitlab-org/govern/security-policies-backend
+/ee/app/services/security/orchestration/** @gitlab-org/govern/security-policies-backend
+/ee/spec/services/security/orchestration/** @gitlab-org/govern/security-policies-backend
^[Code Owners]
/ee/lib/gitlab/code_owners.rb @reprazent @kerrizor @garyh
diff --git a/.rubocop_todo/cop/user_admin.yml b/.rubocop_todo/cop/user_admin.yml
index c9eed57e74d..653865e3d43 100644
--- a/.rubocop_todo/cop/user_admin.yml
+++ b/.rubocop_todo/cop/user_admin.yml
@@ -52,7 +52,6 @@ Cop/UserAdmin:
- lib/api/entities/ci/runner_details.rb
- lib/api/groups.rb
- lib/api/helpers.rb
- - lib/api/personal_access_tokens.rb
- lib/api/users.rb
- lib/api/v3/github.rb
- lib/constraints/admin_constrainer.rb
diff --git a/.rubocop_todo/layout/hash_alignment.yml b/.rubocop_todo/layout/hash_alignment.yml
index 04beadbf905..f15ea0d2506 100644
--- a/.rubocop_todo/layout/hash_alignment.yml
+++ b/.rubocop_todo/layout/hash_alignment.yml
@@ -4,26 +4,6 @@ Layout/HashAlignment:
Exclude:
- 'ee/spec/lib/ee/gitlab/usage_data_spec.rb'
- 'spec/controllers/projects/merge_requests_controller_spec.rb'
- - 'spec/lib/gitlab/ci/config/external/mapper_spec.rb'
- - 'spec/lib/gitlab/ci/lint_spec.rb'
- - 'spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb'
- - 'spec/lib/gitlab/ci/variables/builder_spec.rb'
- - 'spec/lib/gitlab/ci/yaml_processor_spec.rb'
- - 'spec/lib/gitlab/data_builder/issuable_spec.rb'
- - 'spec/lib/gitlab/data_builder/note_spec.rb'
- - 'spec/lib/gitlab/database/migration_helpers_spec.rb'
- - 'spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb'
- - 'spec/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table_spec.rb'
- - 'spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb'
- - 'spec/lib/gitlab/diff/highlight_cache_spec.rb'
- - 'spec/lib/gitlab/diff/lines_unfolder_spec.rb'
- - 'spec/lib/gitlab/diff/position_spec.rb'
- - 'spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb'
- - 'spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb'
- - 'spec/lib/gitlab/etag_caching/middleware_spec.rb'
- - 'spec/lib/gitlab/etag_caching/router/graphql_spec.rb'
- - 'spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb'
- - 'spec/lib/gitlab/import_export/attributes_finder_spec.rb'
- 'spec/lib/gitlab/import_export/group/object_builder_spec.rb'
- 'spec/lib/gitlab/import_export/group/relation_tree_restorer_spec.rb'
- 'spec/lib/gitlab/import_export/project/relation_tree_restorer_spec.rb'
diff --git a/app/assets/javascripts/graphql_shared/possible_types.json b/app/assets/javascripts/graphql_shared/possible_types.json
index eac325f184f..72dbf9e7b7b 100644
--- a/app/assets/javascripts/graphql_shared/possible_types.json
+++ b/app/assets/javascripts/graphql_shared/possible_types.json
@@ -140,6 +140,7 @@
"WorkItemWidgetAssignees",
"WorkItemWidgetDescription",
"WorkItemWidgetHierarchy",
+ "WorkItemWidgetIteration",
"WorkItemWidgetLabels",
"WorkItemWidgetStartAndDueDate",
"WorkItemWidgetVerificationStatus",
diff --git a/app/assets/javascripts/notes/components/note_form.vue b/app/assets/javascripts/notes/components/note_form.vue
index 66a28c0a2c8..b6ede10d02b 100644
--- a/app/assets/javascripts/notes/components/note_form.vue
+++ b/app/assets/javascripts/notes/components/note_form.vue
@@ -423,7 +423,7 @@ export default {
category="primary"
variant="confirm"
data-qa-selector="reply_comment_button"
- class="gl-mr-3 js-vue-issue-save js-comment-button"
+ class="gl-sm-mr-3 gl-xs-mb-3 js-vue-issue-save js-comment-button"
@click="handleUpdate()"
>
{{ saveButtonTitle }}
@@ -432,7 +432,7 @@ export default {
v-if="discussion.resolvable"
category="secondary"
variant="default"
- class="gl-mr-3 js-comment-resolve-button"
+ class="gl-sm-mr-3 gl-xs-mb-3 js-comment-resolve-button"
@click.prevent="handleUpdate(true)"
>
{{ resolveButtonTitle }}
diff --git a/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue b/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue
index 777a332333d..f5620876783 100644
--- a/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue
+++ b/app/assets/javascripts/runner/admin_runners/admin_runners_app.vue
@@ -15,6 +15,7 @@ import allRunnersQuery from 'ee_else_ce/runner/graphql/list/all_runners.query.gr
import allRunnersCountQuery from 'ee_else_ce/runner/graphql/list/all_runners_count.query.graphql';
import RegistrationDropdown from '../components/registration/registration_dropdown.vue';
+import RunnerStackedLayoutBanner from '../components/runner_stacked_layout_banner.vue';
import RunnerFilteredSearchBar from '../components/runner_filtered_search_bar.vue';
import RunnerBulkDelete from '../components/runner_bulk_delete.vue';
import RunnerBulkDeleteCheckbox from '../components/runner_bulk_delete_checkbox.vue';
@@ -37,6 +38,7 @@ export default {
components: {
GlLink,
RegistrationDropdown,
+ RunnerStackedLayoutBanner,
RunnerFilteredSearchBar,
RunnerBulkDelete,
RunnerBulkDeleteCheckbox,
@@ -169,6 +171,8 @@ export default {
</script>
<template>
<div>
+ <runner-stacked-layout-banner />
+
<div
class="gl-display-flex gl-align-items-center gl-flex-direction-column-reverse gl-md-flex-direction-row gl-mt-3 gl-md-mt-0"
>
diff --git a/app/assets/javascripts/runner/components/runner_stacked_layout_banner.vue b/app/assets/javascripts/runner/components/runner_stacked_layout_banner.vue
new file mode 100644
index 00000000000..c36efa73e0e
--- /dev/null
+++ b/app/assets/javascripts/runner/components/runner_stacked_layout_banner.vue
@@ -0,0 +1,71 @@
+<script>
+import allChangesCommittedSvg from '@gitlab/svgs/dist/illustrations/multi-editor_all_changes_committed_empty.svg';
+import { GlBanner } from '@gitlab/ui';
+
+import { s__ } from '~/locale';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
+import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
+
+const I18N_TITLE = s__("Runners|We've made some changes and want your feedback");
+const I18N_DESCRIPTION = s__(
+ "Runners|We want you to be able to manage your runners easily and efficiently from this page, and we are making changes to get there. Give us feedback on how we're doing!",
+);
+const I18N_LINK = s__('Runners|Add your feedback in the issue');
+
+// use a data url instead getting it from via HTML data-* attributes to simplify removal of this feature flag
+const ILLUSTRATION_URL = `data:image/svg+xml;utf8,${encodeURIComponent(allChangesCommittedSvg)}`;
+const ISSUE_URL = 'https://gitlab.com/gitlab-org/gitlab/-/issues/371621';
+const STORAGE_KEY = 'runner_list_stacked_layout_feedback_dismissed';
+
+export default {
+ components: {
+ GlBanner,
+ LocalStorageSync,
+ },
+ mixins: [glFeatureFlagMixin()],
+ data() {
+ return {
+ isDismissed: false,
+ };
+ },
+ computed: {
+ stackedLayoutEnabled() {
+ // Two feature flags can be used: runner_list_stacked_layout_admin or runner_list_stacked_layout
+ // Rollout issue: https://gitlab.com/gitlab-org/gitlab/-/issues/371031
+ const { runnerListStackedLayoutAdmin, runnerListStackedLayout } = this.glFeatures || {};
+ return runnerListStackedLayoutAdmin || runnerListStackedLayout;
+ },
+ showBanner() {
+ return this.stackedLayoutEnabled && !this.isDismissed;
+ },
+ },
+ methods: {
+ onClose() {
+ this.isDismissed = true;
+ },
+ },
+ I18N_TITLE,
+ I18N_DESCRIPTION,
+ I18N_LINK,
+ ILLUSTRATION_URL,
+ ISSUE_URL,
+ STORAGE_KEY,
+};
+</script>
+
+<template>
+ <div>
+ <local-storage-sync v-model="isDismissed" :storage-key="$options.STORAGE_KEY" />
+ <gl-banner
+ v-if="showBanner"
+ :svg-path="$options.ILLUSTRATION_URL"
+ :title="$options.I18N_TITLE"
+ :button-text="$options.I18N_LINK"
+ :button-link="$options.ISSUE_URL"
+ class="gl-my-5"
+ @close="onClose"
+ >
+ <p>{{ $options.I18N_DESCRIPTION }}</p>
+ </gl-banner>
+ </div>
+</template>
diff --git a/app/assets/javascripts/runner/group_runners/group_runners_app.vue b/app/assets/javascripts/runner/group_runners/group_runners_app.vue
index a2b666f4c6a..70826a6bfa1 100644
--- a/app/assets/javascripts/runner/group_runners/group_runners_app.vue
+++ b/app/assets/javascripts/runner/group_runners/group_runners_app.vue
@@ -13,6 +13,7 @@ import {
import groupRunnersQuery from 'ee_else_ce/runner/graphql/list/group_runners.query.graphql';
import RegistrationDropdown from '../components/registration/registration_dropdown.vue';
+import RunnerStackedLayoutBanner from '../components/runner_stacked_layout_banner.vue';
import RunnerFilteredSearchBar from '../components/runner_filtered_search_bar.vue';
import RunnerList from '../components/runner_list.vue';
import RunnerListEmptyState from '../components/runner_list_empty_state.vue';
@@ -37,6 +38,7 @@ export default {
components: {
GlLink,
RegistrationDropdown,
+ RunnerStackedLayoutBanner,
RunnerFilteredSearchBar,
RunnerList,
RunnerListEmptyState,
@@ -179,6 +181,8 @@ export default {
<template>
<div>
+ <runner-stacked-layout-banner />
+
<div class="gl-display-flex gl-align-items-center">
<runner-type-tabs
ref="runner-type-tabs"
diff --git a/app/assets/javascripts/work_items/components/work_item_assignees.vue b/app/assets/javascripts/work_items/components/work_item_assignees.vue
index 9e5403bb416..3d88275c0ef 100644
--- a/app/assets/javascripts/work_items/components/work_item_assignees.vue
+++ b/app/assets/javascripts/work_items/components/work_item_assignees.vue
@@ -266,7 +266,7 @@ export default {
</script>
<template>
- <div class="form-row gl-mb-5 work-item-assignees gl-relative">
+ <div class="form-row gl-mb-5 work-item-assignees gl-relative gl-flex-nowrap">
<span
class="gl-font-weight-bold col-lg-2 col-3 gl-pt-2 min-w-fit-content gl-overflow-wrap-break"
data-testid="assignees-title"
diff --git a/app/assets/javascripts/work_items/components/work_item_labels.vue b/app/assets/javascripts/work_items/components/work_item_labels.vue
index e608e4ad57e..837f79a9a03 100644
--- a/app/assets/javascripts/work_items/components/work_item_labels.vue
+++ b/app/assets/javascripts/work_items/components/work_item_labels.vue
@@ -192,7 +192,7 @@ export default {
</script>
<template>
- <div class="form-row gl-mb-5 work-item-labels gl-relative">
+ <div class="form-row gl-mb-5 work-item-labels gl-relative gl-flex-nowrap">
<span
class="gl-font-weight-bold gl-mt-2 col-lg-2 col-3 gl-pt-2 min-w-fit-content gl-overflow-wrap-break"
data-testid="labels-title"
diff --git a/app/assets/stylesheets/page_bundles/work_items.scss b/app/assets/stylesheets/page_bundles/work_items.scss
index 9220fa82b46..85fa3a974e4 100644
--- a/app/assets/stylesheets/page_bundles/work_items.scss
+++ b/app/assets/stylesheets/page_bundles/work_items.scss
@@ -19,8 +19,10 @@
display: none;
}
- .assignees-selector:hover .assign-myself {
- display: block;
+ @include media-breakpoint-up(sm) {
+ .assignees-selector:hover .assign-myself {
+ display: block;
+ }
}
}
diff --git a/app/assets/stylesheets/pages/notes.scss b/app/assets/stylesheets/pages/notes.scss
index 27d01b38a2a..fc1b78bf730 100644
--- a/app/assets/stylesheets/pages/notes.scss
+++ b/app/assets/stylesheets/pages/notes.scss
@@ -334,7 +334,11 @@ $system-note-svg-size: 16px;
border-radius: 0;
@media (min-width: map-get($grid-breakpoints, md)) {
- --initial-top: calc(#{$header-height} + #{$mr-tabs-height + 28px});
+ --initial-top: calc(#{$header-height} + #{$mr-tabs-height});
+
+ &.is-sidebar-moved {
+ --initial-top: calc(#{$header-height} + #{$mr-tabs-height + 28px});
+ }
.with-performance-bar & {
--top: 123px;
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index a65dd6703f2..65259122417 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -172,6 +172,7 @@ module ProjectsHelper
def project_list_cache_key(project, pipeline_status: true)
key = [
+ project.star_count,
project.route.cache_key,
project.cache_key,
project.last_activity_date,
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 12c296070fc..a08fdf3652a 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -706,24 +706,6 @@ module Ci
job_artifacts.of_report_type(:test).exists?
end
- def has_old_trace?
- old_trace.present?
- end
-
- def trace=(data)
- raise NotImplementedError
- end
-
- def old_trace
- read_attribute(:trace)
- end
-
- def erase_old_trace!
- return unless has_old_trace?
-
- update_column(:trace, nil)
- end
-
def ensure_trace_metadata!
Ci::BuildTraceMetadata.find_or_upsert_for!(id)
end
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index 3b197398349..d8ca68eb2a5 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -8,8 +8,10 @@ class CommitStatus < Ci::ApplicationRecord
include EnumWithNil
include BulkInsertableAssociations
include TaggableQueries
+ include IgnorableColumns
self.table_name = 'ci_builds'
+ ignore_column :trace, remove_with: '15.6', remove_after: '2022-10-22'
belongs_to :user
belongs_to :project
diff --git a/app/services/ci/resource_groups/assign_resource_from_resource_group_service.rb b/app/services/ci/resource_groups/assign_resource_from_resource_group_service.rb
index dfd97498fc8..d7078200c14 100644
--- a/app/services/ci/resource_groups/assign_resource_from_resource_group_service.rb
+++ b/app/services/ci/resource_groups/assign_resource_from_resource_group_service.rb
@@ -9,8 +9,10 @@ module Ci
free_resources = resource_group.resources.free.count
- resource_group.upcoming_processables.take(free_resources).each do |processable|
- processable.enqueue_waiting_for_resource
+ resource_group.upcoming_processables.take(free_resources).each do |upcoming|
+ Gitlab::OptimisticLocking.retry_lock(upcoming, name: 'enqueue_waiting_for_resource') do |processable|
+ processable.enqueue_waiting_for_resource
+ end
end
end
# rubocop: enable CodeReuse/ActiveRecord
diff --git a/app/services/projects/destroy_service.rb b/app/services/projects/destroy_service.rb
index c16b14ba152..2a58ee7a868 100644
--- a/app/services/projects/destroy_service.rb
+++ b/app/services/projects/destroy_service.rb
@@ -134,6 +134,8 @@ module Projects
destroy_ci_records!
destroy_mr_diff_relations!
+ destroy_merge_request_diffs! if ::Feature.enabled?(:extract_mr_diff_deletions)
+
# Rails attempts to load all related records into memory before
# destroying: https://github.com/rails/rails/issues/22510
# This ensures we delete records in batches.
@@ -180,6 +182,24 @@ module Projects
end
# rubocop: enable CodeReuse/ActiveRecord
+ # rubocop: disable CodeReuse/ActiveRecord
+ def destroy_merge_request_diffs!
+ mr_batch_size = 100
+ delete_batch_size = 1000
+
+ project.merge_requests.each_batch(column: :iid, of: mr_batch_size) do |relation_ids|
+ loop do
+ deleted_rows = MergeRequestDiff
+ .where(merge_request_id: relation_ids)
+ .limit(delete_batch_size)
+ .delete_all
+
+ break if deleted_rows == 0
+ end
+ end
+ end
+ # rubocop: enable CodeReuse/ActiveRecord
+
def destroy_ci_records!
# Make sure to destroy this first just in case the project is undergoing stats refresh.
# This is to avoid logging the artifact deletion in Ci::JobArtifacts::DestroyBatchService.
diff --git a/config/feature_flags/development/escape_gitaly_refs.yml b/config/feature_flags/development/escape_gitaly_refs.yml
index bee62c669ee..b42cc4c07e5 100644
--- a/config/feature_flags/development/escape_gitaly_refs.yml
+++ b/config/feature_flags/development/escape_gitaly_refs.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/366437
milestone: '15.2'
type: development
group: group::source code
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/extract_mr_diff_deletions.yml b/config/feature_flags/development/extract_mr_diff_deletions.yml
new file mode 100644
index 00000000000..24067f95074
--- /dev/null
+++ b/config/feature_flags/development/extract_mr_diff_deletions.yml
@@ -0,0 +1,8 @@
+---
+name: extract_mr_diff_deletions
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96455
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/372060
+milestone: '15.4'
+type: development
+group: group::source code
+default_enabled: false
diff --git a/doc/.vale/gitlab/Markdown_emoji.yml b/doc/.vale/gitlab/Markdown_emoji.yml
new file mode 100644
index 00000000000..ac0dab2d69d
--- /dev/null
+++ b/doc/.vale/gitlab/Markdown_emoji.yml
@@ -0,0 +1,13 @@
+---
+# Warning: gitlab.Markdown_emoji
+#
+# Check for use of GLFM emoji syntax (https://docs.gitlab.com/ee/user/markdown.html#emojis), which doesn't render correctly in documentation.
+#
+# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
+extends: existence
+message: 'This appears to be GLFM emoji syntax. Replace "%s" with GitLab SVGs or Unicode emojis.'
+link: https://docs.gitlab.com/ee/development/documentation/styleguide/#gitlab-svg-icons
+level: warning
+scope: text
+raw:
+ - '(?:\s+|^):[a-zA-Z0-9\-_\+]+:(?:\s+|$|\.)'
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 089c6e0d766..45fa85b3454 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -5756,6 +5756,7 @@ Input type: `WorkItemUpdateInput`
| <a id="mutationworkitemupdatedescriptionwidget"></a>`descriptionWidget` | [`WorkItemWidgetDescriptionInput`](#workitemwidgetdescriptioninput) | Input for description widget. |
| <a id="mutationworkitemupdatehierarchywidget"></a>`hierarchyWidget` | [`WorkItemWidgetHierarchyUpdateInput`](#workitemwidgethierarchyupdateinput) | Input for hierarchy widget. |
| <a id="mutationworkitemupdateid"></a>`id` | [`WorkItemID!`](#workitemid) | Global ID of the work item. |
+| <a id="mutationworkitemupdateiterationwidget"></a>`iterationWidget` | [`WorkItemWidgetIterationInput`](#workitemwidgetiterationinput) | Input for iteration widget. |
| <a id="mutationworkitemupdatestartandduedatewidget"></a>`startAndDueDateWidget` | [`WorkItemWidgetStartAndDueDateUpdateInput`](#workitemwidgetstartandduedateupdateinput) | Input for start and due date widget. |
| <a id="mutationworkitemupdatestateevent"></a>`stateEvent` | [`WorkItemStateEvent`](#workitemstateevent) | Close or reopen a work item. |
| <a id="mutationworkitemupdatetitle"></a>`title` | [`String`](#string) | Title of the work item. |
@@ -19162,6 +19163,17 @@ Represents a hierarchy widget.
| <a id="workitemwidgethierarchyparent"></a>`parent` | [`WorkItem`](#workitem) | Parent work item. |
| <a id="workitemwidgethierarchytype"></a>`type` | [`WorkItemWidgetType`](#workitemwidgettype) | Widget type. |
+### `WorkItemWidgetIteration`
+
+Represents an iteration widget.
+
+#### Fields
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="workitemwidgetiterationiteration"></a>`iteration` | [`Iteration`](#iteration) | Iteration of the work item. |
+| <a id="workitemwidgetiterationtype"></a>`type` | [`WorkItemWidgetType`](#workitemwidgettype) | Widget type. |
+
### `WorkItemWidgetLabels`
Represents the labels widget.
@@ -21171,6 +21183,7 @@ Type of a work item widget.
| <a id="workitemwidgettypeassignees"></a>`ASSIGNEES` | Assignees widget. |
| <a id="workitemwidgettypedescription"></a>`DESCRIPTION` | Description widget. |
| <a id="workitemwidgettypehierarchy"></a>`HIERARCHY` | Hierarchy widget. |
+| <a id="workitemwidgettypeiteration"></a>`ITERATION` | Iteration widget. |
| <a id="workitemwidgettypelabels"></a>`LABELS` | Labels widget. |
| <a id="workitemwidgettypestart_and_due_date"></a>`START_AND_DUE_DATE` | Start And Due Date widget. |
| <a id="workitemwidgettypeverification_status"></a>`VERIFICATION_STATUS` | Verification Status widget. |
@@ -22433,6 +22446,7 @@ Implementations:
- [`WorkItemWidgetAssignees`](#workitemwidgetassignees)
- [`WorkItemWidgetDescription`](#workitemwidgetdescription)
- [`WorkItemWidgetHierarchy`](#workitemwidgethierarchy)
+- [`WorkItemWidgetIteration`](#workitemwidgetiteration)
- [`WorkItemWidgetLabels`](#workitemwidgetlabels)
- [`WorkItemWidgetStartAndDueDate`](#workitemwidgetstartandduedate)
- [`WorkItemWidgetVerificationStatus`](#workitemwidgetverificationstatus)
@@ -22986,6 +23000,14 @@ A time-frame defined as a closed inclusive range of two dates.
| <a id="workitemwidgethierarchyupdateinputchildrenids"></a>`childrenIds` | [`[WorkItemID!]`](#workitemid) | Global IDs of children work items. |
| <a id="workitemwidgethierarchyupdateinputparentid"></a>`parentId` | [`WorkItemID`](#workitemid) | Global ID of the parent work item. Use `null` to remove the association. |
+### `WorkItemWidgetIterationInput`
+
+#### Arguments
+
+| Name | Type | Description |
+| ---- | ---- | ----------- |
+| <a id="workitemwidgetiterationinputiterationid"></a>`iterationId` | [`IterationID`](#iterationid) | Iteration to assign to the work item. |
+
### `WorkItemWidgetStartAndDueDateUpdateInput`
#### Arguments
diff --git a/doc/api/personal_access_tokens.md b/doc/api/personal_access_tokens.md
index 620b5c2ed0b..7dc31c3f9f0 100644
--- a/doc/api/personal_access_tokens.md
+++ b/doc/api/personal_access_tokens.md
@@ -134,9 +134,13 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
### Using a request header
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/350240) in GitLab 15.0.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/350240) in GitLab 15.0. Limited to tokens with `api` scope.
+> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/369103) in GitLab 15.4, any token can use this endpoint.
-Revokes a personal access token that is passed in using a request header.
+Revokes a personal access token that is passed in using a request header. Requires:
+
+- `api` scope in GitLab 15.0 to GitLab 15.3.
+- Any scope in GitLab 15.4 and later.
```plaintext
DELETE /personal_access_tokens/self
diff --git a/doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md b/doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md
index d46eef0b9fc..4e3abcdae09 100644
--- a/doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md
+++ b/doc/architecture/blueprints/ci_data_decay/pipeline_partitioning.md
@@ -74,6 +74,11 @@ violates our [principle of 100 GB max size](../database_scaling/size-limits.md).
We also want to [build alerting](https://gitlab.com/gitlab-com/gl-infra/tamland/-/issues/5)
to notify us when this number is exceeded.
+Large SQL tables increase index maintenance time, during which freshly deleted tuples
+cannot be cleaned by `autovacuum`. This highlight the need for small tables.
+We will measure how much bloat we accumulate when [re]indexing huge tables. Base on this analysis,
+we will be able to set up SLO (dead tuples / bloat), associated with [re]indexing.
+
We’ve seen numerous S1 and S2 database-related production environment
incidents, over the last couple of months, for example:
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index 35897012b60..79146e0b8bc 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -147,7 +147,7 @@ with [domain expertise](#domain-experts).
| `~workhorse` changes | [Workhorse maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_workhorse). |
| `~frontend` changes (*1*) | [Frontend maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_frontend). |
| `~UX` user-facing changes (*3*) | [Product Designer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_reviewers_UX). Refer to the [design and user interface guidelines](contributing/design.md) for details. |
-| Adding a new JavaScript library (*1*) | <ul><li>[Frontend foundations member](https://about.gitlab.com/direction/ecosystem/foundations/) if the library significantly increases the [bundle size](https://gitlab.com/gitlab-org/frontend/playground/webpack-memory-metrics/-/blob/master/doc/report.md)</li><li>A [legal department member](https://about.gitlab.com/handbook/legal/) if the license used by the new library hasn't been approved for use in GitLab</li></ul> More information about license compatibility can be found in our [GitLab Licensing and Compatibility documentation](licensing.md). |
+| Adding a new JavaScript library (*1*) | - [Frontend foundations member](https://about.gitlab.com/direction/ecosystem/foundations/) if the library significantly increases the [bundle size](https://gitlab.com/gitlab-org/frontend/playground/webpack-memory-metrics/-/blob/master/doc/report.md).<br/>- A [legal department member](https://about.gitlab.com/handbook/legal/) if the license used by the new library hasn't been approved for use in GitLab.<br/><br/>More information about license compatibility can be found in our [GitLab Licensing and Compatibility documentation](licensing.md). |
| A new dependency or a file system change | [Distribution team member](https://about.gitlab.com/company/team/). See how to work with the [Distribution team](https://about.gitlab.com/handbook/engineering/development/enablement/systems/distribution/#how-to-work-with-distribution) for more details. |
| `~documentation` changes | [Technical writer](https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments) based on assignments in the appropriate [DevOps stage group](https://about.gitlab.com/handbook/product/categories/#devops-stages). |
| Changes to development guidelines | Follow the [review process](development_processes.md#development-guidelines-review) and get the approvals accordingly. |
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 79d87cddb47..a14a3843d4f 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -95,7 +95,7 @@ The following table lists project permissions available for each role:
| [Issues](project/issues/index.md):<br>View [Design Management](project/issues/design_management.md) pages | ✓ | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>View [related issues](project/issues/related_issues.md) | ✓ | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Set [weight](project/issues/issue_weight.md) | ✓ (*15*) | ✓ | ✓ | ✓ | ✓ |
-| [Issues]](project/issues/index.md):<br>Set [parent epic](group/epics/manage_epics.md#add-an-existing-issue-to-an-epic) | | ✓ | ✓ | ✓ | ✓ |
+| [Issues](project/issues/index.md):<br>Set [parent epic](group/epics/manage_epics.md#add-an-existing-issue-to-an-epic) | | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>View [confidential issues](project/issues/confidential_issues.md) | (*2*) | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Close / reopen (*19*) | | ✓ | ✓ | ✓ | ✓ |
| [Issues](project/issues/index.md):<br>Lock threads | | ✓ | ✓ | ✓ | ✓ |
diff --git a/lib/api/api.rb b/lib/api/api.rb
index 1edbb1336ed..5a8772d6c56 100644
--- a/lib/api/api.rb
+++ b/lib/api/api.rb
@@ -263,6 +263,7 @@ module API
mount ::API::PackageFiles
mount ::API::Pages
mount ::API::PagesDomains
+ mount ::API::PersonalAccessTokens::SelfRevocation
mount ::API::PersonalAccessTokens
mount ::API::ProjectClusters
mount ::API::ProjectContainerRepositories
diff --git a/lib/api/helpers/personal_access_tokens_helpers.rb b/lib/api/helpers/personal_access_tokens_helpers.rb
new file mode 100644
index 00000000000..db28daa5396
--- /dev/null
+++ b/lib/api/helpers/personal_access_tokens_helpers.rb
@@ -0,0 +1,35 @@
+# frozen_string_literal: true
+
+module API
+ module Helpers
+ module PersonalAccessTokensHelpers
+ def finder_params(current_user)
+ if current_user.can_admin_all_resources?
+ { user: user(params[:user_id]) }
+ else
+ { user: current_user, impersonation: false }
+ end
+ end
+
+ def user(user_id)
+ UserFinder.new(user_id).find_by_id
+ end
+
+ def restrict_non_admins!
+ return if params[:user_id].blank?
+
+ unauthorized! unless Ability.allowed?(current_user, :read_user_personal_access_tokens, user(params[:user_id]))
+ end
+
+ def find_token(id)
+ PersonalAccessToken.find(id) || not_found!
+ end
+
+ def revoke_token(token)
+ service = ::PersonalAccessTokens::RevokeService.new(current_user, token: token).execute
+
+ service.success? ? no_content! : bad_request!(nil)
+ end
+ end
+ end
+end
diff --git a/lib/api/personal_access_tokens.rb b/lib/api/personal_access_tokens.rb
index 0d7d2dc6a0c..1c00569bba2 100644
--- a/lib/api/personal_access_tokens.rb
+++ b/lib/api/personal_access_tokens.rb
@@ -18,34 +18,10 @@ module API
before do
authenticate!
- restrict_non_admins! unless current_user.admin?
+ restrict_non_admins! unless current_user.can_admin_all_resources?
end
- helpers do
- def finder_params(current_user)
- current_user.admin? ? { user: user(params[:user_id]) } : { user: current_user, impersonation: false }
- end
-
- def user(user_id)
- UserFinder.new(user_id).find_by_id
- end
-
- def restrict_non_admins!
- return if params[:user_id].blank?
-
- unauthorized! unless Ability.allowed?(current_user, :read_user_personal_access_tokens, user(params[:user_id]))
- end
-
- def find_token(id)
- PersonalAccessToken.find(id) || not_found!
- end
-
- def revoke_token(token)
- service = ::PersonalAccessTokens::RevokeService.new(current_user, token: token).execute
-
- service.success? ? no_content! : bad_request!(nil)
- end
- end
+ helpers ::API::Helpers::PersonalAccessTokensHelpers
resources :personal_access_tokens do
get do
@@ -63,14 +39,10 @@ module API
present token, with: Entities::PersonalAccessToken
else
# Only admins should be informed if the token doesn't exist
- current_user.admin? ? not_found! : unauthorized!
+ current_user.can_admin_all_resources? ? not_found! : unauthorized!
end
end
- delete 'self' do
- revoke_token(access_token)
- end
-
delete ':id' do
token = find_token(params[:id])
diff --git a/lib/api/personal_access_tokens/self_revocation.rb b/lib/api/personal_access_tokens/self_revocation.rb
new file mode 100644
index 00000000000..22e07f4cc7b
--- /dev/null
+++ b/lib/api/personal_access_tokens/self_revocation.rb
@@ -0,0 +1,26 @@
+# frozen_string_literal: true
+
+module API
+ class PersonalAccessTokens
+ class SelfRevocation < ::API::Base
+ include APIGuard
+
+ feature_category :authentication_and_authorization
+
+ helpers ::API::Helpers::PersonalAccessTokensHelpers
+
+ # As any token regardless of `scope` should be able to revoke itself
+ # all availabe scopes are allowed for this API class.
+ # Please be aware of the permissive scope when adding new endpoints to this class.
+ allow_access_with_scope(Gitlab::Auth.all_available_scopes)
+
+ before { authenticate! }
+
+ resource :personal_access_tokens do
+ delete 'self' do
+ revoke_token(access_token)
+ end
+ end
+ end
+ end
+end
diff --git a/lib/gitlab/ci/trace.rb b/lib/gitlab/ci/trace.rb
index 95a60b852b8..c5664ef1cfb 100644
--- a/lib/gitlab/ci/trace.rb
+++ b/lib/gitlab/ci/trace.rb
@@ -23,7 +23,6 @@ module Gitlab
attr_reader :job
- delegate :old_trace, to: :job
delegate :can_attempt_archival_now?, :increment_archival_attempts!,
:archival_attempts_message, :archival_attempts_available?, to: :trace_metadata
@@ -82,7 +81,7 @@ module Gitlab
end
def live?
- job.trace_chunks.any? || current_path.present? || old_trace.present?
+ job.trace_chunks.any? || current_path.present?
end
def read(&block)
@@ -111,7 +110,6 @@ module Gitlab
# Erase the live trace
erase_trace_chunks!
FileUtils.rm_f(current_path) if current_path # Remove a trace file of a live trace
- job.erase_old_trace! if job.has_old_trace? # Remove a trace in database of a live trace
ensure
@current_path = nil
end
@@ -162,8 +160,6 @@ module Gitlab
Gitlab::Ci::Trace::ChunkedIO.new(job)
elsif current_path
File.open(current_path, "rb")
- elsif old_trace
- StringIO.new(old_trace)
end
end
@@ -210,11 +206,6 @@ module Gitlab
archive_stream!(stream)
FileUtils.rm(current_path)
end
- elsif old_trace
- StringIO.new(old_trace, 'rb').tap do |stream|
- archive_stream!(stream)
- job.erase_old_trace!
- end
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 870bf4d2466..c4e6a38f750 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -33795,6 +33795,9 @@ msgstr ""
msgid "Runners|Add notes, like who owns the runner or what it should be used for."
msgstr ""
+msgid "Runners|Add your feedback in the issue"
+msgstr ""
+
msgid "Runners|All"
msgstr ""
@@ -34230,6 +34233,12 @@ msgstr ""
msgid "Runners|View installation instructions"
msgstr ""
+msgid "Runners|We want you to be able to manage your runners easily and efficiently from this page, and we are making changes to get there. Give us feedback on how we're doing!"
+msgstr ""
+
+msgid "Runners|We've made some changes and want your feedback"
+msgstr ""
+
msgid "Runners|Windows 2019 Shell with manual scaling and optional scheduling. %{percentage} spot."
msgstr ""
diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb
index 0793e790301..556dd23c135 100644
--- a/spec/controllers/projects/jobs_controller_spec.rb
+++ b/spec/controllers/projects/jobs_controller_spec.rb
@@ -5,9 +5,25 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
include ApiHelpers
include HttpIOHelpers
- let(:project) { create(:project, :public, :repository) }
+ let_it_be(:project) { create(:project, :public, :repository) }
+ let_it_be(:owner) { create(:owner) }
+ let_it_be(:admin) { create(:admin) }
+ let_it_be(:maintainer) { create(:user) }
+ let_it_be(:developer) { create(:user) }
+ let_it_be(:reporter) { create(:user) }
+ let_it_be(:guest) { create(:user) }
+
+ before_all do
+ project.add_owner(owner)
+ project.add_maintainer(maintainer)
+ project.add_developer(developer)
+ project.add_reporter(reporter)
+ project.add_guest(guest)
+ end
+
+ let(:user) { developer }
+
let(:pipeline) { create(:ci_pipeline, project: project) }
- let(:user) { create(:user) }
before do
stub_feature_flags(ci_enable_live_trace: true)
@@ -136,9 +152,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
context 'when requesting JSON' do
let(:merge_request) { create(:merge_request, source_project: project) }
+ let(:user) { developer }
before do
- project.add_developer(user)
sign_in(user)
allow_any_instance_of(Ci::Build)
@@ -307,9 +323,10 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
let(:environment) { create(:environment, project: project, name: 'staging', state: :available) }
let(:job) { create(:ci_build, :running, environment: environment.name, pipeline: pipeline) }
+ let(:user) { maintainer }
+
before do
create(:deployment, :success, :on_cluster, environment: environment, project: project)
- project.add_maintainer(user) # Need to be a maintianer to view cluster.path
end
it 'exposes the deployment information' do
@@ -330,9 +347,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
context 'that belongs to the project' do
let(:runner) { create(:ci_runner, :project, projects: [project]) }
let(:job) { create(:ci_build, :success, pipeline: pipeline, runner: runner) }
+ let(:user) { maintainer }
before do
- project.add_maintainer(user)
sign_in(user)
end
@@ -349,10 +366,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
let(:group) { create(:group) }
let(:runner) { create(:ci_runner, :group, groups: [group]) }
let(:job) { create(:ci_build, :success, pipeline: pipeline, runner: runner) }
- let(:user) { create(:user, :admin) }
+ let(:user) { maintainer }
before do
- project.add_maintainer(user)
sign_in(user)
end
@@ -368,10 +384,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
context 'that belongs to instance' do
let(:runner) { create(:ci_runner, :instance) }
let(:job) { create(:ci_build, :success, pipeline: pipeline, runner: runner) }
- let(:user) { create(:user, :admin) }
+ let(:user) { maintainer }
before do
- project.add_maintainer(user)
sign_in(user)
end
@@ -421,6 +436,8 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
context 'when user is developer' do
+ let(:user) { developer }
+
it 'settings_path is not available' do
expect(response).to have_gitlab_http_status(:ok)
expect(response).to match_response_schema('job/job_details')
@@ -429,10 +446,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
context 'when user is maintainer' do
- let(:user) { create(:user, :admin) }
+ let(:user) { admin }
before do
- project.add_maintainer(user)
sign_in(user)
end
@@ -499,9 +515,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
let(:trigger) { create(:ci_trigger, project: project) }
let(:trigger_request) { create(:ci_trigger_request, pipeline: pipeline, trigger: trigger) }
let(:job) { create(:ci_build, pipeline: pipeline, trigger_request: trigger_request) }
+ let(:user) { developer }
before do
- project.add_developer(user)
sign_in(user)
allow_any_instance_of(Ci::Build)
@@ -526,9 +542,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
context 'user is a maintainer' do
- before do
- project.add_maintainer(user)
+ let(:user) { maintainer }
+ before do
get_show_json
end
@@ -579,7 +595,7 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
def get_show_json
expect { get_show(id: job.id, format: :json) }
- .to change { Gitlab::GitalyClient.get_request_count }.by_at_most(2)
+ .to change { Gitlab::GitalyClient.get_request_count }.by_at_most(3)
end
def get_show(**extra_params)
@@ -617,8 +633,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
let!(:variable) { create(:ci_instance_variable, key: 'CI_DEBUG_TRACE', value: 'true') }
context 'with proper permissions on a project' do
+ let(:user) { developer }
+
before do
- project.add_developer(user)
sign_in(user)
end
@@ -630,8 +647,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
context 'without proper permissions for debug logging' do
+ let(:user) { guest }
+
before do
- project.add_guest(user)
sign_in(user)
end
@@ -753,8 +771,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
describe 'POST retry' do
+ let(:user) { developer }
+
before do
- project.add_developer(user)
sign_in(user)
end
@@ -817,12 +836,13 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
describe 'POST play' do
let(:variable_attributes) { [] }
+ let(:user) { developer }
before do
project.add_developer(user)
create(:protected_branch, :developers_can_merge,
- name: 'master', project: project)
+ name: 'protected-branch', project: project)
sign_in(user)
end
@@ -899,8 +919,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
describe 'POST cancel' do
context 'when user is authorized to cancel the build' do
+ let(:user) { developer }
+
before do
- project.add_developer(user)
sign_in(user)
end
@@ -965,8 +986,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
context 'when user is not authorized to cancel the build' do
let!(:job) { create(:ci_build, :cancelable, pipeline: pipeline) }
+ let(:user) { guest }
+
before do
- project.add_reporter(user)
sign_in(user)
post_cancel
@@ -990,12 +1012,13 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
describe 'POST unschedule' do
before do
- create(:protected_branch, :developers_can_merge, name: 'master', project: project)
+ create(:protected_branch, :developers_can_merge, name: 'protected-branch', project: project)
end
context 'when user is authorized to unschedule the build' do
+ let(:user) { developer }
+
before do
- project.add_developer(user)
sign_in(user)
post_unschedule
@@ -1025,9 +1048,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
context 'when user is not authorized to unschedule the build' do
let(:job) { create(:ci_build, :scheduled, pipeline: pipeline) }
+ let(:user) { guest }
before do
- project.add_reporter(user)
sign_in(user)
post_unschedule
@@ -1048,10 +1071,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
describe 'POST erase' do
- let(:role) { :maintainer }
+ let(:user) { maintainer }
before do
- project.add_role(user, role)
sign_in(user)
end
@@ -1097,7 +1119,7 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
context 'when user is developer' do
- let(:role) { :developer }
+ let(:user) { developer }
let(:job) { create(:ci_build, :erasable, :trace_artifact, pipeline: pipeline, user: triggered_by) }
context 'when triggered by same user' do
@@ -1109,7 +1131,7 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
context 'when triggered by different user' do
- let(:triggered_by) { create(:user) }
+ let(:triggered_by) { maintainer }
it 'does not have successful status' do
expect(response).not_to have_gitlab_http_status(:found)
@@ -1168,8 +1190,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
context 'with proper permissions for debug logging on a project' do
+ let(:user) { developer }
+
before do
- project.add_developer(user)
sign_in(user)
end
@@ -1181,8 +1204,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
context 'without proper permissions for debug logging on a project' do
+ let(:user) { reporter }
+
before do
- project.add_reporter(user)
sign_in(user)
end
@@ -1218,37 +1242,6 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
end
- context "when job has a trace in database" do
- let(:job) { create(:ci_build, pipeline: pipeline) }
-
- before do
- job.update_column(:trace, "Sample trace")
- end
-
- it 'sends a trace file' do
- response = subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers['Content-Type']).to eq('text/plain; charset=utf-8')
- expect(response.headers['Content-Disposition']).to match(/^inline/)
- expect(response.body).to eq('Sample trace')
- end
-
- context 'when trace format is not text/plain' do
- before do
- job.update_column(:trace, '<html></html>')
- end
-
- it 'sets content disposition to attachment' do
- response = subject
-
- expect(response).to have_gitlab_http_status(:ok)
- expect(response.headers['Content-Type']).to eq('text/plain; charset=utf-8')
- expect(response.headers['Content-Disposition']).to match(/^attachment/)
- end
- end
- end
-
context 'when job does not have a trace file' do
let(:job) { create(:ci_build, pipeline: pipeline) }
@@ -1274,8 +1267,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
describe 'GET #terminal' do
+ let(:user) { developer }
+
before do
- project.add_developer(user)
sign_in(user)
end
@@ -1323,8 +1317,9 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
describe 'GET #terminal_websocket_authorize' do
let!(:job) { create(:ci_build, :running, :with_runner_session, pipeline: pipeline, user: user) }
+ let(:user) { developer }
+
before do
- project.add_developer(user)
sign_in(user)
end
@@ -1375,14 +1370,6 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
end
describe 'GET #proxy_websocket_authorize' do
- let_it_be(:owner) { create(:owner) }
- let_it_be(:admin) { create(:admin) }
- let_it_be(:maintainer) { create(:user) }
- let_it_be(:developer) { create(:user) }
- let_it_be(:reporter) { create(:user) }
- let_it_be(:guest) { create(:user) }
- let_it_be(:project) { create(:project, :private, :repository, namespace: owner.namespace) }
-
let(:user) { maintainer }
let(:pipeline) { create(:ci_pipeline, project: project, source: :webide, config_source: :webide_source, user: user) }
let(:job) { create(:ci_build, :running, :with_runner_session, pipeline: pipeline, user: user) }
@@ -1407,11 +1394,6 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
stub_feature_flags(build_service_proxy: true)
allow(job).to receive(:has_terminal?).and_return(true)
- project.add_maintainer(maintainer)
- project.add_developer(developer)
- project.add_reporter(reporter)
- project.add_guest(guest)
-
sign_in(user)
end
diff --git a/spec/features/projects/show/user_interacts_with_stars_spec.rb b/spec/features/projects/show/user_interacts_with_stars_spec.rb
index aa61b629d92..e0dd4f65010 100644
--- a/spec/features/projects/show/user_interacts_with_stars_spec.rb
+++ b/spec/features/projects/show/user_interacts_with_stars_spec.rb
@@ -14,14 +14,36 @@ RSpec.describe 'Projects > Show > User interacts with project stars' do
end
it 'toggles the star' do
- find('.star-btn').click
+ star_project
expect(page).to have_css('.star-count', text: 1)
- find('.star-btn').click
+ unstar_project
expect(page).to have_css('.star-count', text: 0)
end
+
+ it 'validates starring a project' do
+ project.add_owner(user)
+
+ star_project
+
+ visit(dashboard_projects_path)
+
+ expect(page).to have_css('.stars', text: 1)
+ end
+
+ it 'validates un-starring a project' do
+ project.add_owner(user)
+
+ star_project
+
+ unstar_project
+
+ visit(dashboard_projects_path)
+
+ expect(page).to have_css('.stars', text: 0)
+ end
end
context 'when user is not signed in' do
@@ -38,3 +60,15 @@ RSpec.describe 'Projects > Show > User interacts with project stars' do
end
end
end
+
+private
+
+def star_project
+ click_button(_('Star'))
+ wait_for_requests
+end
+
+def unstar_project
+ click_button(_('Unstar'))
+ wait_for_requests
+end
diff --git a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
index ebbb6ed27c7..55a298e1695 100644
--- a/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
+++ b/spec/frontend/runner/admin_runners/admin_runners_app_spec.js
@@ -17,6 +17,7 @@ import { updateHistory } from '~/lib/utils/url_utility';
import { upgradeStatusTokenConfig } from 'ee_else_ce/runner/components/search_tokens/upgrade_status_token_config';
import { createLocalState } from '~/runner/graphql/list/local_state';
import AdminRunnersApp from '~/runner/admin_runners/admin_runners_app.vue';
+import RunnerStackedLayoutBanner from '~/runner/components/runner_stacked_layout_banner.vue';
import RunnerTypeTabs from '~/runner/components/runner_type_tabs.vue';
import RunnerFilteredSearchBar from '~/runner/components/runner_filtered_search_bar.vue';
import RunnerBulkDelete from '~/runner/components/runner_bulk_delete.vue';
@@ -86,6 +87,7 @@ describe('AdminRunnersApp', () => {
let localMutations;
let showToast;
+ const findRunnerStackedLayoutBanner = () => wrapper.findComponent(RunnerStackedLayoutBanner);
const findRunnerStats = () => wrapper.findComponent(RunnerStats);
const findRunnerActionsCell = () => wrapper.findComponent(RunnerActionsCell);
const findRegistrationDropdown = () => wrapper.findComponent(RegistrationDropdown);
@@ -145,6 +147,11 @@ describe('AdminRunnersApp', () => {
wrapper.destroy();
});
+ it('shows the feedback banner', () => {
+ createComponent();
+ expect(findRunnerStackedLayoutBanner().exists()).toBe(true);
+ });
+
it('shows the runner setup instructions', () => {
createComponent();
diff --git a/spec/frontend/runner/components/runner_stacked_layout_banner_spec.js b/spec/frontend/runner/components/runner_stacked_layout_banner_spec.js
new file mode 100644
index 00000000000..b892cfc7d3d
--- /dev/null
+++ b/spec/frontend/runner/components/runner_stacked_layout_banner_spec.js
@@ -0,0 +1,57 @@
+import Vue from 'vue';
+import { GlBanner } from '@gitlab/ui';
+import { shallowMount } from '@vue/test-utils';
+import RunnerStackedLayoutBanner from '~/runner/components/runner_stacked_layout_banner.vue';
+import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
+
+describe('RunnerStackedLayoutBanner', () => {
+ let wrapper;
+
+ const findBanner = () => wrapper.findComponent(GlBanner);
+ const findLocalStorageSync = () => wrapper.findComponent(LocalStorageSync);
+
+ const createComponent = ({ ...options } = {}, mountFn = shallowMount) => {
+ wrapper = mountFn(RunnerStackedLayoutBanner, {
+ ...options,
+ });
+ };
+
+ it('Does not display a banner', () => {
+ createComponent();
+
+ expect(findBanner().exists()).toBe(false);
+ });
+
+ describe.each`
+ glFeatures
+ ${{ runnerListStackedLayoutAdmin: true }}
+ ${{ runnerListStackedLayout: true }}
+ `('When glFeatures = $glFeatures', ({ glFeatures }) => {
+ beforeEach(() => {
+ createComponent({
+ provide: {
+ glFeatures,
+ },
+ });
+ });
+
+ it('Displays a banner', () => {
+ expect(findBanner().props()).toMatchObject({
+ svgPath: expect.stringContaining('data:image/svg+xml;utf8,'),
+ title: expect.any(String),
+ buttonText: expect.any(String),
+ buttonLink: expect.stringContaining('https://gitlab.com/gitlab-org/gitlab/-/issues/'),
+ });
+ expect(findLocalStorageSync().exists()).toBe(true);
+ });
+
+ it('Does not display a banner when dismissed', async () => {
+ findLocalStorageSync().vm.$emit('input', true);
+
+ await Vue.nextTick();
+
+ expect(findBanner().exists()).toBe(false);
+ expect(findLocalStorageSync().exists()).toBe(true); // continues syncing after removal
+ });
+ });
+});
diff --git a/spec/frontend/runner/group_runners/group_runners_app_spec.js b/spec/frontend/runner/group_runners/group_runners_app_spec.js
index 2335cd5d7d6..a17502c7eec 100644
--- a/spec/frontend/runner/group_runners/group_runners_app_spec.js
+++ b/spec/frontend/runner/group_runners/group_runners_app_spec.js
@@ -15,6 +15,7 @@ import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { updateHistory } from '~/lib/utils/url_utility';
import { upgradeStatusTokenConfig } from 'ee_else_ce/runner/components/search_tokens/upgrade_status_token_config';
+import RunnerStackedLayoutBanner from '~/runner/components/runner_stacked_layout_banner.vue';
import RunnerTypeTabs from '~/runner/components/runner_type_tabs.vue';
import RunnerFilteredSearchBar from '~/runner/components/runner_filtered_search_bar.vue';
import RunnerList from '~/runner/components/runner_list.vue';
@@ -77,6 +78,7 @@ jest.mock('~/lib/utils/url_utility', () => ({
describe('GroupRunnersApp', () => {
let wrapper;
+ const findRunnerStackedLayoutBanner = () => wrapper.findComponent(RunnerStackedLayoutBanner);
const findRunnerStats = () => wrapper.findComponent(RunnerStats);
const findRunnerActionsCell = () => wrapper.findComponent(RunnerActionsCell);
const findRegistrationDropdown = () => wrapper.findComponent(RegistrationDropdown);
@@ -125,6 +127,11 @@ describe('GroupRunnersApp', () => {
wrapper.destroy();
});
+ it('shows the feedback banner', () => {
+ createComponent();
+ expect(findRunnerStackedLayoutBanner().exists()).toBe(true);
+ });
+
it('shows the runner tabs with a runner count for each type', async () => {
await createComponent({ mountFn: mountExtended });
diff --git a/spec/lib/gitlab/ci/config/external/mapper_spec.rb b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
index e74fdc2071b..9eaba12f388 100644
--- a/spec/lib/gitlab/ci/config/external/mapper_spec.rb
+++ b/spec/lib/gitlab/ci/config/external/mapper_spec.rb
@@ -210,7 +210,7 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
{ 'local' => local_file },
{ 'local' => local_file }
],
- image: 'image:1.0' }
+ image: 'image:1.0' }
end
it 'does not raise an exception' do
@@ -427,7 +427,7 @@ RSpec.describe Gitlab::Ci::Config::External::Mapper do
{ 'local' => 'hello/secret-file1.yml' },
{ 'local' => 'hello/secret-file2.yml' }
],
- image: 'ruby:2.7' }
+ image: 'ruby:2.7' }
end
it 'has expanset with two' do
diff --git a/spec/lib/gitlab/ci/lint_spec.rb b/spec/lib/gitlab/ci/lint_spec.rb
index 7e0b2b5aa8e..3d46d266c13 100644
--- a/spec/lib/gitlab/ci/lint_spec.rb
+++ b/spec/lib/gitlab/ci/lint_spec.rb
@@ -341,9 +341,9 @@ RSpec.describe Gitlab::Ci::Lint do
let(:counters) do
{
'count' => a_kind_of(Numeric),
- 'avg' => a_kind_of(Numeric),
- 'max' => a_kind_of(Numeric),
- 'min' => a_kind_of(Numeric)
+ 'avg' => a_kind_of(Numeric),
+ 'max' => a_kind_of(Numeric),
+ 'min' => a_kind_of(Numeric)
}
end
diff --git a/spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb
index 51185be3e74..6569ce937ac 100644
--- a/spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/seed/deployment_spec.rb
@@ -6,8 +6,7 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Deployment do
let_it_be(:project, refind: true) { create(:project, :repository) }
let(:pipeline) do
- create(:ci_pipeline, project: project,
- sha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0')
+ create(:ci_pipeline, project: project, sha: 'b83d6e391c22777fca1ed3012fce84f633d7fed0')
end
let(:job) { build(:ci_build, project: project, pipeline: pipeline) }
diff --git a/spec/lib/gitlab/ci/trace_spec.rb b/spec/lib/gitlab/ci/trace_spec.rb
index 888ceb7ff9a..3043c8c5467 100644
--- a/spec/lib/gitlab/ci/trace_spec.rb
+++ b/spec/lib/gitlab/ci/trace_spec.rb
@@ -10,7 +10,6 @@ RSpec.describe Gitlab::Ci::Trace, :clean_gitlab_redis_shared_state, factory_defa
describe "associations" do
it { expect(trace).to respond_to(:job) }
- it { expect(trace).to delegate_method(:old_trace).to(:job) }
end
context 'when trace is migrated to object storage' do
diff --git a/spec/lib/gitlab/ci/variables/builder_spec.rb b/spec/lib/gitlab/ci/variables/builder_spec.rb
index fc6211a7ba3..4833ccf9093 100644
--- a/spec/lib/gitlab/ci/variables/builder_spec.rb
+++ b/spec/lib/gitlab/ci/variables/builder_spec.rb
@@ -138,11 +138,11 @@ RSpec.describe Gitlab::Ci::Variables::Builder, :clean_gitlab_redis_cache do
{ key: 'GITLAB_USER_ID',
value: user.id.to_s },
{ key: 'GITLAB_USER_EMAIL',
- value: user.email },
+ value: user.email },
{ key: 'GITLAB_USER_LOGIN',
- value: user.username },
+ value: user.username },
{ key: 'GITLAB_USER_NAME',
- value: user.name }
+ value: user.name }
].map { |var| var.merge(public: true, masked: false) }
end
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index bffdd370179..b68b12d8f43 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -298,8 +298,8 @@ module Gitlab
context 'when delayed is defined' do
let(:config) do
YAML.dump(rspec: {
- script: 'rollout 10%',
- when: 'delayed',
+ script: 'rollout 10%',
+ when: 'delayed',
start_in: '1 day'
})
end
@@ -315,7 +315,7 @@ module Gitlab
context 'when resource group is defined' do
let(:config) do
YAML.dump(rspec: {
- script: 'test',
+ script: 'test',
resource_group: 'iOS'
})
end
@@ -1676,10 +1676,10 @@ module Gitlab
describe "Artifacts" do
it "returns artifacts when defined" do
config = YAML.dump({
- image: "image:1.0",
- services: ["mysql"],
+ image: "image:1.0",
+ services: ["mysql"],
before_script: ["pwd"],
- rspec: {
+ rspec: {
artifacts: {
paths: ["logs/", "binaries/"],
expose_as: "Exposed artifacts",
@@ -1935,7 +1935,7 @@ module Gitlab
let(:config) do
{
deploy_to_production: {
- stage: 'deploy',
+ stage: 'deploy',
script: 'test'
}
}
@@ -2304,15 +2304,15 @@ module Gitlab
let(:config) do
{
- var_default: { stage: 'build', script: 'test', rules: [{ if: '$VAR == null' }] },
- var_when: { stage: 'build', script: 'test', rules: [{ if: '$VAR == null', when: 'always' }] },
+ var_default: { stage: 'build', script: 'test', rules: [{ if: '$VAR == null' }] },
+ var_when: { stage: 'build', script: 'test', rules: [{ if: '$VAR == null', when: 'always' }] },
var_and_changes: { stage: 'build', script: 'test', rules: [{ if: '$VAR == null', changes: %w[README], when: 'always' }] },
changes_not_var: { stage: 'test', script: 'test', rules: [{ if: '$VAR != null', changes: %w[README] }] },
var_not_changes: { stage: 'test', script: 'test', rules: [{ if: '$VAR == null', changes: %w[other/file.rb], when: 'always' }] },
- nothing: { stage: 'test', script: 'test', rules: [{ when: 'manual' }] },
- var_never: { stage: 'deploy', script: 'test', rules: [{ if: '$VAR == null', when: 'never' }] },
- var_delayed: { stage: 'deploy', script: 'test', rules: [{ if: '$VAR == null', when: 'delayed', start_in: '3 hours' }] },
- two_rules: { stage: 'deploy', script: 'test', rules: [{ if: '$VAR == null', when: 'on_success' }, { changes: %w[README], when: 'manual' }] }
+ nothing: { stage: 'test', script: 'test', rules: [{ when: 'manual' }] },
+ var_never: { stage: 'deploy', script: 'test', rules: [{ if: '$VAR == null', when: 'never' }] },
+ var_delayed: { stage: 'deploy', script: 'test', rules: [{ if: '$VAR == null', when: 'delayed', start_in: '3 hours' }] },
+ two_rules: { stage: 'deploy', script: 'test', rules: [{ if: '$VAR == null', when: 'on_success' }, { changes: %w[README], when: 'manual' }] }
}
end
diff --git a/spec/lib/gitlab/data_builder/issuable_spec.rb b/spec/lib/gitlab/data_builder/issuable_spec.rb
index f0802f335f4..455800a3f7d 100644
--- a/spec/lib/gitlab/data_builder/issuable_spec.rb
+++ b/spec/lib/gitlab/data_builder/issuable_spec.rb
@@ -73,7 +73,7 @@ RSpec.describe Gitlab::DataBuilder::Issuable do
},
assignees: {
previous: [],
- current: [{
+ current: [{
name: "Foo Bar",
username: "foobar",
avatar_url: "http://www.example.com/my-avatar.jpg"
diff --git a/spec/lib/gitlab/data_builder/note_spec.rb b/spec/lib/gitlab/data_builder/note_spec.rb
index 3fa535dd800..8e8b8ce6681 100644
--- a/spec/lib/gitlab/data_builder/note_spec.rb
+++ b/spec/lib/gitlab/data_builder/note_spec.rb
@@ -49,8 +49,7 @@ RSpec.describe Gitlab::DataBuilder::Note do
let(:label) { create(:label, project: project) }
let(:issue) do
- create(:labeled_issue, created_at: fixed_time, updated_at: fixed_time,
- project: project, labels: [label])
+ create(:labeled_issue, created_at: fixed_time, updated_at: fixed_time, project: project, labels: [label])
end
let(:note) do
@@ -84,15 +83,15 @@ RSpec.describe Gitlab::DataBuilder::Note do
describe 'When asking for a note on merge request' do
let(:label) { create(:label, project: project) }
let(:merge_request) do
- create(:labeled_merge_request, created_at: fixed_time,
- updated_at: fixed_time,
- source_project: project,
- labels: [label])
+ create(:labeled_merge_request,
+ created_at: fixed_time,
+ updated_at: fixed_time,
+ source_project: project,
+ labels: [label])
end
let(:note) do
- create(:note_on_merge_request, noteable: merge_request,
- project: project)
+ create(:note_on_merge_request, noteable: merge_request, project: project)
end
it_behaves_like 'includes general data'
@@ -112,14 +111,15 @@ RSpec.describe Gitlab::DataBuilder::Note do
describe 'When asking for a note on merge request diff' do
let(:label) { create(:label, project: project) }
let(:merge_request) do
- create(:labeled_merge_request, created_at: fixed_time, updated_at: fixed_time,
- source_project: project,
- labels: [label])
+ create(:labeled_merge_request,
+ created_at: fixed_time,
+ updated_at: fixed_time,
+ source_project:
+ project, labels: [label])
end
let(:note) do
- create(:diff_note_on_merge_request, noteable: merge_request,
- project: project)
+ create(:diff_note_on_merge_request, noteable: merge_request, project: project)
end
it_behaves_like 'includes general data'
@@ -138,13 +138,11 @@ RSpec.describe Gitlab::DataBuilder::Note do
describe 'When asking for a note on project snippet' do
let!(:snippet) do
- create(:project_snippet, created_at: fixed_time, updated_at: fixed_time,
- project: project)
+ create(:project_snippet, created_at: fixed_time, updated_at: fixed_time, project: project)
end
let!(:note) do
- create(:note_on_project_snippet, noteable: snippet,
- project: project)
+ create(:note_on_project_snippet, noteable: snippet, project: project)
end
it_behaves_like 'includes general data'
diff --git a/spec/lib/gitlab/database/migration_helpers_spec.rb b/spec/lib/gitlab/database/migration_helpers_spec.rb
index dd5ad40d8ef..d73b478ee7c 100644
--- a/spec/lib/gitlab/database/migration_helpers_spec.rb
+++ b/spec/lib/gitlab/database/migration_helpers_spec.rb
@@ -667,7 +667,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
column: :user_id,
on_delete: :cascade,
name: name,
- primary_key: :id).and_return(true)
+ primary_key: :id).and_return(true)
expect(model).not_to receive(:execute).with(/ADD CONSTRAINT/)
expect(model).to receive(:execute).with(/VALIDATE CONSTRAINT/)
diff --git a/spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb b/spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb
index 04b9fba5b2f..1768f97de54 100644
--- a/spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb
+++ b/spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb
@@ -181,9 +181,10 @@ RSpec.describe Gitlab::Database::Partitioning::SlidingListStrategy do
Class.new(ApplicationRecord) do
include PartitionedTable
- partitioned_by :partition, strategy: :sliding_list,
- next_partition_if: proc { false },
- detach_partition_if: proc { false }
+ partitioned_by :partition,
+ strategy: :sliding_list,
+ next_partition_if: proc { false },
+ detach_partition_if: proc { false }
end
end.to raise_error(/ignored_columns/)
end
@@ -195,7 +196,8 @@ RSpec.describe Gitlab::Database::Partitioning::SlidingListStrategy do
self.ignored_columns = [:partition]
- partitioned_by :partition, strategy: :sliding_list,
+ partitioned_by :partition,
+ strategy: :sliding_list,
next_partition_if: proc { false },
detach_partition_if: proc { false }
end
@@ -221,7 +223,8 @@ RSpec.describe Gitlab::Database::Partitioning::SlidingListStrategy do
def self.detach_partition_if_wrapper(...)
detach_partition?(...)
end
- partitioned_by :partition, strategy: :sliding_list,
+ partitioned_by :partition,
+ strategy: :sliding_list,
next_partition_if: method(:next_partition_if_wrapper),
detach_partition_if: method(:detach_partition_if_wrapper)
diff --git a/spec/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table_spec.rb b/spec/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table_spec.rb
index 3072c413246..1885e84ac4c 100644
--- a/spec/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table_spec.rb
+++ b/spec/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table_spec.rb
@@ -97,7 +97,8 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::BackfillPartition
end
it 'marks each job record as succeeded after processing' do
- create(:background_migration_job, class_name: "::#{described_class.name}",
+ create(:background_migration_job,
+ class_name: "::#{described_class.name}",
arguments: [source1.id, source3.id, source_table, destination_table, unique_key])
expect(::Gitlab::Database::BackgroundMigrationJob).to receive(:mark_all_as_succeeded).and_call_original
@@ -108,7 +109,8 @@ RSpec.describe Gitlab::Database::PartitioningMigrationHelpers::BackfillPartition
end
it 'returns the number of job records marked as succeeded' do
- create(:background_migration_job, class_name: "::#{described_class.name}",
+ create(:background_migration_job,
+ class_name: "::#{described_class.name}",
arguments: [source1.id, source3.id, source_table, destination_table, unique_key])
jobs_updated = backfill_job.perform(source1.id, source3.id, source_table, destination_table, unique_key)
diff --git a/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb b/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb
index 6601b6658d5..ad91320c6eb 100644
--- a/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb
+++ b/spec/lib/gitlab/database_importers/self_monitoring/project/create_service_spec.rb
@@ -181,8 +181,8 @@ RSpec.describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService
let(:existing_project) { create(:project, namespace: existing_group) }
before do
- application_setting.update!(instance_administrators_group_id: existing_group.id,
- self_monitoring_project_id: existing_project.id)
+ application_setting.update!(
+ instance_administrators_group_id: existing_group.id, self_monitoring_project_id: existing_project.id)
end
it 'returns success' do
diff --git a/spec/lib/gitlab/diff/highlight_cache_spec.rb b/spec/lib/gitlab/diff/highlight_cache_spec.rb
index 68a2b17840c..53e74748234 100644
--- a/spec/lib/gitlab/diff/highlight_cache_spec.rb
+++ b/spec/lib/gitlab/diff/highlight_cache_spec.rb
@@ -9,33 +9,33 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do
{ ".gitignore-false-false-false" =>
[{ line_code: nil, rich_text: nil, text: "@@ -17,3 +17,4 @@ rerun.txt", type: "match", index: 0, old_pos: 17, new_pos: 17 },
{ line_code: "a5cc2925ca8258af241be7e5b0381edf30266302_17_17",
- rich_text: " <span id=\"LC17\" class=\"line\" lang=\"plaintext\">pickle-email-*.html</span>\n",
- text: " pickle-email-*.html",
- type: nil,
- index: 1,
- old_pos: 17,
- new_pos: 17 },
+ rich_text: " <span id=\"LC17\" class=\"line\" lang=\"plaintext\">pickle-email-*.html</span>\n",
+ text: " pickle-email-*.html",
+ type: nil,
+ index: 1,
+ old_pos: 17,
+ new_pos: 17 },
{ line_code: "a5cc2925ca8258af241be7e5b0381edf30266302_18_18",
- rich_text: " <span id=\"LC18\" class=\"line\" lang=\"plaintext\">.project</span>\n",
- text: " .project",
- type: nil,
- index: 2,
- old_pos: 18,
- new_pos: 18 },
+ rich_text: " <span id=\"LC18\" class=\"line\" lang=\"plaintext\">.project</span>\n",
+ text: " .project",
+ type: nil,
+ index: 2,
+ old_pos: 18,
+ new_pos: 18 },
{ line_code: "a5cc2925ca8258af241be7e5b0381edf30266302_19_19",
- rich_text: " <span id=\"LC19\" class=\"line\" lang=\"plaintext\">config/initializers/secret_token.rb</span>\n",
- text: " config/initializers/secret_token.rb",
- type: nil,
- index: 3,
- old_pos: 19,
- new_pos: 19 },
+ rich_text: " <span id=\"LC19\" class=\"line\" lang=\"plaintext\">config/initializers/secret_token.rb</span>\n",
+ text: " config/initializers/secret_token.rb",
+ type: nil,
+ index: 3,
+ old_pos: 19,
+ new_pos: 19 },
{ line_code: "a5cc2925ca8258af241be7e5b0381edf30266302_20_20",
- rich_text: "+<span id=\"LC20\" class=\"line\" lang=\"plaintext\">.DS_Store</span>",
- text: "+.DS_Store",
- type: "new",
- index: 4,
- old_pos: 20,
- new_pos: 20 }] }
+ rich_text: "+<span id=\"LC20\" class=\"line\" lang=\"plaintext\">.DS_Store</span>",
+ text: "+.DS_Store",
+ type: "new",
+ index: 4,
+ old_pos: 20,
+ new_pos: 20 }] }
end
let(:cache_key) { cache.key }
diff --git a/spec/lib/gitlab/diff/lines_unfolder_spec.rb b/spec/lib/gitlab/diff/lines_unfolder_spec.rb
index f0e710be2e4..98f0c4df204 100644
--- a/spec/lib/gitlab/diff/lines_unfolder_spec.rb
+++ b/spec/lib/gitlab/diff/lines_unfolder_spec.rb
@@ -189,14 +189,14 @@ RSpec.describe Gitlab::Diff::LinesUnfolder do
let(:diff) do
Gitlab::Git::Diff.new({ diff: raw_diff,
- new_path: "build-aux/flatpak/org.gnome.Nautilus.json",
- old_path: "build-aux/flatpak/org.gnome.Nautilus.json",
- a_mode: "100644",
- b_mode: "100644",
- new_file: false,
- renamed_file: false,
- deleted_file: false,
- too_large: false })
+ new_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ old_path: "build-aux/flatpak/org.gnome.Nautilus.json",
+ a_mode: "100644",
+ b_mode: "100644",
+ new_file: false,
+ renamed_file: false,
+ deleted_file: false,
+ too_large: false })
end
let(:diff_file) do
diff --git a/spec/lib/gitlab/diff/position_spec.rb b/spec/lib/gitlab/diff/position_spec.rb
index bb3522eb579..00a468bfef6 100644
--- a/spec/lib/gitlab/diff/position_spec.rb
+++ b/spec/lib/gitlab/diff/position_spec.rb
@@ -684,7 +684,7 @@ RSpec.describe Gitlab::Diff::Position do
"old_line" => 18,
"new_line" => 18
},
- "end" => {
+ "end" => {
"line_code" => end_line_code,
"type" => nil,
"old_line" => end_old_line,
diff --git a/spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb b/spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb
index 210829056c8..c9b632b50e1 100644
--- a/spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb
+++ b/spec/lib/gitlab/error_tracking/processor/context_payload_processor_spec.rb
@@ -38,10 +38,10 @@ RSpec.describe Gitlab::ErrorTracking::Processor::ContextPayloadProcessor do
expect(result_hash[:tags])
.to include(priority: 'high',
- locale: 'en',
- program: 'test',
- feature_category: 'feature_a',
- correlation_id: 'cid')
+ locale: 'en',
+ program: 'test',
+ feature_category: 'feature_a',
+ correlation_id: 'cid')
expect(result_hash[:extra])
.to include(some_info: 'info',
diff --git a/spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb b/spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb
index 577d59798da..3d23249d00d 100644
--- a/spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb
+++ b/spec/lib/gitlab/error_tracking/stack_trace_highlight_decorator_spec.rb
@@ -52,7 +52,7 @@ RSpec.describe Gitlab::ErrorTracking::StackTraceHighlightDecorator do
'function' => 'print',
'lineNo' => 3,
'filename' => 'hello_world.php',
- 'context' => [
+ 'context' => [
[1, '<span id="LC1" class="line" lang="hack"><span class="c1">// PHP/Hack example</span></span>'],
[2, '<span id="LC1" class="line" lang="hack"><span class="cp">&lt;?php</span></span>'],
[3, '<span id="LC1" class="line" lang="hack"><span class="k">echo</span> <span class="s1">\'Hello, World!\'</span><span class="p">;</span></span>']
diff --git a/spec/lib/gitlab/etag_caching/middleware_spec.rb b/spec/lib/gitlab/etag_caching/middleware_spec.rb
index 8228f95dd5e..da5eaf2e4ab 100644
--- a/spec/lib/gitlab/etag_caching/middleware_spec.rb
+++ b/spec/lib/gitlab/etag_caching/middleware_spec.rb
@@ -119,11 +119,11 @@ RSpec.describe Gitlab::EtagCaching::Middleware, :clean_gitlab_redis_shared_state
let(:expected_items) do
{
etag_route: endpoint,
- params: {},
- format: :html,
- method: 'GET',
- path: enabled_path,
- status: status_code
+ params: {},
+ format: :html,
+ method: 'GET',
+ path: enabled_path,
+ status: status_code
}
end
diff --git a/spec/lib/gitlab/etag_caching/router/graphql_spec.rb b/spec/lib/gitlab/etag_caching/router/graphql_spec.rb
index 9a6787e3640..792f02f8cda 100644
--- a/spec/lib/gitlab/etag_caching/router/graphql_spec.rb
+++ b/spec/lib/gitlab/etag_caching/router/graphql_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe Gitlab::EtagCaching::Router::Graphql do
def match_route(path, header)
described_class.match(
double(path_info: path,
- headers: { 'X-GITLAB-GRAPHQL-RESOURCE-ETAG' => header }))
+ headers: { 'X-GITLAB-GRAPHQL-RESOURCE-ETAG' => header }))
end
describe '.cache_key' do
diff --git a/spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb b/spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb
index 487b19a98e0..5006d27c356 100644
--- a/spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb
+++ b/spec/lib/gitlab/grape_logging/formatters/lograge_with_timestamp_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Gitlab::GrapeLogging::Formatters::LogrageWithTimestamp do
let(:log_entry) do
{
status: 200,
- time: {
+ time: {
total: 758.58,
db: 77.06,
view: 681.52
diff --git a/spec/lib/gitlab/import_export/attributes_finder_spec.rb b/spec/lib/gitlab/import_export/attributes_finder_spec.rb
index 428d8d605ee..6536b895b2f 100644
--- a/spec/lib/gitlab/import_export/attributes_finder_spec.rb
+++ b/spec/lib/gitlab/import_export/attributes_finder_spec.rb
@@ -123,7 +123,7 @@ RSpec.describe Gitlab::ImportExport::AttributesFinder do
is_expected.to match(
include: [{ merge_requests: {
include: [{ notes: { include: [{ author: { include: [] } }],
- preload: { author: nil } } }],
+ preload: { author: nil } } }],
preload: { notes: { author: nil } }
} }],
preload: { merge_requests: { notes: { author: nil } } }
@@ -132,7 +132,7 @@ RSpec.describe Gitlab::ImportExport::AttributesFinder do
it 'generates the correct hash for a relation with included attributes' do
setup_yaml(tree: { project: [:issues] },
- included_attributes: { issues: [:name, :description] })
+ included_attributes: { issues: [:name, :description] })
is_expected.to match(
include: [{ issues: { include: [],
@@ -143,7 +143,7 @@ RSpec.describe Gitlab::ImportExport::AttributesFinder do
it 'generates the correct hash for a relation with excluded attributes' do
setup_yaml(tree: { project: [:issues] },
- excluded_attributes: { issues: [:name] })
+ excluded_attributes: { issues: [:name] })
is_expected.to match(
include: [{ issues: { except: [:name],
@@ -154,8 +154,8 @@ RSpec.describe Gitlab::ImportExport::AttributesFinder do
it 'generates the correct hash for a relation with both excluded and included attributes' do
setup_yaml(tree: { project: [:issues] },
- excluded_attributes: { issues: [:name] },
- included_attributes: { issues: [:description] })
+ excluded_attributes: { issues: [:name] },
+ included_attributes: { issues: [:description] })
is_expected.to match(
include: [{ issues: { except: [:name],
@@ -167,7 +167,7 @@ RSpec.describe Gitlab::ImportExport::AttributesFinder do
it 'generates the correct hash for a relation with custom methods' do
setup_yaml(tree: { project: [:issues] },
- methods: { issues: [:name] })
+ methods: { issues: [:name] })
is_expected.to match(
include: [{ issues: { include: [],
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index eac8115742d..3a656c4a42d 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -1225,70 +1225,6 @@ RSpec.describe Ci::Build do
end
end
- describe '#has_old_trace?' do
- subject { build.has_old_trace? }
-
- context 'when old trace exists' do
- before do
- build.update_column(:trace, 'old trace')
- end
-
- it { is_expected.to be_truthy }
- end
-
- context 'when old trace does not exist' do
- it { is_expected.to be_falsy }
- end
- end
-
- describe '#trace=' do
- it "expect to fail trace=" do
- expect { build.trace = "new" }.to raise_error(NotImplementedError)
- end
- end
-
- describe '#old_trace' do
- subject { build.old_trace }
-
- before do
- build.update_column(:trace, 'old trace')
- end
-
- it "expect to receive data from database" do
- is_expected.to eq('old trace')
- end
- end
-
- describe '#erase_old_trace!' do
- subject { build.erase_old_trace! }
-
- context 'when old trace exists' do
- before do
- build.update_column(:trace, 'old trace')
- end
-
- it "erases old trace" do
- subject
-
- expect(build.old_trace).to be_nil
- end
-
- it "executes UPDATE query" do
- recorded = ActiveRecord::QueryRecorder.new { subject }
-
- expect(recorded.log.count { |l| l.match?(/UPDATE.*ci_builds/) }).to eq(1)
- end
- end
-
- context 'when old trace does not exist' do
- it 'does not execute UPDATE query' do
- recorded = ActiveRecord::QueryRecorder.new { subject }
-
- expect(recorded.log.count { |l| l.match?(/UPDATE.*ci_builds/) }).to eq(0)
- end
- end
- end
-
describe '#hide_secrets' do
let(:metrics) { spy('metrics') }
let(:subject) { build.hide_secrets(data) }
diff --git a/spec/models/ci/processable_spec.rb b/spec/models/ci/processable_spec.rb
index 594f9b679ec..61e2864a518 100644
--- a/spec/models/ci/processable_spec.rb
+++ b/spec/models/ci/processable_spec.rb
@@ -55,8 +55,7 @@ RSpec.describe Ci::Processable do
let(:clone_accessors) { ::Ci::Build.clone_accessors.without(::Ci::Build.extra_accessors) }
let(:reject_accessors) do
- %i[id status user token_encrypted coverage trace runner
- artifacts_expire_at
+ %i[id status user token_encrypted coverage runner artifacts_expire_at
created_at updated_at started_at finished_at queued_at erased_by
erased_at auto_canceled_by job_artifacts job_artifacts_archive
job_artifacts_metadata job_artifacts_trace job_artifacts_junit
diff --git a/spec/requests/api/graphql/group/work_item_types_spec.rb b/spec/requests/api/graphql/group/work_item_types_spec.rb
index a33e3ae5427..d6b0673e4f8 100644
--- a/spec/requests/api/graphql/group/work_item_types_spec.rb
+++ b/spec/requests/api/graphql/group/work_item_types_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe 'getting a list of work item types for a group' do
end
end
- context "when user doesn't have acces to the group" do
+ context "when user doesn't have access to the group" do
let(:current_user) { create(:user) }
before do
diff --git a/spec/requests/api/personal_access_tokens/self_revocation_spec.rb b/spec/requests/api/personal_access_tokens/self_revocation_spec.rb
new file mode 100644
index 00000000000..f829b39cc1e
--- /dev/null
+++ b/spec/requests/api/personal_access_tokens/self_revocation_spec.rb
@@ -0,0 +1,69 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::PersonalAccessTokens::SelfRevocation do
+ let_it_be(:current_user) { create(:user) }
+
+ describe 'DELETE /personal_access_tokens/self' do
+ let(:path) { '/personal_access_tokens/self' }
+ let(:token) { create(:personal_access_token, user: current_user) }
+
+ subject(:delete_token) { delete api(path, personal_access_token: token) }
+
+ shared_examples 'revoking token succeeds' do
+ it 'revokes token' do
+ delete_token
+
+ expect(response).to have_gitlab_http_status(:no_content)
+ expect(token.reload).to be_revoked
+ end
+ end
+
+ shared_examples 'revoking token denied' do |status|
+ it 'cannot revoke token' do
+ delete_token
+
+ expect(response).to have_gitlab_http_status(status)
+ end
+ end
+
+ context 'when current_user is an administrator', :enable_admin_mode do
+ let(:current_user) { create(:admin) }
+
+ it_behaves_like 'revoking token succeeds'
+
+ context 'with impersonated token' do
+ let(:token) { create(:personal_access_token, :impersonation, user: current_user) }
+
+ it_behaves_like 'revoking token succeeds'
+ end
+ end
+
+ context 'when current_user is not an administrator' do
+ let(:current_user) { create(:user) }
+
+ it_behaves_like 'revoking token succeeds'
+
+ context 'with impersonated token' do
+ let(:token) { create(:personal_access_token, :impersonation, user: current_user) }
+
+ it_behaves_like 'revoking token denied', :bad_request
+ end
+
+ context 'with already revoked token' do
+ let(:token) { create(:personal_access_token, :revoked, user: current_user) }
+
+ it_behaves_like 'revoking token denied', :unauthorized
+ end
+ end
+
+ Gitlab::Auth.all_available_scopes.each do |scope|
+ context "with a '#{scope}' scoped token" do
+ let(:token) { create(:personal_access_token, scopes: [scope], user: current_user) }
+
+ it_behaves_like 'revoking token succeeds'
+ end
+ end
+ end
+end
diff --git a/spec/requests/api/personal_access_tokens_spec.rb b/spec/requests/api/personal_access_tokens_spec.rb
index 8d8998cfdd6..37b5a594f2a 100644
--- a/spec/requests/api/personal_access_tokens_spec.rb
+++ b/spec/requests/api/personal_access_tokens_spec.rb
@@ -75,6 +75,7 @@ RSpec.describe API::PersonalAccessTokens do
describe 'GET /personal_access_tokens/:id' do
let_it_be(:user_token) { create(:personal_access_token, user: current_user) }
+ let_it_be(:user_read_only_token) { create(:personal_access_token, scopes: ['read_repository'], user: current_user) }
let_it_be(:user_token_path) { "/personal_access_tokens/#{user_token.id}" }
let_it_be(:invalid_path) { "/personal_access_tokens/#{non_existing_record_id}" }
@@ -125,53 +126,11 @@ RSpec.describe API::PersonalAccessTokens do
expect(response).to have_gitlab_http_status(:unauthorized)
end
- end
- end
-
- describe 'DELETE /personal_access_tokens/self' do
- let(:path) { '/personal_access_tokens/self' }
- let(:token) { create(:personal_access_token, user: current_user) }
-
- subject { delete api(path, current_user, personal_access_token: token) }
-
- shared_examples 'revoking token succeeds' do
- it 'revokes token' do
- subject
-
- expect(response).to have_gitlab_http_status(:no_content)
- expect(token.reload).to be_revoked
- end
- end
- shared_examples 'revoking token denied' do |status|
- it 'cannot revoke token' do
- subject
+ it 'fails to return own PAT by id with read_repository token' do
+ get api(user_token_path, current_user, personal_access_token: user_read_only_token)
- expect(response).to have_gitlab_http_status(status)
- end
- end
-
- context 'when current_user is an administrator', :enable_admin_mode do
- let(:current_user) { create(:admin) }
-
- it_behaves_like 'revoking token succeeds'
- end
-
- context 'when current_user is not an administrator' do
- let(:current_user) { create(:user) }
-
- it_behaves_like 'revoking token succeeds'
-
- context 'with impersonated token' do
- let(:token) { create(:personal_access_token, :impersonation, user: current_user) }
-
- it_behaves_like 'revoking token denied', :bad_request
- end
-
- context 'with already revoked token' do
- let(:token) { create(:personal_access_token, :revoked, user: current_user) }
-
- it_behaves_like 'revoking token denied', :unauthorized
+ expect(response).to have_gitlab_http_status(:forbidden)
end
end
end
@@ -183,6 +142,9 @@ RSpec.describe API::PersonalAccessTokens do
let_it_be(:admin_user) { create(:admin) }
let_it_be(:admin_token) { create(:personal_access_token, user: admin_user) }
let_it_be(:admin_path) { "/personal_access_tokens/#{admin_token.id}" }
+ let_it_be(:admin_read_only_token) do
+ create(:personal_access_token, scopes: ['read_repository'], user: admin_user)
+ end
it 'revokes a different users token' do
delete api(path, admin_user)
@@ -196,6 +158,12 @@ RSpec.describe API::PersonalAccessTokens do
expect(response).to have_gitlab_http_status(:no_content)
end
+
+ it 'fails to revoke a different user token using a readonly scope' do
+ delete api(path, personal_access_token: admin_read_only_token)
+
+ expect(token1.reload.revoked?).to be false
+ end
end
context 'when current_user is not an administrator' do
diff --git a/spec/services/ci/resource_groups/assign_resource_from_resource_group_service_spec.rb b/spec/services/ci/resource_groups/assign_resource_from_resource_group_service_spec.rb
index 194203a422c..3d1abe290bc 100644
--- a/spec/services/ci/resource_groups/assign_resource_from_resource_group_service_spec.rb
+++ b/spec/services/ci/resource_groups/assign_resource_from_resource_group_service_spec.rb
@@ -3,6 +3,8 @@
require 'spec_helper'
RSpec.describe Ci::ResourceGroups::AssignResourceFromResourceGroupService do
+ include ConcurrentHelpers
+
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
@@ -134,6 +136,19 @@ RSpec.describe Ci::ResourceGroups::AssignResourceFromResourceGroupService do
end
end
end
+
+ context 'when parallel services are running' do
+ it 'can run the same command in parallel' do
+ parallel_num = 4
+
+ blocks = Array.new(parallel_num).map do
+ -> { subject }
+ end
+
+ run_parallel(blocks)
+ expect(build.reload).to be_pending
+ end
+ end
end
context 'when there are no available resources' do
diff --git a/spec/services/projects/destroy_service_spec.rb b/spec/services/projects/destroy_service_spec.rb
index 94320320407..8269dbebccb 100644
--- a/spec/services/projects/destroy_service_spec.rb
+++ b/spec/services/projects/destroy_service_spec.rb
@@ -135,6 +135,33 @@ RSpec.describe Projects::DestroyService, :aggregate_failures, :event_store_publi
end
end
+ context 'deleting a project with merge request diffs' do
+ let!(:merge_request) { create(:merge_request, source_project: project) }
+ let!(:another_project_mr) { create(:merge_request, source_project: create(:project)) }
+
+ it 'deletes merge request diffs' do
+ merge_request_diffs = merge_request.merge_request_diffs
+ expect(merge_request_diffs.size).to eq(1)
+
+ expect { destroy_project(project, user, {}) }.to change(MergeRequestDiff, :count).by(-1)
+ expect { another_project_mr.reload }.not_to raise_error
+ end
+
+ context 'when extract_mr_diff_deletions feature flag is disabled' do
+ before do
+ stub_feature_flags(extract_mr_diff_deletions: false)
+ end
+
+ it 'also deletes merge request diffs' do
+ merge_request_diffs = merge_request.merge_request_diffs
+ expect(merge_request_diffs.size).to eq(1)
+
+ expect { destroy_project(project, user, {}) }.to change(MergeRequestDiff, :count).by(-1)
+ expect { another_project_mr.reload }.not_to raise_error
+ end
+ end
+ end
+
it_behaves_like 'deleting the project'
it 'invalidates personal_project_count cache' do
diff --git a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
index c388a3a2c7f..10f58748698 100644
--- a/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
+++ b/spec/support/shared_examples/lib/gitlab/ci/ci_trace_shared_examples.rb
@@ -370,15 +370,6 @@ RSpec.shared_examples 'trace with disabled live trace feature' do
end
end
- shared_examples 'read successfully with StringIO' do
- it 'yields with source' do
- trace.read do |stream|
- expect(stream).to be_a(Gitlab::Ci::Trace::Stream)
- expect(stream.stream).to be_a(StringIO)
- end
- end
- end
-
shared_examples 'failed to read' do
it 'yields without source' do
trace.read do |stream|
@@ -404,14 +395,6 @@ RSpec.shared_examples 'trace with disabled live trace feature' do
it_behaves_like 'read successfully with IO'
end
- context 'when db trace exists' do
- before do
- build.send(:write_attribute, :trace, "data")
- end
-
- it_behaves_like 'read successfully with StringIO'
- end
-
context 'when no sources exist' do
it_behaves_like 'failed to read'
end
@@ -462,25 +445,6 @@ RSpec.shared_examples 'trace with disabled live trace feature' do
expect(trace.exist?).to be(false)
end
end
-
- context 'stored in database' do
- before do
- build.send(:write_attribute, :trace, "data")
- end
-
- it "trace exist" do
- expect(trace.exist?).to be(true)
- end
-
- it "can be erased" do
- trace.erase!
- expect(trace.exist?).to be(false)
- end
-
- it "returns database data" do
- expect(trace.raw).to eq("data")
- end
- end
end
describe '#archive!' do
@@ -520,24 +484,12 @@ RSpec.shared_examples 'trace with disabled live trace feature' do
expect(build.trace.exist?).to be_truthy
expect(build.job_artifacts_trace.file.exists?).to be_truthy
expect(build.job_artifacts_trace.file.filename).to eq('job.log')
- expect(build.old_trace).to be_nil
expect(src_checksum)
.to eq(described_class.sha256_hexdigest(build.job_artifacts_trace.file.path))
expect(build.job_artifacts_trace.file_sha256).to eq(src_checksum)
end
end
- shared_examples 'source trace in database stays intact' do |error:|
- it do
- expect { subject }.to raise_error(error)
-
- build.reload
- expect(build.trace.exist?).to be_truthy
- expect(build.job_artifacts_trace).to be_nil
- expect(build.old_trace).to eq(trace_content)
- end
- end
-
context 'when job does not have trace artifact' do
context 'when trace file stored in default path' do
let!(:build) { create(:ci_build, :success, :trace_live) }
@@ -564,58 +516,6 @@ RSpec.shared_examples 'trace with disabled live trace feature' do
it_behaves_like 'source trace file stays intact', error: ActiveRecord::RecordInvalid
end
end
-
- context 'when trace is stored in database' do
- let(:build) { create(:ci_build, :success) }
- let(:trace_content) { 'Sample trace' }
- let(:src_checksum) { Digest::SHA256.hexdigest(trace_content) }
-
- before do
- build.update_column(:trace, trace_content)
- end
-
- it_behaves_like 'archive trace in database'
-
- context 'when failed to create clone file' do
- before do
- allow(IO).to receive(:copy_stream).and_return(0)
- end
-
- it_behaves_like 'source trace in database stays intact', error: Gitlab::Ci::Trace::ArchiveError
- end
-
- context 'when failed to create job artifact record' do
- before do
- allow_any_instance_of(Ci::JobArtifact).to receive(:save).and_return(false)
- allow_any_instance_of(Ci::JobArtifact).to receive_message_chain(:errors, :full_messages)
- .and_return(%w[Error Error])
- end
-
- it_behaves_like 'source trace in database stays intact', error: ActiveRecord::RecordInvalid
- end
-
- context 'when there is a validation error on Ci::Build' do
- before do
- allow_any_instance_of(Ci::Build).to receive(:save).and_return(false)
- allow_any_instance_of(Ci::Build).to receive_message_chain(:errors, :full_messages)
- .and_return(%w[Error Error])
- end
-
- context "when erase old trace with 'save'" do
- before do
- build.send(:write_attribute, :trace, nil)
- build.save # rubocop:disable Rails/SaveBang
- end
-
- it 'old trace is not deleted' do
- build.reload
- expect(build.trace.raw).to eq(trace_content)
- end
- end
-
- it_behaves_like 'archive trace in database'
- end
- end
end
context 'when job has trace artifact' do
@@ -645,22 +545,6 @@ RSpec.shared_examples 'trace with disabled live trace feature' do
subject { trace.erase! }
context 'when it is a live trace' do
- context 'when trace is stored in database' do
- let(:build) { create(:ci_build) }
-
- before do
- build.update_column(:trace, 'sample trace')
- end
-
- it { expect(trace.raw).not_to be_nil }
-
- it "removes trace" do
- subject
-
- expect(trace.raw).to be_nil
- end
- end
-
context 'when trace is stored in file storage' do
let(:build) { create(:ci_build, :trace_live) }