Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
61666f277a
commit
b26eec8cbc
|
|
@ -1427,7 +1427,6 @@ lib/gitlab/checks/** @proglottis @toon @zj-gitlab
|
|||
/app/assets/javascripts/ci/pipeline_schedules/ @gitlab-org/ci-cd/verify/frontend
|
||||
/app/assets/javascripts/pipeline_editor/ @gitlab-org/ci-cd/verify/frontend
|
||||
/ee/app/assets/javascripts/ci/ @gitlab-org/ci-cd/verify/frontend
|
||||
/ee/app/assets/javascripts/reports/ @gitlab-org/ci-cd/verify/frontend
|
||||
/app/assets/javascripts/token_access/ @gitlab-org/ci-cd/verify/frontend
|
||||
/app/assets/javascripts/admin/application_settings/runner_token_expiration/ @gitlab-org/ci-cd/verify/frontend
|
||||
|
||||
|
|
|
|||
|
|
@ -878,23 +878,28 @@ fail-pipeline-early:
|
|||
script:
|
||||
- fail_pipeline_early
|
||||
|
||||
rspec rspec-pg12-rerun-previous-failed-tests:
|
||||
.base-rspec-pg12-rerun-previous-failed-tests:
|
||||
extends:
|
||||
- .rspec-base-pg12
|
||||
- .rails:rules:rerun-previous-failed-tests
|
||||
stage: test
|
||||
needs: ["setup-test-env", "compile-test-assets", "detect-previous-failed-tests"]
|
||||
script:
|
||||
- !reference [.base-script, script]
|
||||
- rspec_rerun_previous_failed_tests tmp/previous_failed_tests/rspec_failed_files.txt
|
||||
- rspec_rerun_previous_failed_tests "${PREVIOUS_FAILED_TESTS_FILE}"
|
||||
|
||||
rspec rspec-pg12-rerun-previous-failed-tests:
|
||||
extends:
|
||||
- .rspec-base-pg12
|
||||
- .base-rspec-pg12-rerun-previous-failed-tests
|
||||
variables:
|
||||
PREVIOUS_FAILED_TESTS_FILE: tmp/previous_failed_tests/rspec_failed_files.txt
|
||||
|
||||
rspec rspec-ee-pg12-rerun-previous-failed-tests:
|
||||
extends:
|
||||
- "rspec rspec-pg12-rerun-previous-failed-tests"
|
||||
- .rspec-ee-base-pg12
|
||||
script:
|
||||
- !reference [.base-script, script]
|
||||
- rspec_rerun_previous_failed_tests tmp/previous_failed_tests/rspec_ee_failed_files.txt
|
||||
- .base-rspec-pg12-rerun-previous-failed-tests
|
||||
variables:
|
||||
PREVIOUS_FAILED_TESTS_FILE: tmp/previous_failed_tests/rspec_ee_failed_files.txt
|
||||
|
||||
# EE: Canonical MR pipelines
|
||||
##################################################
|
||||
|
|
|
|||
|
|
@ -1,45 +0,0 @@
|
|||
---
|
||||
# Cop supports --autocorrect.
|
||||
Style/IfInsideElse:
|
||||
Exclude:
|
||||
- 'app/controllers/application_controller.rb'
|
||||
- 'app/controllers/passwords_controller.rb'
|
||||
- 'app/finders/projects_finder.rb'
|
||||
- 'app/helpers/diff_helper.rb'
|
||||
- 'app/helpers/issuables_helper.rb'
|
||||
- 'app/helpers/members_helper.rb'
|
||||
- 'app/helpers/search_helper.rb'
|
||||
- 'app/models/namespace.rb'
|
||||
- 'app/presenters/project_presenter.rb'
|
||||
- 'app/services/system_notes/commit_service.rb'
|
||||
- 'app/services/task_list_toggle_service.rb'
|
||||
- 'app/uploaders/gitlab_uploader.rb'
|
||||
- 'config/settings.rb'
|
||||
- 'ee/app/controllers/groups/omniauth_callbacks_controller.rb'
|
||||
- 'ee/app/models/iterations/cadence.rb'
|
||||
- 'ee/app/models/protected_environments/authorizable.rb'
|
||||
- 'ee/app/policies/ee/group_policy.rb'
|
||||
- 'ee/app/services/app_sec/dast/site_profiles/audit/update_service.rb'
|
||||
- 'ee/app/services/deployments/approval_service.rb'
|
||||
- 'ee/app/services/geo/framework_repository_sync_service.rb'
|
||||
- 'ee/app/services/geo/repository_base_sync_service.rb'
|
||||
- 'ee/app/services/gitlab_subscriptions/fetch_subscription_plans_service.rb'
|
||||
- 'ee/app/services/vulnerability_external_issue_links/create_service.rb'
|
||||
- 'ee/app/workers/elastic/project_transfer_worker.rb'
|
||||
- 'ee/lib/gitlab/geo/base_batcher.rb'
|
||||
- 'lib/api/projects.rb'
|
||||
- 'lib/gitlab/auth.rb'
|
||||
- 'lib/gitlab/conflict/file.rb'
|
||||
- 'lib/gitlab/sql/pattern.rb'
|
||||
- 'lib/gitlab/usage/service_ping/payload_keys_processor.rb'
|
||||
- 'lib/service_ping/build_payload.rb'
|
||||
- 'lib/tasks/gitlab/cleanup.rake'
|
||||
- 'lib/tasks/gitlab/shell.rake'
|
||||
- 'qa/qa/resource/protected_branch.rb'
|
||||
- 'qa/qa/specs/helpers/feature_flag.rb'
|
||||
- 'rubocop/cop/migration/add_limit_to_text_columns.rb'
|
||||
- 'scripts/review_apps/automated_cleanup.rb'
|
||||
- 'spec/controllers/projects/merge_requests/conflicts_controller_spec.rb'
|
||||
- 'spec/support/import_export/export_file_helper.rb'
|
||||
- 'spec/support/shared_examples/finders/snippet_visibility_shared_examples.rb'
|
||||
- 'spec/support/shared_examples/metrics/active_record_subscriber_shared_examples.rb'
|
||||
2
Gemfile
2
Gemfile
|
|
@ -166,7 +166,7 @@ gem 'seed-fu', '~> 2.3.7'
|
|||
gem 'elasticsearch-model', '~> 7.2'
|
||||
gem 'elasticsearch-rails', '~> 7.2', require: 'elasticsearch/rails/instrumentation'
|
||||
gem 'elasticsearch-api', '7.13.3'
|
||||
gem 'aws-sdk-core', '~> 3.168.1'
|
||||
gem 'aws-sdk-core', '~> 3.168.2'
|
||||
gem 'aws-sdk-cloudformation', '~> 1'
|
||||
gem 'aws-sdk-s3', '~> 1.117.1'
|
||||
gem 'faraday_middleware-aws-sigv4', '~>0.3.0'
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@
|
|||
{"name":"awesome_print","version":"1.9.2","platform":"ruby","checksum":"e99b32b704acff16d768b3468680793ced40bfdc4537eb07e06a4be11133786e"},
|
||||
{"name":"awrence","version":"1.1.1","platform":"ruby","checksum":"9be584c97408ed92d5e1ca11740853646fe270de675f2f8dd44e8233226dfc97"},
|
||||
{"name":"aws-eventstream","version":"1.2.0","platform":"ruby","checksum":"ffa53482c92880b001ff2fb06919b9bb82fd847cbb0fa244985d2ebb6dd0d1df"},
|
||||
{"name":"aws-partitions","version":"1.664.0","platform":"ruby","checksum":"cf7e9d07fb7d3517e4e349cf83d724fb7751caecc9b7a1abfd4e665be69ec9c0"},
|
||||
{"name":"aws-partitions","version":"1.667.0","platform":"ruby","checksum":"b02f7af0ba8a47dd667f8dbe48f547102b050e67ffc8060d94c0b951cd3992a5"},
|
||||
{"name":"aws-sdk-cloudformation","version":"1.41.0","platform":"ruby","checksum":"31e47539719734413671edf9b1a31f8673fbf9688549f50c41affabbcb1c6b26"},
|
||||
{"name":"aws-sdk-core","version":"3.168.1","platform":"ruby","checksum":"2b83c2cc0dde47293a9ff4f4ad1c4d49913c718d0daba8d1b357b5315fdad6ee"},
|
||||
{"name":"aws-sdk-core","version":"3.168.2","platform":"ruby","checksum":"21107826ea56a5a501eae8d2a52ee42020a1b86649a1505971a024bfc1e0b844"},
|
||||
{"name":"aws-sdk-kms","version":"1.59.0","platform":"ruby","checksum":"6c002ebf8e404625c8338ca12ae69b1329399f9dc1b0ebca474e00ff06700153"},
|
||||
{"name":"aws-sdk-s3","version":"1.117.1","platform":"ruby","checksum":"76f6dac5baeb2b78616eb34c6af650c1b7a15c1078b169d1b27e8421904c509d"},
|
||||
{"name":"aws-sigv4","version":"1.5.1","platform":"ruby","checksum":"d68c87fff4ee843b4b92b23c7f31f957f254ec6eb064181f7119124aab8b8bb4"},
|
||||
|
|
@ -295,7 +295,7 @@
|
|||
{"name":"jaro_winkler","version":"1.5.4","platform":"java","checksum":"0454333a50b44a09745878bfe57859893631ff7dfe48c029827894944514fe7c"},
|
||||
{"name":"jaro_winkler","version":"1.5.4","platform":"ruby","checksum":"50c3e83c5a9e8769c1cf5b73c8b51bb6eebbf8852a0ee53bf6ad6e4dc63414f9"},
|
||||
{"name":"jira-ruby","version":"2.1.4","platform":"ruby","checksum":"4267c095cac8323b9eef3ba866eb28bb1388b7623a5abb60c1e7caf12d4adb9e"},
|
||||
{"name":"jmespath","version":"1.6.1","platform":"ruby","checksum":"40ca83f4141bdd1e503db5485de68b84237183d84cf7a159fbeebcc6005adbd6"},
|
||||
{"name":"jmespath","version":"1.6.2","platform":"ruby","checksum":"238d774a58723d6c090494c8879b5e9918c19485f7e840f2c1c7532cf84ebcb1"},
|
||||
{"name":"js_regex","version":"3.8.0","platform":"ruby","checksum":"7934bcdd5a0e6d5af4a520288fd4684a02a472ae55831d9178ccaf82356344b5"},
|
||||
{"name":"json","version":"2.5.1","platform":"java","checksum":"be284a0c4a9d0373e81b0d5dfe71ed5b18d0479f05970e60a77be89a2978ce6c"},
|
||||
{"name":"json","version":"2.5.1","platform":"ruby","checksum":"918d8c41dacb7cfdbe0c7bbd6014a5372f0cf1c454ca150e9f4010fe80cc3153"},
|
||||
|
|
|
|||
|
|
@ -185,11 +185,11 @@ GEM
|
|||
awesome_print (1.9.2)
|
||||
awrence (1.1.1)
|
||||
aws-eventstream (1.2.0)
|
||||
aws-partitions (1.664.0)
|
||||
aws-partitions (1.667.0)
|
||||
aws-sdk-cloudformation (1.41.0)
|
||||
aws-sdk-core (~> 3, >= 3.99.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-core (3.168.1)
|
||||
aws-sdk-core (3.168.2)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
aws-partitions (~> 1, >= 1.651.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
|
|
@ -789,7 +789,7 @@ GEM
|
|||
atlassian-jwt
|
||||
multipart-post
|
||||
oauth (~> 0.5, >= 0.5.0)
|
||||
jmespath (1.6.1)
|
||||
jmespath (1.6.2)
|
||||
js_regex (3.8.0)
|
||||
character_set (~> 1.4)
|
||||
regexp_parser (~> 2.5)
|
||||
|
|
@ -1593,7 +1593,7 @@ DEPENDENCIES
|
|||
autoprefixer-rails (= 10.2.5.1)
|
||||
awesome_print
|
||||
aws-sdk-cloudformation (~> 1)
|
||||
aws-sdk-core (~> 3.168.1)
|
||||
aws-sdk-core (~> 3.168.2)
|
||||
aws-sdk-s3 (~> 1.117.1)
|
||||
babosa (~> 1.0.4)
|
||||
base32 (~> 0.3.0)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
*/
|
||||
import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
|
||||
import { s__ } from '~/locale';
|
||||
import ReportLink from '~/reports/components/report_link.vue';
|
||||
import { STATUS_SUCCESS, STATUS_NEUTRAL } from '~/reports/constants';
|
||||
import ReportLink from '~/ci/reports/components/report_link.vue';
|
||||
import { STATUS_SUCCESS, STATUS_NEUTRAL } from '~/ci/reports/constants';
|
||||
import { SEVERITY_CLASSES, SEVERITY_ICONS } from '../constants';
|
||||
|
||||
export default {
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { s__ } from '~/locale';
|
||||
import ReportItem from '~/reports/components/report_item.vue';
|
||||
import ReportItem from '~/ci/reports/components/report_item.vue';
|
||||
import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
|
||||
|
||||
export default {
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import IssueStatusIcon from '~/reports/components/issue_status_icon.vue';
|
||||
import IssueStatusIcon from '~/ci/reports/components/issue_status_icon.vue';
|
||||
|
||||
export const components = {
|
||||
CodequalityIssueBody: () => import('../codequality_report/components/codequality_issue_body.vue'),
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import ReportItem from '~/reports/components/report_item.vue';
|
||||
import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/reports/constants';
|
||||
import ReportItem from '~/ci/reports/components/report_item.vue';
|
||||
import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/ci/reports/constants';
|
||||
import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
|
||||
|
||||
const wrapIssueWithState = (status, isNew = false) => (issue) => ({
|
||||
|
|
@ -4,7 +4,7 @@ import {
|
|||
componentNames,
|
||||
iconComponents,
|
||||
iconComponentNames,
|
||||
} from 'ee_else_ce/reports/components/issue_body';
|
||||
} from 'ee_else_ce/ci/reports/components/issue_body';
|
||||
|
||||
export default {
|
||||
name: 'ReportItem',
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<script>
|
||||
import { GlButton, GlIcon } from '@gitlab/ui';
|
||||
import { SEVERITY_CLASSES, SEVERITY_ICONS } from '~/reports/codequality_report/constants';
|
||||
import { SEVERITY_CLASSES, SEVERITY_ICONS } from '~/ci/reports/codequality_report/constants';
|
||||
|
||||
export default {
|
||||
components: { GlButton, GlIcon },
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ export default {
|
|||
:disabled="disableSubmitButton"
|
||||
:phrase="confirmationPhrase"
|
||||
:button-text="confirmButtonText"
|
||||
button-qa-selector="transfer_group_button"
|
||||
@confirm="$emit('confirm')"
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { n__, s__, sprintf } from '~/locale';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { EXTENSION_ICONS } from '~/vue_merge_request_widget/constants';
|
||||
import { SEVERITY_ICONS_MR_WIDGET } from '~/reports/codequality_report/constants';
|
||||
import { parseCodeclimateMetrics } from '~/reports/codequality_report/store/utils/codequality_parser';
|
||||
import { SEVERITY_ICONS_MR_WIDGET } from '~/ci/reports/codequality_report/constants';
|
||||
import { parseCodeclimateMetrics } from '~/ci/reports/codequality_report/store/utils/codequality_parser';
|
||||
import { capitalizeFirstCharacter } from '~/lib/utils/text_utility';
|
||||
|
||||
export default {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
import { mapActions, mapGetters } from 'vuex';
|
||||
import { createAlert } from '~/flash';
|
||||
import { s__ } from '~/locale';
|
||||
import ReportSection from '~/reports/components/report_section.vue';
|
||||
import { ERROR, SLOT_SUCCESS, SLOT_LOADING, SLOT_ERROR } from '~/reports/constants';
|
||||
import ReportSection from '~/ci/reports/components/report_section.vue';
|
||||
import { ERROR, SLOT_SUCCESS, SLOT_LOADING, SLOT_ERROR } from '~/ci/reports/constants';
|
||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import HelpIcon from './components/help_icon.vue';
|
||||
import SecurityReportDownloadDropdown from './components/security_report_download_dropdown.vue';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { s__, sprintf } from '~/locale';
|
||||
import { LOADING, ERROR, SUCCESS } from '~/reports/constants';
|
||||
import { LOADING, ERROR, SUCCESS } from '~/ci/reports/constants';
|
||||
import { TRANSLATION_IS_LOADING } from './messages';
|
||||
import { countVulnerabilities, groupedTextBuilder } from './utils';
|
||||
|
||||
|
|
|
|||
|
|
@ -426,8 +426,8 @@ class ApplicationController < ActionController::Base
|
|||
# accepting the terms.
|
||||
redirect_path = if request.get?
|
||||
request.fullpath
|
||||
else
|
||||
URI(request.referer).path if request.referer
|
||||
elsif request.referer
|
||||
URI(request.referer).path
|
||||
end
|
||||
|
||||
flash[:notice] = message
|
||||
|
|
|
|||
|
|
@ -58,8 +58,8 @@ class PasswordsController < Devise::PasswordsController
|
|||
def check_password_authentication_available
|
||||
if resource
|
||||
return if resource.allow_password_authentication?
|
||||
else
|
||||
return if Gitlab::CurrentSettings.password_authentication_enabled?
|
||||
elsif Gitlab::CurrentSettings.password_authentication_enabled?
|
||||
return
|
||||
end
|
||||
|
||||
redirect_to after_sending_reset_password_instructions_path_for(resource_name),
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class PersonalAccessTokensFinder
|
|||
attr_reader :current_user
|
||||
|
||||
def by_current_user(tokens)
|
||||
return tokens if current_user.nil? || current_user.admin?
|
||||
return tokens if current_user.nil? || current_user.can_admin_all_resources?
|
||||
return PersonalAccessToken.none unless Ability.allowed?(current_user, :read_user_personal_access_tokens, params[:user])
|
||||
|
||||
tokens
|
||||
|
|
|
|||
|
|
@ -97,12 +97,10 @@ class ProjectsFinder < UnionFinder
|
|||
current_user.owned_projects
|
||||
elsif min_access_level?
|
||||
current_user.authorized_projects(params[:min_access_level])
|
||||
elsif private_only? || impossible_visibility_level?
|
||||
current_user.authorized_projects
|
||||
else
|
||||
if private_only? || impossible_visibility_level?
|
||||
current_user.authorized_projects
|
||||
else
|
||||
Project.public_or_visible_to_user(current_user)
|
||||
end
|
||||
Project.public_or_visible_to_user(current_user)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ module Resolvers
|
|||
authorize :read_work_item
|
||||
authorizes_object!
|
||||
|
||||
# this resolver may be calling gitaly as part of parsing notes that contain commit references
|
||||
calls_gitaly!
|
||||
|
||||
alias_method :notes_widget, :object
|
||||
|
||||
argument :filter, Types::WorkItems::NotesFilterTypeEnum,
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ module Types
|
|||
def id
|
||||
return super unless object.is_a?(SyntheticNote)
|
||||
|
||||
::Gitlab::GlobalId.build(object, model_name: object.class.to_s, id: "not-persisted")
|
||||
::Gitlab::GlobalId.build(object, model_name: object.class.to_s, id: object.discussion_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -76,13 +76,11 @@ module DiffHelper
|
|||
def diff_line_content(line)
|
||||
if line.blank?
|
||||
" ".html_safe
|
||||
else
|
||||
elsif line.start_with?('+', '-', ' ')
|
||||
# `sub` and substring-ing would destroy HTML-safeness of `line`
|
||||
if line.start_with?('+', '-', ' ')
|
||||
line[1, line.length]
|
||||
else
|
||||
line
|
||||
end
|
||||
line[1, line.length]
|
||||
else
|
||||
line
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -348,12 +348,10 @@ module IssuablesHelper
|
|||
else
|
||||
[_("Closed"), "merge-request-close"]
|
||||
end
|
||||
elsif issuable.open?
|
||||
[_("Open"), "issues"]
|
||||
else
|
||||
if issuable.open?
|
||||
[_("Open"), "issues"]
|
||||
else
|
||||
[_("Closed"), "issue-closed"]
|
||||
end
|
||||
[_("Closed"), "issue-closed"]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -14,19 +14,17 @@ module MembersHelper
|
|||
else
|
||||
"deny #{member.user.name}'s request to join"
|
||||
end
|
||||
elsif member.user
|
||||
"remove #{member.user.name} from"
|
||||
else
|
||||
if member.user
|
||||
"remove #{member.user.name} from"
|
||||
else
|
||||
e = RuntimeError.new("Data integrity error: no associated user for member ID #{member.id}")
|
||||
Gitlab::ErrorTracking.track_exception(e,
|
||||
member_id: member.id,
|
||||
invite_email: member.invite_email,
|
||||
invite_accepted_at: member.invite_accepted_at,
|
||||
source_id: member.source_id,
|
||||
source_type: member.source_type)
|
||||
"remove this orphaned member from"
|
||||
end
|
||||
e = RuntimeError.new("Data integrity error: no associated user for member ID #{member.id}")
|
||||
Gitlab::ErrorTracking.track_exception(e,
|
||||
member_id: member.id,
|
||||
invite_email: member.invite_email,
|
||||
invite_accepted_at: member.invite_accepted_at,
|
||||
source_id: member.source_id,
|
||||
source_type: member.source_type)
|
||||
"remove this orphaned member from"
|
||||
end
|
||||
|
||||
"#{text} #{action} the #{member.source.human_name} #{source_text(member)}?"
|
||||
|
|
|
|||
|
|
@ -565,12 +565,10 @@ module SearchHelper
|
|||
else
|
||||
:success
|
||||
end
|
||||
elsif issuable.closed?
|
||||
:info
|
||||
else
|
||||
if issuable.closed?
|
||||
:info
|
||||
else
|
||||
:success
|
||||
end
|
||||
:success
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -552,12 +552,10 @@ class Namespace < ApplicationRecord
|
|||
def shared_runners_setting
|
||||
if shared_runners_enabled
|
||||
SR_ENABLED
|
||||
elsif allow_descendants_override_disabled_shared_runners
|
||||
SR_DISABLED_WITH_OVERRIDE
|
||||
else
|
||||
if allow_descendants_override_disabled_shared_runners
|
||||
SR_DISABLED_WITH_OVERRIDE
|
||||
else
|
||||
SR_DISABLED_AND_UNOVERRIDABLE
|
||||
end
|
||||
SR_DISABLED_AND_UNOVERRIDABLE
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -290,16 +290,14 @@ class ProjectPresenter < Gitlab::View::Presenter::Delegated
|
|||
'btn-default',
|
||||
nil,
|
||||
'license')
|
||||
else
|
||||
if can_current_user_push_to_default_branch?
|
||||
AnchorData.new(false,
|
||||
elsif can_current_user_push_to_default_branch?
|
||||
AnchorData.new(false,
|
||||
content_tag(:span, statistic_icon + _('Add LICENSE'), class: 'add-license-link d-flex'),
|
||||
empty_repo? ? add_license_ide_path : add_license_path)
|
||||
else
|
||||
AnchorData.new(false,
|
||||
icon + content_tag(:span, _('No license. All rights reserved'), class: 'project-stat-value'),
|
||||
nil)
|
||||
end
|
||||
else
|
||||
AnchorData.new(false,
|
||||
icon + content_tag(:span, _('No license. All rights reserved'), class: 'project-stat-value'),
|
||||
nil)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -39,12 +39,9 @@ module Issuable
|
|||
|
||||
notes = prepare_notes_for_rendering(notes)
|
||||
|
||||
# TODO: optimize this permission check.
|
||||
# Given this loads notes on a single issuable and current permission system, we should not have to check
|
||||
# permission on every single note. We should be able to check permission on the given issuable or its container,
|
||||
# which should result in just one permission check. Perhaps that should also either be passed to NotesFinder or
|
||||
# should be done in NotesFinder, which would decide right away if it would need to return no notes
|
||||
# or if it should just filter out internal notes.
|
||||
# we need to check the permission on every note, because some system notes for instance can have references to
|
||||
# resources that some user do not have read access, so those notes are filtered out from the list of notes.
|
||||
# see Note#all_referenced_mentionables_allowed?
|
||||
notes = notes.select { |n| n.readable_by?(current_user) }
|
||||
|
||||
Discussion.build_collection(notes, issuable)
|
||||
|
|
|
|||
|
|
@ -81,12 +81,10 @@ module SystemNotes
|
|||
|
||||
commit_ids = if count == 1
|
||||
existing_commits.first.short_id
|
||||
elsif oldrev && !Gitlab::Git.blank_ref?(oldrev)
|
||||
"#{Commit.truncate_sha(oldrev)}...#{existing_commits.last.short_id}"
|
||||
else
|
||||
if oldrev && !Gitlab::Git.blank_ref?(oldrev)
|
||||
"#{Commit.truncate_sha(oldrev)}...#{existing_commits.last.short_id}"
|
||||
else
|
||||
"#{existing_commits.first.short_id}..#{existing_commits.last.short_id}"
|
||||
end
|
||||
"#{existing_commits.first.short_id}..#{existing_commits.last.short_id}"
|
||||
end
|
||||
|
||||
commits_text = "#{count} commit".pluralize(count)
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ class TaskListToggleService
|
|||
# any `[ ]` or `[x]` in the middle of the text
|
||||
if currently_checked
|
||||
markdown_task.sub!(Taskable::COMPLETE_PATTERN, '[ ]') unless toggle_as_checked
|
||||
else
|
||||
markdown_task.sub!(Taskable::INCOMPLETE_PATTERN, '[x]') if toggle_as_checked
|
||||
elsif toggle_as_checked
|
||||
markdown_task.sub!(Taskable::INCOMPLETE_PATTERN, '[x]')
|
||||
end
|
||||
|
||||
source_lines[source_line_index] = markdown_task
|
||||
|
|
|
|||
|
|
@ -101,8 +101,8 @@ class GitlabUploader < CarrierWave::Uploader::Base
|
|||
stream =
|
||||
if file_storage?
|
||||
File.open(path, "rb") if path
|
||||
else
|
||||
::Gitlab::HttpIO.new(url, cached_size) if url
|
||||
elsif url
|
||||
::Gitlab::HttpIO.new(url, cached_size)
|
||||
end
|
||||
|
||||
return unless stream
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
- form_id = "transfer-group-form"
|
||||
- initial_data = { button_text: s_('GroupSettings|Transfer group'), group_name: @group.name, group_id: @group.id, target_form_id: form_id, is_paid_group: group.paid?.to_s }
|
||||
|
||||
.sub-section
|
||||
.sub-section{ data: { qa_selector: 'transfer_group_content' } }
|
||||
%h4.warning-title= s_('GroupSettings|Transfer group')
|
||||
%p= _('Transfer group to another parent group.')
|
||||
= form_for group, url: transfer_group_path(group), method: :put, html: { id: form_id, class: 'js-group-transfer-form' } do |f|
|
||||
|
|
|
|||
|
|
@ -42,12 +42,10 @@ class Settings < Settingslogic
|
|||
|
||||
if gitlab_shell.ssh_port != 22
|
||||
"ssh://#{user_host}:#{gitlab_shell.ssh_port}/"
|
||||
elsif gitlab_shell.ssh_host.include? ':'
|
||||
"[#{user_host}]:"
|
||||
else
|
||||
if gitlab_shell.ssh_host.include? ':'
|
||||
"[#{user_host}]:"
|
||||
else
|
||||
"#{user_host}:"
|
||||
end
|
||||
"#{user_host}:"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
stage: Create
|
||||
group: Source Code
|
||||
group: Code Review
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ module API
|
|||
class Kubernetes < ::API::Base
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
|
||||
feature_category :kubernetes_management
|
||||
before do
|
||||
check_feature_enabled
|
||||
authenticate_gitlab_kas_request!
|
||||
|
|
@ -86,7 +85,7 @@ module API
|
|||
detail 'Retrieves agent info for the given token'
|
||||
end
|
||||
route_setting :authentication, cluster_agent_token_allowed: true
|
||||
get '/agent_info', urgency: :low do
|
||||
get '/agent_info', feature_category: :kubernetes_management, urgency: :low do
|
||||
project = agent.project
|
||||
|
||||
status 200
|
||||
|
|
@ -104,7 +103,7 @@ module API
|
|||
detail 'Retrieves project info (if authorized)'
|
||||
end
|
||||
route_setting :authentication, cluster_agent_token_allowed: true
|
||||
get '/project_info', urgency: :low do
|
||||
get '/project_info', feature_category: :kubernetes_management, urgency: :low do
|
||||
project = find_project(params[:id])
|
||||
|
||||
not_found! unless agent_has_access_to_project?(project)
|
||||
|
|
@ -127,7 +126,7 @@ module API
|
|||
requires :agent_id, type: Integer, desc: 'ID of the configured Agent'
|
||||
requires :agent_config, type: JSON, desc: 'Configuration for the Agent'
|
||||
end
|
||||
post '/' do
|
||||
post '/', feature_category: :kubernetes_management do
|
||||
agent = ::Clusters::Agent.find(params[:agent_id])
|
||||
|
||||
::Clusters::Agents::RefreshAuthorizationService.new(agent, config: params[:agent_config]).execute
|
||||
|
|
@ -150,7 +149,7 @@ module API
|
|||
optional :agent_users_using_ci_tunnel, type: Set[Integer], desc: 'A set of user ids that have interacted a CI Tunnel to'
|
||||
end
|
||||
end
|
||||
post '/' do
|
||||
post '/', feature_category: :kubernetes_management do
|
||||
increment_count_events
|
||||
increment_unique_events
|
||||
|
||||
|
|
|
|||
|
|
@ -559,8 +559,8 @@ module API
|
|||
|
||||
if result
|
||||
present_project user_project.reset, with: Entities::Project, current_user: current_user
|
||||
else
|
||||
render_api_error!("Project already forked", 409) if user_project.forked?
|
||||
elsif user_project.forked?
|
||||
render_api_error!("Project already forked", 409)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -135,15 +135,13 @@ module Gitlab
|
|||
# it is important to reset the ban counter once the client has proven
|
||||
# they are not a 'bad guy'.
|
||||
rate_limiter.reset!
|
||||
else
|
||||
elsif rate_limiter.register_fail!
|
||||
# Register a login failure so that Rack::Attack can block the next
|
||||
# request from this IP if needed.
|
||||
# This returns true when the failures are over the threshold and the IP
|
||||
# is banned.
|
||||
if rate_limiter.register_fail!
|
||||
Gitlab::AppLogger.info "IP #{rate_limiter.ip} failed to login " \
|
||||
Gitlab::AppLogger.info "IP #{rate_limiter.ip} failed to login " \
|
||||
"as #{login} but has been temporarily banned from Git auth"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -236,14 +236,12 @@ module Gitlab
|
|||
else
|
||||
:modified_target_removed_source
|
||||
end
|
||||
elsif our_path.present? && their_path.present?
|
||||
:both_added
|
||||
elsif their_path.blank?
|
||||
diff_file.renamed_file? ? :renamed_same_file : :removed_target_renamed_source
|
||||
else
|
||||
if our_path.present? && their_path.present?
|
||||
:both_added
|
||||
elsif their_path.blank?
|
||||
diff_file.renamed_file? ? :renamed_same_file : :removed_target_renamed_source
|
||||
else
|
||||
:removed_source_renamed_target
|
||||
end
|
||||
:removed_source_renamed_target
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -51,16 +51,14 @@ module Gitlab
|
|||
|
||||
if words.any?
|
||||
words.map { |word| arel_column.matches(to_pattern(word, use_minimum_char_limit: use_minimum_char_limit)) }.reduce(:and)
|
||||
else
|
||||
elsif lower_exact_match
|
||||
# No words of at least 3 chars, but we can search for an exact
|
||||
# case insensitive match with the query as a whole
|
||||
if lower_exact_match
|
||||
Arel::Nodes::NamedFunction
|
||||
Arel::Nodes::NamedFunction
|
||||
.new('LOWER', [arel_column])
|
||||
.eq(query)
|
||||
else
|
||||
arel_column.matches(sanitize_sql_like(query))
|
||||
end
|
||||
else
|
||||
arel_column.matches(sanitize_sql_like(query))
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ module Gitlab
|
|||
payload.map do |key, value|
|
||||
if has_metric_definition?(key, parents)
|
||||
parents.dup.append(key).join('.')
|
||||
else
|
||||
payload_keys(value, parents.dup << key) if value.is_a?(Hash)
|
||||
elsif value.is_a?(Hash)
|
||||
payload_keys(value, parents.dup << key)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ module ServicePing
|
|||
|
||||
if has_metric_definition?(key_path)
|
||||
include_metric?(key_path)
|
||||
else
|
||||
filtered_usage_data(node, parents.dup << label) if node.is_a?(Hash)
|
||||
elsif node.is_a?(Hash)
|
||||
filtered_usage_data(node, parents.dup << label)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -15,13 +15,11 @@ namespace :gitlab do
|
|||
|
||||
if Gitlab::Auth::Ldap::Access.allowed?(user)
|
||||
puts " [OK]".color(:green)
|
||||
elsif block_flag
|
||||
user.block! unless user.blocked?
|
||||
puts " [BLOCKED]".color(:red)
|
||||
else
|
||||
if block_flag
|
||||
user.block! unless user.blocked?
|
||||
puts " [BLOCKED]".color(:red)
|
||||
else
|
||||
puts " [NOT IN LDAP]".color(:yellow)
|
||||
end
|
||||
puts " [NOT IN LDAP]".color(:yellow)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -53,13 +53,11 @@ namespace :gitlab do
|
|||
path_to_repo = project.repository.path_to_repo
|
||||
if File.exist?(path_to_repo)
|
||||
print '-'
|
||||
else
|
||||
if Gitlab::Shell.new.create_repository(project.repository_storage,
|
||||
elsif Gitlab::Shell.new.create_repository(project.repository_storage,
|
||||
project.disk_path)
|
||||
print '.'
|
||||
else
|
||||
print 'F'
|
||||
end
|
||||
print '.'
|
||||
else
|
||||
print 'F'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
"@cubejs-client/core": "^0.31.0",
|
||||
"@gitlab/at.js": "1.5.7",
|
||||
"@gitlab/favicon-overlay": "2.0.0",
|
||||
"@gitlab/svgs": "3.12.0",
|
||||
"@gitlab/svgs": "3.13.0",
|
||||
"@gitlab/ui": "50.1.2",
|
||||
"@gitlab/visual-review-tools": "1.7.3",
|
||||
"@gitlab/web-ide": "0.0.1-dev-20221114183058",
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ gem 'fog-google', '~> 1.19', require: false
|
|||
gem 'fog-core', '2.1.0', require: false # fog-google generates a ton of warnings with latest core
|
||||
gem "warning", "~> 1.3"
|
||||
|
||||
gem 'confiner', '~> 0.3'
|
||||
gem 'confiner', '~> 0.4'
|
||||
|
||||
gem 'chemlab', '~> 0.10'
|
||||
gem 'chemlab-library-www-gitlab-com', '~> 0.1', '>= 0.1.1'
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ DEPENDENCIES
|
|||
capybara-screenshot (~> 1.0.26)
|
||||
chemlab (~> 0.10)
|
||||
chemlab-library-www-gitlab-com (~> 0.1, >= 0.1.1)
|
||||
confiner (~> 0.3)
|
||||
confiner (~> 0.4)
|
||||
deprecation_toolkit (~> 2.0.1)
|
||||
faker (~> 3.0)
|
||||
faraday-retry (~> 2.0)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,14 @@ module QA
|
|||
element :project_creation_level_dropdown
|
||||
end
|
||||
|
||||
view 'app/views/groups/settings/_transfer.html.haml' do
|
||||
element :transfer_group_content
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/groups/components/transfer_group_form.vue' do
|
||||
element :transfer_group_button
|
||||
end
|
||||
|
||||
def set_group_name(name)
|
||||
find_element(:group_name_field).send_keys([:command, 'a'], :backspace)
|
||||
find_element(:group_name_field).set name
|
||||
|
|
@ -102,6 +110,38 @@ module QA
|
|||
|
||||
click_element(:save_permissions_changes_button)
|
||||
end
|
||||
|
||||
def transfer_group(source_group, target_group)
|
||||
QA::Runtime::Logger.info "Transferring group: #{source_group.path} to target group: #{target_group.path}"
|
||||
|
||||
expand_content(:advanced_settings_content)
|
||||
|
||||
scroll_to_transfer_group_content
|
||||
|
||||
select_namespace(target_group.path)
|
||||
|
||||
wait_for_enabled_transfer_group_button
|
||||
click_element(:transfer_group_button)
|
||||
|
||||
fill_confirmation_text(source_group.path)
|
||||
confirm_transfer
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def scroll_to_transfer_group_content
|
||||
retry_until(sleep_interval: 1, message: 'Waiting for transfer group content to display') do
|
||||
has_element?(:transfer_group_content, wait: 3)
|
||||
end
|
||||
|
||||
scroll_to_element :transfer_group_content
|
||||
end
|
||||
|
||||
def wait_for_enabled_transfer_group_button
|
||||
retry_until(sleep_interval: 1, message: 'Waiting for transfer group button to be enabled') do
|
||||
has_element?(:transfer_group_button, disabled: false, wait: 3)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ module QA
|
|||
element :downstream_title_content
|
||||
end
|
||||
|
||||
view 'app/assets/javascripts/reports/components/report_section.vue' do
|
||||
view 'app/assets/javascripts/ci/reports/components/report_section.vue' do
|
||||
element :expand_report_button
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -51,8 +51,8 @@ module QA
|
|||
page.select_allowed_to_merge(allowed_to_merge)
|
||||
page.select_allowed_to_push(allowed_to_push)
|
||||
page.protect_branch
|
||||
else
|
||||
page.require_code_owner_approval(branch_name) if require_code_owner_approval
|
||||
elsif require_code_owner_approval
|
||||
page.require_code_owner_approval(branch_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module QA
|
||||
RSpec.describe 'Manage' do
|
||||
describe 'Subgroup transfer', product_group: :workspace do
|
||||
let(:source_group) do
|
||||
Resource::Group.fabricate_via_api! do |group|
|
||||
group.path = "source-group-for-transfer_#{SecureRandom.hex(8)}"
|
||||
end
|
||||
end
|
||||
|
||||
let!(:target_group) do
|
||||
Resource::Group.fabricate_via_api! do |group|
|
||||
group.path = "target-group-for-transfer_#{SecureRandom.hex(8)}"
|
||||
end
|
||||
end
|
||||
|
||||
let(:sub_group_for_transfer) do
|
||||
Resource::Group.fabricate_via_api! do |group|
|
||||
group.path = "subgroup-for-transfer_#{SecureRandom.hex(8)}"
|
||||
group.sandbox = source_group
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
Flow::Login.sign_in
|
||||
sub_group_for_transfer.visit!
|
||||
end
|
||||
|
||||
it 'transfers a subgroup to another group',
|
||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347692' do
|
||||
Page::Group::Menu.perform(&:click_group_general_settings_item)
|
||||
Page::Group::Settings::General.perform do |general|
|
||||
general.transfer_group(sub_group_for_transfer, target_group)
|
||||
|
||||
sub_group_for_transfer.sandbox = target_group
|
||||
sub_group_for_transfer.reload!
|
||||
end
|
||||
|
||||
expect(page).to have_text("Group '#{sub_group_for_transfer.path}' was successfully transferred.")
|
||||
expect(page.driver.current_url).to include(sub_group_for_transfer.full_path)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -20,11 +20,11 @@ module QA
|
|||
# This is to avoid flakiness with other tests running in parallel on the same environment
|
||||
# as well as interfering with feature flag experimentation done by development groups.
|
||||
example.metadata[:skip] = global_feature_flag_message if ContextSelector.dot_com?
|
||||
else
|
||||
elsif skip_env_for_scoped_feature_flag
|
||||
# Tests using a feature flag scoped to an actor (ex: :project, :user, :group), or
|
||||
# with no scope defined (such as in the case of a low risk global feature flag),
|
||||
# will only be skipped on environments without an admin account
|
||||
example.metadata[:skip] = feature_flag_message if skip_env_for_scoped_feature_flag
|
||||
example.metadata[:skip] = feature_flag_message
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -44,11 +44,9 @@ module RuboCop
|
|||
|
||||
if text_operation_with_limit?(send_node)
|
||||
add_offense(send_node.loc.selector, message: TEXT_LIMIT_ATTRIBUTE_NOT_ALLOWED) if version(node) < TEXT_LIMIT_ATTRIBUTE_ALLOWED_SINCE
|
||||
else
|
||||
elsif text_limit_missing?(node, *table_and_attribute_name(send_node))
|
||||
# We require a limit for the same table and attribute name
|
||||
if text_limit_missing?(node, *table_and_attribute_name(send_node))
|
||||
add_offense(send_node.loc.selector)
|
||||
end
|
||||
add_offense(send_node.loc.selector)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -91,13 +91,11 @@ module ReviewApps
|
|||
release = Tooling::Helm3Client::Release.new(environment.slug, 1, deployed_at.to_s, nil, nil, environment.slug)
|
||||
releases_to_delete << release
|
||||
end
|
||||
elsif deployed_at >= stop_threshold
|
||||
print_release_state(subject: 'Review App', release_name: environment.slug, release_date: last_deploy, action: 'leaving')
|
||||
else
|
||||
if deployed_at >= stop_threshold
|
||||
print_release_state(subject: 'Review App', release_name: environment.slug, release_date: last_deploy, action: 'leaving')
|
||||
else
|
||||
environment_state = fetch_environment(environment)&.state
|
||||
stop_environment(environment, deployment) if environment_state && environment_state != 'stopped'
|
||||
end
|
||||
environment_state = fetch_environment(environment)&.state
|
||||
stop_environment(environment, deployment) if environment_state && environment_state != 'stopped'
|
||||
end
|
||||
|
||||
checked_environments << environment.slug
|
||||
|
|
|
|||
|
|
@ -105,15 +105,13 @@ RSpec.describe Projects::MergeRequests::ConflictsController do
|
|||
if section['conflict']
|
||||
expect(line['type']).to be_in(%w(old new))
|
||||
expect(line.values_at('old_line', 'new_line')).to contain_exactly(nil, a_kind_of(Integer))
|
||||
elsif line['type'].nil?
|
||||
expect(line['old_line']).not_to eq(nil)
|
||||
expect(line['new_line']).not_to eq(nil)
|
||||
else
|
||||
if line['type'].nil?
|
||||
expect(line['old_line']).not_to eq(nil)
|
||||
expect(line['new_line']).not_to eq(nil)
|
||||
else
|
||||
expect(line['type']).to eq('match')
|
||||
expect(line['old_line']).to eq(nil)
|
||||
expect(line['new_line']).to eq(nil)
|
||||
end
|
||||
expect(line['type']).to eq('match')
|
||||
expect(line['old_line']).to eq(nil)
|
||||
expect(line['new_line']).to eq(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,359 +2,320 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe PersonalAccessTokensFinder do
|
||||
def finder(options = {}, current_user = nil)
|
||||
described_class.new(options, current_user)
|
||||
end
|
||||
RSpec.describe PersonalAccessTokensFinder, :enable_admin_mode do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
describe '# searches PATs' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
describe '#execute' do
|
||||
let(:admin) { create(:admin) }
|
||||
let(:user) { create(:user) }
|
||||
let(:other_user) { create(:user) }
|
||||
let(:project_bot) { create(:user, :project_bot) }
|
||||
|
||||
let_it_be(:time_token) do
|
||||
create(:personal_access_token, created_at: DateTime.new(2022, 01, 02),
|
||||
last_used_at: DateTime.new(2022, 01, 02))
|
||||
let!(:tokens) do
|
||||
{
|
||||
active: create(:personal_access_token, user: user, name: 'my_pat_1'),
|
||||
active_other: create(:personal_access_token, user: other_user, name: 'my_pat_2'),
|
||||
expired: create(:personal_access_token, :expired, user: user),
|
||||
revoked: create(:personal_access_token, :revoked, user: user),
|
||||
active_impersonation: create(:personal_access_token, :impersonation, user: user),
|
||||
expired_impersonation: create(:personal_access_token, :expired, :impersonation, user: user),
|
||||
revoked_impersonation: create(:personal_access_token, :revoked, :impersonation, user: user),
|
||||
bot: create(:personal_access_token, user: project_bot)
|
||||
}
|
||||
end
|
||||
|
||||
let_it_be(:name_token) { create(:personal_access_token, name: 'test_1') }
|
||||
let(:params) { {} }
|
||||
let(:current_user) { admin }
|
||||
|
||||
let_it_be(:impersonated_token) do
|
||||
create(:personal_access_token, :impersonation,
|
||||
created_at: DateTime.new(2022, 01, 02),
|
||||
last_used_at: DateTime.new(2022, 01, 02),
|
||||
name: 'imp_token'
|
||||
)
|
||||
end
|
||||
subject { described_class.new(params, current_user).execute }
|
||||
|
||||
shared_examples 'finding tokens by user and options' do
|
||||
subject { finder(option, user).execute }
|
||||
describe 'by current user' do
|
||||
context 'with no user' do
|
||||
let(:current_user) { nil }
|
||||
|
||||
it 'finds exactly' do
|
||||
subject
|
||||
it 'returns all tokens' do
|
||||
is_expected.to match_array(tokens.values)
|
||||
end
|
||||
end
|
||||
|
||||
is_expected.to contain_exactly(*result)
|
||||
context 'with admin' do
|
||||
let(:current_user) { admin }
|
||||
|
||||
context 'when admin mode setting is disabled', :do_not_mock_admin_mode_setting do
|
||||
it 'returns all tokens' do
|
||||
is_expected.to match_array(tokens.values)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when admin mode setting is enabled' do
|
||||
context 'when in admin mode', :enable_admin_mode do
|
||||
it 'returns all tokens' do
|
||||
is_expected.to match_array(tokens.values)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when not in admin mode' do
|
||||
before do
|
||||
allow_next_instance_of(Gitlab::Auth::CurrentUserMode) do |current_user_mode|
|
||||
allow(current_user_mode).to receive(:admin_mode?).and_return(false)
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns no tokens' do
|
||||
is_expected.to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user can read user personal access tokens' do
|
||||
let(:params) { { user: user } }
|
||||
let(:current_user) { user }
|
||||
|
||||
it 'returns tokens of user' do
|
||||
is_expected.to contain_exactly(*user.personal_access_tokens)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user can not read user personal access tokens' do
|
||||
let(:params) { { user: other_user } }
|
||||
let(:current_user) { user }
|
||||
|
||||
it 'returns no tokens' do
|
||||
is_expected.to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'by' do
|
||||
where(:option, :user, :result) do
|
||||
{ created_before: DateTime.new(2022, 01, 03) } | create(:admin) | lazy { [time_token, impersonated_token] }
|
||||
{ created_after: DateTime.new(2022, 01, 01) } | create(:admin) | lazy { [time_token, name_token, impersonated_token] }
|
||||
{ last_used_before: DateTime.new(2022, 01, 03) } | create(:admin) | lazy { [time_token, impersonated_token] }
|
||||
{ last_used_before: DateTime.new(2022, 01, 03) } | create(:admin) | lazy { [time_token, impersonated_token] }
|
||||
{ impersonation: true } | create(:admin) | lazy { [impersonated_token] }
|
||||
{ search: 'test' } | create(:admin) | lazy { [name_token] }
|
||||
describe 'by user' do
|
||||
where(:by_user, :expected_tokens) do
|
||||
nil | tokens.keys
|
||||
ref(:user) | [:active, :expired, :revoked, :active_impersonation, :expired_impersonation, :revoked_impersonation]
|
||||
ref(:other_user) | [:active_other]
|
||||
ref(:admin) | []
|
||||
end
|
||||
|
||||
with_them do
|
||||
it_behaves_like 'finding tokens by user and options'
|
||||
end
|
||||
end
|
||||
end
|
||||
let(:params) { { user: by_user } }
|
||||
|
||||
describe '#execute' do
|
||||
let(:user) { create(:user) }
|
||||
let(:params) { {} }
|
||||
let(:current_user) { nil }
|
||||
let!(:active_personal_access_token) { create(:personal_access_token, user: user) }
|
||||
let!(:expired_personal_access_token) { create(:personal_access_token, :expired, user: user) }
|
||||
let!(:revoked_personal_access_token) { create(:personal_access_token, :revoked, user: user) }
|
||||
let!(:active_impersonation_token) { create(:personal_access_token, :impersonation, user: user) }
|
||||
let!(:expired_impersonation_token) { create(:personal_access_token, :expired, :impersonation, user: user) }
|
||||
let!(:revoked_impersonation_token) { create(:personal_access_token, :revoked, :impersonation, user: user) }
|
||||
let!(:project_bot) { create(:user, :project_bot) }
|
||||
let!(:project_member) { create(:project_member, user: project_bot) }
|
||||
let!(:project_access_token) { create(:personal_access_token, user: project_bot) }
|
||||
|
||||
subject { finder(params, current_user).execute }
|
||||
|
||||
context 'when current_user is defined' do
|
||||
let(:current_user) { create(:admin) }
|
||||
let(:params) { { user: user } }
|
||||
|
||||
context 'current_user is allowed to read PATs' do
|
||||
it do
|
||||
is_expected.to contain_exactly(active_personal_access_token, active_impersonation_token,
|
||||
revoked_personal_access_token, expired_personal_access_token,
|
||||
revoked_impersonation_token, expired_impersonation_token)
|
||||
end
|
||||
end
|
||||
|
||||
context 'current_user is not allowed to read PATs' do
|
||||
let(:current_user) { create(:user) }
|
||||
|
||||
it { is_expected.to be_empty }
|
||||
end
|
||||
|
||||
context 'when user param is not set' do
|
||||
let(:params) { {} }
|
||||
|
||||
it do
|
||||
is_expected.to contain_exactly(active_personal_access_token, active_impersonation_token,
|
||||
revoked_personal_access_token, expired_personal_access_token,
|
||||
revoked_impersonation_token, expired_impersonation_token, project_access_token)
|
||||
end
|
||||
|
||||
context 'when current_user is not an administrator' do
|
||||
let(:current_user) { create(:user) }
|
||||
|
||||
it { is_expected.to be_empty }
|
||||
it 'returns tokens by user' do
|
||||
is_expected.to match_array(tokens.values_at(*expected_tokens))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'without user' do
|
||||
it do
|
||||
is_expected.to contain_exactly(active_personal_access_token, active_impersonation_token,
|
||||
revoked_personal_access_token, expired_personal_access_token,
|
||||
revoked_impersonation_token, expired_impersonation_token, project_access_token)
|
||||
describe 'by users' do
|
||||
where(:by_users, :expected_tokens) do
|
||||
nil | tokens.keys
|
||||
lazy { [user] } | [:active, :expired, :revoked, :active_impersonation, :expired_impersonation, :revoked_impersonation]
|
||||
lazy { [other_user] } | [:active_other]
|
||||
lazy { [user, other_user] } | [:active, :active_other, :expired, :revoked, :active_impersonation, :expired_impersonation, :revoked_impersonation]
|
||||
[] | [] # rubocop:disable Lint/BinaryOperatorWithIdenticalOperands
|
||||
end
|
||||
|
||||
describe 'with users' do
|
||||
let(:user2) { create(:user) }
|
||||
with_them do
|
||||
let(:params) { { users: by_users } }
|
||||
|
||||
before do
|
||||
create(:personal_access_token, user: user2)
|
||||
create(:personal_access_token, :expired, user: user2)
|
||||
create(:personal_access_token, :revoked, user: user2)
|
||||
create(:personal_access_token, :impersonation, user: user2)
|
||||
create(:personal_access_token, :expired, :impersonation, user: user2)
|
||||
create(:personal_access_token, :revoked, :impersonation, user: user2)
|
||||
|
||||
params[:users] = [user]
|
||||
end
|
||||
|
||||
it {
|
||||
is_expected.to contain_exactly(active_personal_access_token, active_impersonation_token,
|
||||
revoked_personal_access_token, expired_personal_access_token,
|
||||
revoked_impersonation_token, expired_impersonation_token)
|
||||
}
|
||||
end
|
||||
|
||||
describe 'with sort order' do
|
||||
before do
|
||||
params[:sort] = 'id_asc'
|
||||
end
|
||||
|
||||
it 'sorts records as per the specified sort order' do
|
||||
expect(subject).to match_array(PersonalAccessToken.all.order(id: :asc))
|
||||
end
|
||||
end
|
||||
|
||||
describe 'without impersonation' do
|
||||
before do
|
||||
params[:impersonation] = false
|
||||
end
|
||||
|
||||
it { is_expected.to contain_exactly(active_personal_access_token, revoked_personal_access_token, expired_personal_access_token, project_access_token) }
|
||||
|
||||
describe 'with active state' do
|
||||
before do
|
||||
params[:state] = 'active'
|
||||
end
|
||||
|
||||
it { is_expected.to contain_exactly(active_personal_access_token, project_access_token) }
|
||||
end
|
||||
|
||||
describe 'with inactive state' do
|
||||
before do
|
||||
params[:state] = 'inactive'
|
||||
end
|
||||
|
||||
it { is_expected.to contain_exactly(revoked_personal_access_token, expired_personal_access_token) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with impersonation' do
|
||||
before do
|
||||
params[:impersonation] = true
|
||||
end
|
||||
|
||||
it { is_expected.to contain_exactly(active_impersonation_token, revoked_impersonation_token, expired_impersonation_token) }
|
||||
|
||||
describe 'with active state' do
|
||||
before do
|
||||
params[:state] = 'active'
|
||||
end
|
||||
|
||||
it { is_expected.to contain_exactly(active_impersonation_token) }
|
||||
end
|
||||
|
||||
describe 'with inactive state' do
|
||||
before do
|
||||
params[:state] = 'inactive'
|
||||
end
|
||||
|
||||
it { is_expected.to contain_exactly(revoked_impersonation_token, expired_impersonation_token) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with active state' do
|
||||
before do
|
||||
params[:state] = 'active'
|
||||
end
|
||||
|
||||
it { is_expected.to contain_exactly(active_personal_access_token, active_impersonation_token, project_access_token) }
|
||||
end
|
||||
|
||||
describe 'with inactive state' do
|
||||
before do
|
||||
params[:state] = 'inactive'
|
||||
end
|
||||
|
||||
it do
|
||||
is_expected.to contain_exactly(expired_personal_access_token, revoked_personal_access_token,
|
||||
expired_impersonation_token, revoked_impersonation_token)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with id' do
|
||||
subject { finder(params).find_by_id(active_personal_access_token.id) }
|
||||
|
||||
it { is_expected.to eq(active_personal_access_token) }
|
||||
|
||||
describe 'with impersonation' do
|
||||
before do
|
||||
params[:impersonation] = true
|
||||
end
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with token' do
|
||||
subject { finder(params).find_by_token(active_personal_access_token.token) }
|
||||
|
||||
it { is_expected.to eq(active_personal_access_token) }
|
||||
|
||||
describe 'with impersonation' do
|
||||
before do
|
||||
params[:impersonation] = true
|
||||
end
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
it 'returns tokens by users' do
|
||||
is_expected.to match_array(tokens.values_at(*expected_tokens))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with user' do
|
||||
let(:user2) { create(:user) }
|
||||
let!(:other_user_active_personal_access_token) { create(:personal_access_token, user: user2) }
|
||||
let!(:other_user_expired_personal_access_token) { create(:personal_access_token, :expired, user: user2) }
|
||||
let!(:other_user_revoked_personal_access_token) { create(:personal_access_token, :revoked, user: user2) }
|
||||
let!(:other_user_active_impersonation_token) { create(:personal_access_token, :impersonation, user: user2) }
|
||||
let!(:other_user_expired_impersonation_token) { create(:personal_access_token, :expired, :impersonation, user: user2) }
|
||||
let!(:other_user_revoked_impersonation_token) { create(:personal_access_token, :revoked, :impersonation, user: user2) }
|
||||
describe 'by impersonation' do
|
||||
where(:by_impersonation, :expected_tokens) do
|
||||
nil | tokens.keys
|
||||
true | [:active_impersonation, :expired_impersonation, :revoked_impersonation]
|
||||
false | [:active, :active_other, :expired, :revoked, :bot]
|
||||
'other' | tokens.keys
|
||||
end
|
||||
|
||||
with_them do
|
||||
let(:params) { { impersonation: by_impersonation } }
|
||||
|
||||
it 'returns tokens by impersonation' do
|
||||
is_expected.to match_array(tokens.values_at(*expected_tokens))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'by state' do
|
||||
where(:by_state, :expected_tokens) do
|
||||
nil | tokens.keys
|
||||
'active' | [:active, :active_other, :active_impersonation, :bot]
|
||||
'inactive' | [:expired, :revoked, :expired_impersonation, :revoked_impersonation]
|
||||
'other' | tokens.keys
|
||||
end
|
||||
|
||||
with_them do
|
||||
let(:params) { { state: by_state } }
|
||||
|
||||
it 'returns tokens by state' do
|
||||
is_expected.to match_array(tokens.values_at(*expected_tokens))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'by owner type' do
|
||||
where(:by_owner_type, :expected_tokens) do
|
||||
nil | tokens.keys
|
||||
'human' | [:active, :active_other, :expired, :revoked, :active_impersonation, :expired_impersonation, :revoked_impersonation]
|
||||
'other' | tokens.keys
|
||||
end
|
||||
|
||||
with_them do
|
||||
let(:params) { { owner_type: by_owner_type } }
|
||||
|
||||
it 'returns tokens by owner type' do
|
||||
is_expected.to match_array(tokens.values_at(*expected_tokens))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'by revoked state' do
|
||||
where(:by_revoked_state, :expected_tokens) do
|
||||
nil | [:active, :active_other, :expired, :active_impersonation, :expired_impersonation, :bot]
|
||||
true | [:revoked, :revoked_impersonation]
|
||||
false | [:active, :active_other, :expired, :active_impersonation, :expired_impersonation, :bot]
|
||||
end
|
||||
|
||||
with_them do
|
||||
let(:params) { { revoked: by_revoked_state } }
|
||||
|
||||
it 'returns tokens by revoked state' do
|
||||
is_expected.to match_array(tokens.values_at(*expected_tokens))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'by created date' do
|
||||
before do
|
||||
params[:user] = user
|
||||
tokens[:active_other].update!(created_at: 5.days.ago)
|
||||
end
|
||||
|
||||
it do
|
||||
is_expected.to contain_exactly(active_personal_access_token, active_impersonation_token,
|
||||
revoked_personal_access_token, expired_personal_access_token,
|
||||
revoked_impersonation_token, expired_impersonation_token)
|
||||
end
|
||||
|
||||
describe 'filtering human tokens' do
|
||||
before do
|
||||
params[:owner_type] = 'human'
|
||||
describe 'by created before' do
|
||||
where(:by_created_before, :expected_tokens) do
|
||||
6.days.ago | []
|
||||
2.days.ago | [:active_other]
|
||||
2.days.from_now | tokens.keys
|
||||
end
|
||||
|
||||
it { is_expected.not_to include(project_access_token) }
|
||||
end
|
||||
with_them do
|
||||
let(:params) { { created_before: by_created_before } }
|
||||
|
||||
describe 'without impersonation' do
|
||||
before do
|
||||
params[:impersonation] = false
|
||||
end
|
||||
|
||||
it { is_expected.to contain_exactly(active_personal_access_token, revoked_personal_access_token, expired_personal_access_token) }
|
||||
|
||||
describe 'with active state' do
|
||||
before do
|
||||
params[:state] = 'active'
|
||||
it 'returns tokens by created before' do
|
||||
is_expected.to match_array(tokens.values_at(*expected_tokens))
|
||||
end
|
||||
|
||||
it { is_expected.to contain_exactly(active_personal_access_token) }
|
||||
end
|
||||
|
||||
describe 'with inactive state' do
|
||||
before do
|
||||
params[:state] = 'inactive'
|
||||
end
|
||||
|
||||
it { is_expected.to contain_exactly(revoked_personal_access_token, expired_personal_access_token) }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with impersonation' do
|
||||
before do
|
||||
params[:impersonation] = true
|
||||
describe 'by created after' do
|
||||
where(:by_created_after, :expected_tokens) do
|
||||
6.days.ago | tokens.keys
|
||||
2.days.ago | [:active, :expired, :revoked, :active_impersonation, :expired_impersonation, :revoked_impersonation, :bot]
|
||||
2.days.from_now | []
|
||||
end
|
||||
|
||||
it { is_expected.to contain_exactly(active_impersonation_token, revoked_impersonation_token, expired_impersonation_token) }
|
||||
with_them do
|
||||
let(:params) { { created_after: by_created_after } }
|
||||
|
||||
describe 'with active state' do
|
||||
before do
|
||||
params[:state] = 'active'
|
||||
it 'returns tokens by created before' do
|
||||
is_expected.to match_array(tokens.values_at(*expected_tokens))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it { is_expected.to contain_exactly(active_impersonation_token) }
|
||||
describe 'by last used date' do
|
||||
before do
|
||||
PersonalAccessToken.update_all(last_used_at: Time.now)
|
||||
tokens[:active_other].update!(last_used_at: 5.days.ago)
|
||||
end
|
||||
|
||||
describe 'by last used before' do
|
||||
where(:by_last_used_before, :expected_tokens) do
|
||||
6.days.ago | []
|
||||
2.days.ago | [:active_other]
|
||||
2.days.from_now | tokens.keys
|
||||
end
|
||||
|
||||
describe 'with inactive state' do
|
||||
before do
|
||||
params[:state] = 'inactive'
|
||||
end
|
||||
with_them do
|
||||
let(:params) { { last_used_before: by_last_used_before } }
|
||||
|
||||
it { is_expected.to contain_exactly(revoked_impersonation_token, expired_impersonation_token) }
|
||||
it 'returns tokens by last used before' do
|
||||
is_expected.to match_array(tokens.values_at(*expected_tokens))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with active state' do
|
||||
before do
|
||||
params[:state] = 'active'
|
||||
describe 'by last used after' do
|
||||
where(:by_last_used_after, :expected_tokens) do
|
||||
6.days.ago | tokens.keys
|
||||
2.days.ago | [:active, :expired, :revoked, :active_impersonation, :expired_impersonation, :revoked_impersonation, :bot]
|
||||
2.days.from_now | []
|
||||
end
|
||||
|
||||
it { is_expected.to contain_exactly(active_personal_access_token, active_impersonation_token) }
|
||||
end
|
||||
with_them do
|
||||
let(:params) { { last_used_after: by_last_used_after } }
|
||||
|
||||
describe 'with inactive state' do
|
||||
before do
|
||||
params[:state] = 'inactive'
|
||||
end
|
||||
|
||||
it do
|
||||
is_expected.to contain_exactly(expired_personal_access_token, revoked_personal_access_token,
|
||||
expired_impersonation_token, revoked_impersonation_token)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with id' do
|
||||
subject { finder(params).find_by_id(active_personal_access_token.id) }
|
||||
|
||||
it { is_expected.to eq(active_personal_access_token) }
|
||||
|
||||
describe 'with impersonation' do
|
||||
before do
|
||||
params[:impersonation] = true
|
||||
it 'returns tokens by last used after' do
|
||||
is_expected.to match_array(tokens.values_at(*expected_tokens))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
describe 'by search' do
|
||||
where(:by_search, :expected_tokens) do
|
||||
nil | tokens.keys
|
||||
'my_pat' | [:active, :active_other]
|
||||
'other' | []
|
||||
end
|
||||
|
||||
with_them do
|
||||
let(:params) { { search: by_search } }
|
||||
|
||||
it 'returns tokens by search' do
|
||||
is_expected.to match_array(tokens.values_at(*expected_tokens))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'sort' do
|
||||
where(:sort, :expected_tokens) do
|
||||
nil | tokens.keys
|
||||
'id_asc' | [:active, :active_other, :expired, :revoked, :active_impersonation, :expired_impersonation, :revoked_impersonation, :bot]
|
||||
'id_desc' | [:bot, :revoked_impersonation, :expired_impersonation, :active_impersonation, :revoked, :expired, :active_other, :active]
|
||||
'other' | tokens.keys
|
||||
end
|
||||
|
||||
with_them do
|
||||
let(:params) { { sort: sort } }
|
||||
|
||||
it 'returns ordered tokens' do
|
||||
expect(subject.map(&:id)).to eq(tokens.values_at(*expected_tokens).map(&:id))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'delegates' do
|
||||
subject { described_class.new(params, current_user) }
|
||||
|
||||
describe '#find_by_id' do
|
||||
it 'returns token by id' do
|
||||
expect(subject.find_by_id(tokens[:active].id)).to eq(tokens[:active])
|
||||
end
|
||||
end
|
||||
|
||||
describe 'with token' do
|
||||
subject { finder(params).find_by_token(active_personal_access_token.token) }
|
||||
describe '#find_by_token' do
|
||||
it 'returns token by token' do
|
||||
expect(subject.find_by_token(tokens[:active].token)).to eq(tokens[:active])
|
||||
end
|
||||
end
|
||||
|
||||
it { is_expected.to eq(active_personal_access_token) }
|
||||
|
||||
describe 'with impersonation' do
|
||||
before do
|
||||
params[:impersonation] = true
|
||||
end
|
||||
|
||||
it { is_expected.to be_nil }
|
||||
describe '#find' do
|
||||
it 'returns token by id' do
|
||||
expect(subject.find(tokens[:active].id)).to eq(tokens[:active])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { GlIcon } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||
import component from '~/reports/codequality_report/components/codequality_issue_body.vue';
|
||||
import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/reports/constants';
|
||||
import component from '~/ci/reports/codequality_report/components/codequality_issue_body.vue';
|
||||
import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/ci/reports/constants';
|
||||
|
||||
describe('code quality issue body issue body', () => {
|
||||
let wrapper;
|
||||
|
|
@ -2,10 +2,10 @@ import MockAdapter from 'axios-mock-adapter';
|
|||
import testAction from 'helpers/vuex_action_helper';
|
||||
import { TEST_HOST } from 'spec/test_constants';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import createStore from '~/reports/codequality_report/store';
|
||||
import * as actions from '~/reports/codequality_report/store/actions';
|
||||
import * as types from '~/reports/codequality_report/store/mutation_types';
|
||||
import { STATUS_NOT_FOUND } from '~/reports/constants';
|
||||
import createStore from '~/ci/reports/codequality_report/store';
|
||||
import * as actions from '~/ci/reports/codequality_report/store/actions';
|
||||
import * as types from '~/ci/reports/codequality_report/store/mutation_types';
|
||||
import { STATUS_NOT_FOUND } from '~/ci/reports/constants';
|
||||
import { reportIssues, parsedReportIssues } from '../mock_data';
|
||||
|
||||
const pollInterval = 123;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import createStore from '~/reports/codequality_report/store';
|
||||
import * as getters from '~/reports/codequality_report/store/getters';
|
||||
import { LOADING, ERROR, SUCCESS, STATUS_NOT_FOUND } from '~/reports/constants';
|
||||
import createStore from '~/ci/reports/codequality_report/store';
|
||||
import * as getters from '~/ci/reports/codequality_report/store/getters';
|
||||
import { LOADING, ERROR, SUCCESS, STATUS_NOT_FOUND } from '~/ci/reports/constants';
|
||||
|
||||
describe('Codequality reports store getters', () => {
|
||||
let localState;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import createStore from '~/reports/codequality_report/store';
|
||||
import mutations from '~/reports/codequality_report/store/mutations';
|
||||
import { STATUS_NOT_FOUND } from '~/reports/constants';
|
||||
import createStore from '~/ci/reports/codequality_report/store';
|
||||
import mutations from '~/ci/reports/codequality_report/store/mutations';
|
||||
import { STATUS_NOT_FOUND } from '~/ci/reports/constants';
|
||||
|
||||
describe('Codequality Reports mutations', () => {
|
||||
let localState;
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import { reportIssues, parsedReportIssues } from 'jest/reports/codequality_report/mock_data';
|
||||
import { parseCodeclimateMetrics } from '~/reports/codequality_report/store/utils/codequality_parser';
|
||||
import { reportIssues, parsedReportIssues } from 'jest/ci/reports/codequality_report/mock_data';
|
||||
import { parseCodeclimateMetrics } from '~/ci/reports/codequality_report/store/utils/codequality_parser';
|
||||
|
||||
describe('Codequality report store utils', () => {
|
||||
let result;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import GroupedIssuesList from '~/reports/components/grouped_issues_list.vue';
|
||||
import ReportItem from '~/reports/components/report_item.vue';
|
||||
import GroupedIssuesList from '~/ci/reports/components/grouped_issues_list.vue';
|
||||
import ReportItem from '~/ci/reports/components/report_item.vue';
|
||||
import SmartVirtualList from '~/vue_shared/components/smart_virtual_list.vue';
|
||||
|
||||
describe('Grouped Issues List', () => {
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import ReportItem from '~/reports/components/issue_status_icon.vue';
|
||||
import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/reports/constants';
|
||||
import ReportItem from '~/ci/reports/components/issue_status_icon.vue';
|
||||
import { STATUS_FAILED, STATUS_NEUTRAL, STATUS_SUCCESS } from '~/ci/reports/constants';
|
||||
|
||||
describe('IssueStatusIcon', () => {
|
||||
let wrapper;
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { componentNames } from '~/reports/components/issue_body';
|
||||
import IssueStatusIcon from '~/reports/components/issue_status_icon.vue';
|
||||
import ReportItem from '~/reports/components/report_item.vue';
|
||||
import { STATUS_SUCCESS } from '~/reports/constants';
|
||||
import { componentNames } from '~/ci/reports/components/issue_body';
|
||||
import IssueStatusIcon from '~/ci/reports/components/issue_status_icon.vue';
|
||||
import ReportItem from '~/ci/reports/components/report_item.vue';
|
||||
import { STATUS_SUCCESS } from '~/ci/reports/constants';
|
||||
|
||||
describe('ReportItem', () => {
|
||||
describe('showReportSectionStatusIcon', () => {
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import ReportLink from '~/reports/components/report_link.vue';
|
||||
import ReportLink from '~/ci/reports/components/report_link.vue';
|
||||
|
||||
describe('app/assets/javascripts/reports/components/report_link.vue', () => {
|
||||
describe('app/assets/javascripts/ci/reports/components/report_link.vue', () => {
|
||||
let wrapper;
|
||||
|
||||
afterEach(() => {
|
||||
|
|
@ -1,8 +1,8 @@
|
|||
import { GlButton } from '@gitlab/ui';
|
||||
import { mountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import HelpPopover from '~/vue_shared/components/help_popover.vue';
|
||||
import ReportItem from '~/reports/components/report_item.vue';
|
||||
import ReportSection from '~/reports/components/report_section.vue';
|
||||
import ReportItem from '~/ci/reports/components/report_item.vue';
|
||||
import ReportSection from '~/ci/reports/components/report_section.vue';
|
||||
|
||||
describe('ReportSection component', () => {
|
||||
let wrapper;
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { mount } from '@vue/test-utils';
|
||||
import { extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||
import HelpPopover from '~/vue_shared/components/help_popover.vue';
|
||||
import SummaryRow from '~/reports/components/summary_row.vue';
|
||||
import SummaryRow from '~/ci/reports/components/summary_row.vue';
|
||||
|
||||
describe('Summary row', () => {
|
||||
let wrapper;
|
||||
|
|
@ -1,11 +1,21 @@
|
|||
{
|
||||
"status": "failed",
|
||||
"summary": { "total": 11, "resolved": 2, "errored": 0, "failed": 2 },
|
||||
"summary": {
|
||||
"total": 11,
|
||||
"resolved": 2,
|
||||
"errored": 0,
|
||||
"failed": 2
|
||||
},
|
||||
"suites": [
|
||||
{
|
||||
"name": "rspec:pg",
|
||||
"status": "failed",
|
||||
"summary": { "total": 8, "resolved": 2, "errored": 0, "failed": 1 },
|
||||
"summary": {
|
||||
"total": 8,
|
||||
"resolved": 2,
|
||||
"errored": 0,
|
||||
"failed": 1
|
||||
},
|
||||
"new_failures": [
|
||||
{
|
||||
"status": "failed",
|
||||
|
|
@ -36,7 +46,12 @@
|
|||
{
|
||||
"name": "java ant",
|
||||
"status": "failed",
|
||||
"summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 1 },
|
||||
"summary": {
|
||||
"total": 3,
|
||||
"resolved": 0,
|
||||
"errored": 0,
|
||||
"failed": 1
|
||||
},
|
||||
"new_failures": [],
|
||||
"resolved_failures": [],
|
||||
"existing_failures": [
|
||||
|
|
@ -52,4 +67,4 @@
|
|||
"existing_errors": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,19 @@
|
|||
{
|
||||
"summary": { "total": 11, "resolved": 0, "errored": 2, "failed": 0 },
|
||||
"summary": {
|
||||
"total": 11,
|
||||
"resolved": 0,
|
||||
"errored": 2,
|
||||
"failed": 0
|
||||
},
|
||||
"suites": [
|
||||
{
|
||||
"name": "karma",
|
||||
"summary": { "total": 3, "resolved": 0, "errored": 2, "failed": 0 },
|
||||
"summary": {
|
||||
"total": 3,
|
||||
"resolved": 0,
|
||||
"errored": 2,
|
||||
"failed": 0
|
||||
},
|
||||
"new_failures": [],
|
||||
"resolved_failures": [],
|
||||
"existing_failures": [],
|
||||
|
|
@ -26,7 +36,12 @@
|
|||
},
|
||||
{
|
||||
"name": "rspec:pg",
|
||||
"summary": { "total": 8, "resolved": 0, "errored": 0, "failed": 0 },
|
||||
"summary": {
|
||||
"total": 8,
|
||||
"resolved": 0,
|
||||
"errored": 0,
|
||||
"failed": 0
|
||||
},
|
||||
"new_failures": [],
|
||||
"resolved_failures": [],
|
||||
"existing_failures": [],
|
||||
|
|
@ -35,4 +50,4 @@
|
|||
"existing_errors": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,19 @@
|
|||
{
|
||||
"summary": { "total": 11, "resolved": 0, "errored": 0, "failed": 2 },
|
||||
"summary": {
|
||||
"total": 11,
|
||||
"resolved": 0,
|
||||
"errored": 0,
|
||||
"failed": 2
|
||||
},
|
||||
"suites": [
|
||||
{
|
||||
"name": "rspec:pg",
|
||||
"summary": { "total": 8, "resolved": 0, "errored": 0, "failed": 2 },
|
||||
"summary": {
|
||||
"total": 8,
|
||||
"resolved": 0,
|
||||
"errored": 0,
|
||||
"failed": 2
|
||||
},
|
||||
"new_failures": [
|
||||
{
|
||||
"result": "failure",
|
||||
|
|
@ -28,7 +38,12 @@
|
|||
},
|
||||
{
|
||||
"name": "java ant",
|
||||
"summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 0 },
|
||||
"summary": {
|
||||
"total": 3,
|
||||
"resolved": 0,
|
||||
"errored": 0,
|
||||
"failed": 0
|
||||
},
|
||||
"new_failures": [],
|
||||
"resolved_failures": [],
|
||||
"existing_failures": [],
|
||||
|
|
@ -37,4 +52,4 @@
|
|||
"existing_errors": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,19 @@
|
|||
{
|
||||
"summary": { "total": 11, "resolved": 0, "errored": 0, "failed": 2 },
|
||||
"summary": {
|
||||
"total": 11,
|
||||
"resolved": 0,
|
||||
"errored": 0,
|
||||
"failed": 2
|
||||
},
|
||||
"suites": [
|
||||
{
|
||||
"name": "rspec:pg",
|
||||
"summary": { "total": 8, "resolved": 0, "errored": 0, "failed": 2 },
|
||||
"summary": {
|
||||
"total": 8,
|
||||
"resolved": 0,
|
||||
"errored": 0,
|
||||
"failed": 2
|
||||
},
|
||||
"new_failures": [
|
||||
{
|
||||
"result": "failure",
|
||||
|
|
@ -28,7 +38,12 @@
|
|||
},
|
||||
{
|
||||
"name": "java ant",
|
||||
"summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 0 },
|
||||
"summary": {
|
||||
"total": 3,
|
||||
"resolved": 0,
|
||||
"errored": 0,
|
||||
"failed": 0
|
||||
},
|
||||
"new_failures": [],
|
||||
"resolved_failures": [],
|
||||
"existing_failures": [],
|
||||
|
|
@ -37,4 +52,4 @@
|
|||
"existing_errors": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,21 @@
|
|||
{
|
||||
"status": "success",
|
||||
"summary": { "total": 11, "resolved": 0, "errored": 0, "failed": 0 },
|
||||
"summary": {
|
||||
"total": 11,
|
||||
"resolved": 0,
|
||||
"errored": 0,
|
||||
"failed": 0
|
||||
},
|
||||
"suites": [
|
||||
{
|
||||
"name": "rspec:pg",
|
||||
"status": "success",
|
||||
"summary": { "total": 8, "resolved": 0, "errored": 0, "failed": 0 },
|
||||
"summary": {
|
||||
"total": 8,
|
||||
"resolved": 0,
|
||||
"errored": 0,
|
||||
"failed": 0
|
||||
},
|
||||
"new_failures": [],
|
||||
"resolved_failures": [],
|
||||
"existing_failures": [],
|
||||
|
|
@ -16,7 +26,12 @@
|
|||
{
|
||||
"name": "java ant",
|
||||
"status": "success",
|
||||
"summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 0 },
|
||||
"summary": {
|
||||
"total": 3,
|
||||
"resolved": 0,
|
||||
"errored": 0,
|
||||
"failed": 0
|
||||
},
|
||||
"new_failures": [],
|
||||
"resolved_failures": [],
|
||||
"existing_failures": [],
|
||||
|
|
@ -25,4 +40,4 @@
|
|||
"existing_errors": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,21 @@
|
|||
{
|
||||
"summary": { "total": 11, "resolved": 0, "errored": 0, "failed": 3, "recentlyFailed": 2 },
|
||||
"summary": {
|
||||
"total": 11,
|
||||
"resolved": 0,
|
||||
"errored": 0,
|
||||
"failed": 3,
|
||||
"recentlyFailed": 2
|
||||
},
|
||||
"suites": [
|
||||
{
|
||||
"name": "rspec:pg",
|
||||
"summary": { "total": 8, "resolved": 0, "errored": 0, "failed": 2, "recentlyFailed": 1 },
|
||||
"summary": {
|
||||
"total": 8,
|
||||
"resolved": 0,
|
||||
"errored": 0,
|
||||
"failed": 2,
|
||||
"recentlyFailed": 1
|
||||
},
|
||||
"new_failures": [
|
||||
{
|
||||
"result": "failure",
|
||||
|
|
@ -30,7 +42,13 @@
|
|||
},
|
||||
{
|
||||
"name": "java ant",
|
||||
"summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 1, "recentlyFailed": 1 },
|
||||
"summary": {
|
||||
"total": 3,
|
||||
"resolved": 0,
|
||||
"errored": 0,
|
||||
"failed": 1,
|
||||
"recentlyFailed": 1
|
||||
},
|
||||
"new_failures": [
|
||||
{
|
||||
"result": "failure",
|
||||
|
|
@ -49,4 +67,4 @@
|
|||
"existing_errors": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,21 @@
|
|||
{
|
||||
"status": "success",
|
||||
"summary": { "total": 11, "resolved": 4, "errored": 0, "failed": 0 },
|
||||
"summary": {
|
||||
"total": 11,
|
||||
"resolved": 4,
|
||||
"errored": 0,
|
||||
"failed": 0
|
||||
},
|
||||
"suites": [
|
||||
{
|
||||
"name": "rspec:pg",
|
||||
"status": "success",
|
||||
"summary": { "total": 8, "resolved": 4, "errored": 0, "failed": 0 },
|
||||
"summary": {
|
||||
"total": 8,
|
||||
"resolved": 4,
|
||||
"errored": 0,
|
||||
"failed": 0
|
||||
},
|
||||
"new_failures": [],
|
||||
"resolved_failures": [
|
||||
{
|
||||
|
|
@ -18,7 +28,7 @@
|
|||
{
|
||||
"status": "success",
|
||||
"name": "Test#sum when a is 100 and b is 200 returns summary",
|
||||
"execution_time": 7.6e-5,
|
||||
"execution_time": 0.000076,
|
||||
"system_output": null,
|
||||
"stack_trace": null
|
||||
}
|
||||
|
|
@ -46,7 +56,12 @@
|
|||
{
|
||||
"name": "java ant",
|
||||
"status": "success",
|
||||
"summary": { "total": 3, "resolved": 0, "errored": 0, "failed": 0 },
|
||||
"summary": {
|
||||
"total": 3,
|
||||
"resolved": 0,
|
||||
"errored": 0,
|
||||
"failed": 0
|
||||
},
|
||||
"new_failures": [],
|
||||
"resolved_failures": [],
|
||||
"existing_failures": [],
|
||||
|
|
@ -55,4 +70,4 @@
|
|||
"existing_errors": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
import { GlIcon } from '@gitlab/ui';
|
||||
import { mountExtended, shallowMountExtended } from 'helpers/vue_test_utils_helper';
|
||||
import DiffCodeQuality from '~/diffs/components/diff_code_quality.vue';
|
||||
import { SEVERITY_CLASSES, SEVERITY_ICONS } from '~/reports/codequality_report/constants';
|
||||
import { SEVERITY_CLASSES, SEVERITY_ICONS } from '~/ci/reports/codequality_report/constants';
|
||||
import { multipleFindingsArr } from '../mock_data/diff_code_quality';
|
||||
|
||||
let wrapper;
|
||||
|
|
|
|||
|
|
@ -11,14 +11,14 @@ import { registerExtension } from '~/vue_merge_request_widget/components/extensi
|
|||
import httpStatusCodes from '~/lib/utils/http_status';
|
||||
import TestCaseDetails from '~/pipelines/components/test_reports/test_case_details.vue';
|
||||
|
||||
import { failedReport } from 'jest/reports/mock_data/mock_data';
|
||||
import mixedResultsTestReports from 'jest/reports/mock_data/new_and_fixed_failures_report.json';
|
||||
import newErrorsTestReports from 'jest/reports/mock_data/new_errors_report.json';
|
||||
import newFailedTestReports from 'jest/reports/mock_data/new_failures_report.json';
|
||||
import newFailedTestWithNullFilesReport from 'jest/reports/mock_data/new_failures_with_null_files_report.json';
|
||||
import successTestReports from 'jest/reports/mock_data/no_failures_report.json';
|
||||
import resolvedFailures from 'jest/reports/mock_data/resolved_failures.json';
|
||||
import recentFailures from 'jest/reports/mock_data/recent_failures_report.json';
|
||||
import { failedReport } from 'jest/ci/reports/mock_data/mock_data';
|
||||
import mixedResultsTestReports from 'jest/ci/reports/mock_data/new_and_fixed_failures_report.json';
|
||||
import newErrorsTestReports from 'jest/ci/reports/mock_data/new_errors_report.json';
|
||||
import newFailedTestReports from 'jest/ci/reports/mock_data/new_failures_report.json';
|
||||
import newFailedTestWithNullFilesReport from 'jest/ci/reports/mock_data/new_failures_with_null_files_report.json';
|
||||
import successTestReports from 'jest/ci/reports/mock_data/no_failures_report.json';
|
||||
import resolvedFailures from 'jest/ci/reports/mock_data/resolved_failures.json';
|
||||
import recentFailures from 'jest/ci/reports/mock_data/recent_failures_report.json';
|
||||
|
||||
const reportWithParsingErrors = failedReport;
|
||||
reportWithParsingErrors.suites[0].suite_errors = {
|
||||
|
|
|
|||
|
|
@ -204,6 +204,12 @@ RSpec.describe Gitlab::Audit::Type::Definition do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'validate that all the YAML definitions matches the audit event type schema' do
|
||||
it 'successfully loads all the YAML definitions' do
|
||||
expect { described_class.definitions }.not_to raise_error
|
||||
end
|
||||
end
|
||||
|
||||
describe '.definitions' do
|
||||
let(:store1) { Dir.mktmpdir('path1') }
|
||||
|
||||
|
|
|
|||
|
|
@ -117,8 +117,8 @@ module ExportFileHelper
|
|||
# Check whether this is a hash attribute inside a model
|
||||
if model.is_a?(Symbol)
|
||||
return true if (safe_hashes[model] - parent.keys).empty?
|
||||
else
|
||||
return true if safe_model?(model, excluded_attributes, parent)
|
||||
elsif safe_model?(model, excluded_attributes, parent)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -237,8 +237,8 @@ RSpec.shared_examples 'snippet visibility' do
|
|||
|
||||
if project.private?
|
||||
project.add_developer(external) unless member
|
||||
else
|
||||
member.delete if member
|
||||
elsif member
|
||||
member.delete
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -129,8 +129,8 @@ RSpec.shared_examples 'record ActiveRecord metrics in a metrics transaction' do
|
|||
expect(transaction).to receive(:increment).with("gitlab_transaction_db_#{db_role}_wal_count_total".to_sym, 1, { db_config_name: db_config_name })
|
||||
expect(transaction).to receive(:increment).with("gitlab_transaction_db_#{db_role}_wal_cached_count_total".to_sym, 1, { db_config_name: db_config_name }) if record_cached_query
|
||||
end
|
||||
else
|
||||
expect(transaction).not_to receive(:increment).with("gitlab_transaction_db_#{db_role}_wal_count_total".to_sym, 1, { db_config_name: db_config_name }) if db_role
|
||||
elsif db_role
|
||||
expect(transaction).not_to receive(:increment).with("gitlab_transaction_db_#{db_role}_wal_count_total".to_sym, 1, { db_config_name: db_config_name })
|
||||
end
|
||||
|
||||
subscriber.sql(event)
|
||||
|
|
|
|||
|
|
@ -1120,10 +1120,10 @@
|
|||
stylelint-declaration-strict-value "1.8.0"
|
||||
stylelint-scss "4.2.0"
|
||||
|
||||
"@gitlab/svgs@3.12.0":
|
||||
version "3.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.12.0.tgz#cebd2ebf21e803d0d9e674d43fcb2d868f5d5a62"
|
||||
integrity sha512-7GDMXuBoOL380sjdBSpPufUzwd5dJgkzqgpx26JBlrO2ShSW0k5KnmIurSXSe8gpqwAEIEw/BbpjCz0SRRRwQg==
|
||||
"@gitlab/svgs@3.13.0":
|
||||
version "3.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.13.0.tgz#2d62286c956bd49ba7156b2aa4eed79507baca53"
|
||||
integrity sha512-Yv4dZ4pOyUVMCZXNxLuMinZ/x8E6+g8/yM1z/2ERT0t7hSAC3bCUHn2OEFpujtYzFtwMZXMFPQFEJJipQ1I/+w==
|
||||
|
||||
"@gitlab/ui@50.1.2":
|
||||
version "50.1.2"
|
||||
|
|
|
|||
Loading…
Reference in New Issue