Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-12-02 00:07:06 +00:00
parent 61666f277a
commit b26eec8cbc
98 changed files with 670 additions and 585 deletions

View File

@ -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

View File

@ -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
##################################################

View File

@ -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'

View File

@ -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'

View File

@ -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"},

View File

@ -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)

View File

@ -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 {

View File

@ -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 {

View File

@ -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'),

View File

@ -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) => ({

View File

@ -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',

View File

@ -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 },

View File

@ -73,6 +73,7 @@ export default {
:disabled="disableSubmitButton"
:phrase="confirmationPhrase"
:button-text="confirmButtonText"
button-qa-selector="transfer_group_button"
@confirm="$emit('confirm')"
/>
</div>

View File

@ -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 {

View File

@ -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';

View File

@ -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';

View File

@ -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

View File

@ -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),

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -76,13 +76,11 @@ module DiffHelper
def diff_line_content(line)
if line.blank?
"&nbsp;".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

View File

@ -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

View File

@ -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)}?"

View File

@ -565,12 +565,10 @@ module SearchHelper
else
:success
end
elsif issuable.closed?
:info
else
if issuable.closed?
:info
else
:success
end
:success
end
end

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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|

View File

@ -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

View File

@ -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
---

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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",

View File

@ -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'

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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', () => {

View File

@ -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;

View File

@ -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', () => {

View File

@ -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(() => {

View File

@ -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;

View File

@ -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;

View File

@ -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": []
}
]
}
}

View File

@ -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": []
}
]
}
}

View File

@ -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": []
}
]
}
}

View File

@ -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": []
}
]
}
}

View File

@ -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": []
}
]
}
}

View File

@ -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": []
}
]
}
}

View File

@ -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": []
}
]
}
}

View File

@ -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;

View File

@ -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 = {

View File

@ -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') }

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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"