Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2023-03-20 15:08:26 +00:00
parent fa10e47f6e
commit 849e6f56ae
70 changed files with 678 additions and 351 deletions

View File

@ -1763,23 +1763,6 @@ Layout/ArgumentAlignment:
- 'ee/spec/views/admin/identities/index.html.haml_spec.rb'
- 'ee/spec/views/groups/edit.html.haml_spec.rb'
- 'ee/spec/views/projects/edit.html.haml_spec.rb'
- 'ee/spec/workers/adjourned_group_deletion_worker_spec.rb'
- 'ee/spec/workers/analytics/cycle_analytics/consistency_worker_spec.rb'
- 'ee/spec/workers/analytics/devops_adoption/create_snapshot_worker_spec.rb'
- 'ee/spec/workers/audit_events/audit_event_streaming_worker_spec.rb'
- 'ee/spec/workers/concerns/update_orchestration_policy_configuration_spec.rb'
- 'ee/spec/workers/create_github_webhook_worker_spec.rb'
- 'ee/spec/workers/ee/projects/inactive_projects_deletion_cron_worker_spec.rb'
- 'ee/spec/workers/ee/repository_check/batch_worker_spec.rb'
- 'ee/spec/workers/elastic_index_bulk_cron_worker_spec.rb'
- 'ee/spec/workers/elastic_index_initial_bulk_cron_worker_spec.rb'
- 'ee/spec/workers/epics/update_cached_metadata_worker_spec.rb'
- 'ee/spec/workers/namespaces/sync_namespace_name_worker_spec.rb'
- 'ee/spec/workers/pull_mirrors/reenable_configuration_worker_spec.rb'
- 'ee/spec/workers/repository_update_mirror_worker_spec.rb'
- 'ee/spec/workers/security/orchestration_policy_rule_schedule_namespace_worker_spec.rb'
- 'ee/spec/workers/security/orchestration_policy_rule_schedule_worker_spec.rb'
- 'ee/spec/workers/security/process_scan_result_policy_worker_spec.rb'
- 'lib/api/access_requests.rb'
- 'lib/api/admin/plan_limits.rb'
- 'lib/api/alert_management_alerts.rb'
@ -3073,37 +3056,4 @@ Layout/ArgumentAlignment:
- 'spec/views/projects/tags/index.html.haml_spec.rb'
- 'spec/views/shared/milestones/_issuables.html.haml_spec.rb'
- 'spec/views/shared/runners/_runner_details.html.haml_spec.rb'
- 'spec/workers/authorized_project_update/user_refresh_over_user_range_worker_spec.rb'
- 'spec/workers/build_hooks_worker_spec.rb'
- 'spec/workers/build_queue_worker_spec.rb'
- 'spec/workers/ci/job_artifacts/track_artifact_report_worker_spec.rb'
- 'spec/workers/concerns/worker_context_spec.rb'
- 'spec/workers/deployments/hooks_worker_spec.rb'
- 'spec/workers/design_management/new_version_worker_spec.rb'
- 'spec/workers/every_sidekiq_worker_spec.rb'
- 'spec/workers/integrations/irker_worker_spec.rb'
- 'spec/workers/jira_connect/sync_branch_worker_spec.rb'
- 'spec/workers/jira_connect/sync_builds_worker_spec.rb'
- 'spec/workers/jira_connect/sync_deployments_worker_spec.rb'
- 'spec/workers/jira_connect/sync_feature_flags_worker_spec.rb'
- 'spec/workers/jira_connect/sync_merge_request_worker_spec.rb'
- 'spec/workers/jira_connect/sync_project_worker_spec.rb'
- 'spec/workers/merge_requests/delete_source_branch_worker_spec.rb'
- 'spec/workers/merge_requests/update_head_pipeline_worker_spec.rb'
- 'spec/workers/namespaces/root_statistics_worker_spec.rb'
- 'spec/workers/object_pool/destroy_worker_spec.rb'
- 'spec/workers/pipeline_hooks_worker_spec.rb'
- 'spec/workers/pipeline_metrics_worker_spec.rb'
- 'spec/workers/process_commit_worker_spec.rb'
- 'spec/workers/projects/inactive_projects_deletion_cron_worker_spec.rb'
- 'spec/workers/projects/inactive_projects_deletion_notification_worker_spec.rb'
- 'spec/workers/rebase_worker_spec.rb'
- 'spec/workers/remote_mirror_notification_worker_spec.rb'
- 'spec/workers/remove_expired_members_worker_spec.rb'
- 'spec/workers/remove_unaccepted_member_invites_worker_spec.rb'
- 'spec/workers/remove_unreferenced_lfs_objects_worker_spec.rb'
- 'spec/workers/repository_update_remote_mirror_worker_spec.rb'
- 'spec/workers/run_pipeline_schedule_worker_spec.rb'
- 'spec/workers/update_head_pipeline_for_merge_request_worker_spec.rb'
- 'spec/workers/web_hook_worker_spec.rb'
- 'tooling/danger/suggestor.rb'

View File

@ -3164,7 +3164,6 @@ RSpec/ContextWording:
- 'spec/support_specs/helpers/stub_method_calls_spec.rb'
- 'spec/tasks/cache/clear/redis_spec.rb'
- 'spec/tasks/dev_rake_spec.rb'
- 'spec/tasks/gettext_rake_spec.rb'
- 'spec/tasks/gitlab/cleanup_rake_spec.rb'
- 'spec/tasks/gitlab/db/validate_config_rake_spec.rb'
- 'spec/tasks/gitlab/db_rake_spec.rb'

View File

@ -6079,7 +6079,6 @@ RSpec/MissingFeatureCategory:
- 'spec/tasks/admin_mode_spec.rb'
- 'spec/tasks/config_lint_spec.rb'
- 'spec/tasks/dev_rake_spec.rb'
- 'spec/tasks/gettext_rake_spec.rb'
- 'spec/tasks/gitlab/artifacts/check_rake_spec.rb'
- 'spec/tasks/gitlab/artifacts/migrate_rake_spec.rb'
- 'spec/tasks/gitlab/background_migrations_rake_spec.rb'

View File

@ -77,7 +77,6 @@ Style/RedundantRegexpEscape:
- 'lib/gitlab/utils/sanitize_node_link.rb'
- 'lib/gitlab/word_diff/segments/diff_hunk.rb'
- 'lib/product_analytics/tracker.rb'
- 'lib/tasks/gettext.rake'
- 'lib/tasks/gitlab/info.rake'
- 'qa/spec/runtime/key/ecdsa_spec.rb'
- 'qa/spec/runtime/key/ed25519_spec.rb'

View File

@ -1 +1 @@
534e1a1c783059ab7a24ede2c63a53867ba393a2
1017fbf2f98b23dd93d86173015159fd31df64d0

View File

@ -102,7 +102,7 @@ gem 'acme-client', '~> 2.0'
gem 'browser', '~> 5.3.1'
# OS detection for usage ping
gem 'ohai', '~> 16.10'
gem 'ohai', '~> 17.9'
# GPG
gem 'gpgme', '~> 2.0.22'

View File

@ -396,7 +396,7 @@
{"name":"oauth","version":"0.5.6","platform":"ruby","checksum":"4085fe28e0c5e2434135e00a6555294fd2a4ff96a98d1bdecdcd619fc6368dff"},
{"name":"oauth2","version":"2.0.9","platform":"ruby","checksum":"b21f9defcf52dc1610e0dfab4c868342173dcd707fd15c777d9f4f04e153f7fb"},
{"name":"octokit","version":"4.25.1","platform":"ruby","checksum":"c02092ee82dcdfe84db0e0ea630a70d32becc54245a4f0bacfd21c010df09b96"},
{"name":"ohai","version":"16.10.6","platform":"ruby","checksum":"b835806e585faea4ac8346b68c722fb5fc29a29f73fd7e3a022f9073132dec22"},
{"name":"ohai","version":"17.9.0","platform":"ruby","checksum":"c59cf16124c0a6481fb85013ec7ec5b398651b6abed782d3e06ab058ce9a5406"},
{"name":"oj","version":"3.13.23","platform":"ruby","checksum":"206dfdc4020ad9974705037f269cfba211d61b7662a58c717cce771829ccef51"},
{"name":"oj-introspect","version":"0.7.2","platform":"ruby","checksum":"c415a44567ed2870d8e963a69421d9322128e194fab7867e37e54d5a25d5333d"},
{"name":"omniauth","version":"2.1.0","platform":"ruby","checksum":"bff7234f5ec9323622b217c7f26d52f850de0b0e2b8c807c3358fc79fe572300"},

View File

@ -1000,16 +1000,16 @@ GEM
octokit (4.25.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
ohai (16.10.6)
chef-config (>= 12.8, < 17)
chef-utils (>= 16.0, < 17)
ohai (17.9.0)
chef-config (>= 14.12, < 18)
chef-utils (>= 16.0, < 18)
ffi (~> 1.9)
ffi-yajl (~> 2.2)
ipaddress
mixlib-cli (>= 1.7.0)
mixlib-config (>= 2.0, < 4.0)
mixlib-log (>= 2.0.1, < 4.0)
mixlib-shellout (>= 2.0, < 4.0)
mixlib-shellout (~> 3.2, >= 3.2.5)
plist (~> 3.1)
train-core
wmi-lite (~> 1.0)
@ -1801,7 +1801,7 @@ DEPENDENCIES
nokogiri (~> 1.14.2)
oauth2 (~> 2.0)
octokit (~> 4.15)
ohai (~> 16.10)
ohai (~> 17.9)
oj (~> 3.13.21)
oj-introspect (~> 0.7)
omniauth (~> 2.1.0)

View File

@ -0,0 +1,33 @@
# frozen_string_literal: true
module Mutations
module Achievements
class Delete < BaseMutation
graphql_name 'AchievementsDelete'
include Gitlab::Graphql::Authorize::AuthorizeResource
field :achievement,
::Types::Achievements::AchievementType,
null: true,
description: 'Achievement.'
argument :achievement_id, ::Types::GlobalIDType[::Achievements::Achievement],
required: true,
description: 'Global ID of the achievement being deleted.'
authorize :admin_achievement
def resolve(args)
achievement = authorized_find!(id: args[:achievement_id])
result = ::Achievements::DestroyService.new(current_user, achievement).execute
{ achievement: result.payload, errors: result.errors }
end
def find_object(id:)
GitlabSchema.object_from_id(id, expected_type: ::Achievements::Achievement)
end
end
end
end

View File

@ -8,6 +8,7 @@ module Types
mount_mutation Mutations::Achievements::Award, alpha: { milestone: '15.10' }
mount_mutation Mutations::Achievements::Create, alpha: { milestone: '15.8' }
mount_mutation Mutations::Achievements::Delete, alpha: { milestone: '15.11' }
mount_mutation Mutations::Achievements::Revoke, alpha: { milestone: '15.10' }
mount_mutation Mutations::Admin::SidekiqQueues::DeleteJobs
mount_mutation Mutations::AlertManagement::CreateAlertIssue

View File

@ -17,3 +17,5 @@ module ProtectedBranchesHelper
end
end
end
ProtectedBranchesHelper.prepend_mod

View File

@ -58,12 +58,23 @@ module UsersHelper
end
# Used to preload when you are rendering many projects and checking access
#
# rubocop: disable CodeReuse/ActiveRecord: `projects` can be array which also responds to pluck
def load_max_project_member_accesses(projects)
current_user&.max_member_access_for_project_ids(projects.pluck(:id))
# There are two different request store paradigms for max member access and
# we need to preload both of them. One is keyed User the other is keyed by
# Project. See https://gitlab.com/gitlab-org/gitlab/-/issues/396822
# rubocop: disable CodeReuse/ActiveRecord: `projects` can be array which also responds to pluck
project_ids = projects.pluck(:id)
# rubocop: enable CodeReuse/ActiveRecord
if Feature.enabled?(:fix_users_helper_load_max_project_member_accesses)
Preloaders::UserMaxAccessLevelInProjectsPreloader
.new(project_ids, current_user)
.execute
end
current_user&.max_member_access_for_project_ids(project_ids)
end
# rubocop: enable CodeReuse/ActiveRecord
def max_project_member_access(project)
current_user&.max_member_access_for_project(project.id) || Gitlab::Access::NO_ACCESS

View File

@ -22,7 +22,7 @@ module VisibilityLevelHelper
when Project
project_visibility_level_description(level)
when Group
group_visibility_level_description(level)
group_visibility_level_description(level, form_model)
end
end
@ -125,22 +125,39 @@ module VisibilityLevelHelper
def project_visibility_level_description(level)
case level
when Gitlab::VisibilityLevel::PRIVATE
_("Project access must be granted explicitly to each user. If this project is part of a group, access is granted to members of the group.")
s_("VisibilityLevel|Project access must be granted explicitly to each user. If this project is part of a group, access is granted to members of the group.")
when Gitlab::VisibilityLevel::INTERNAL
_("The project can be accessed by any logged in user except external users.")
s_("VisibilityLevel|The project can be accessed by any logged in user except external users.")
when Gitlab::VisibilityLevel::PUBLIC
_("The project can be accessed without any authentication.")
s_("VisibilityLevel|The project can be accessed without any authentication.")
end
end
def group_visibility_level_description(level)
def show_updated_public_description_for_setting(group)
group && !group.new_record? && Gitlab::CurrentSettings.current_application_settings.try(:should_check_namespace_plan?)
end
def group_visibility_level_description(level, group = nil)
case level
when Gitlab::VisibilityLevel::PRIVATE
_("The group and its projects can only be viewed by members.")
s_("VisibilityLevel|The group and its projects can only be viewed by members.")
when Gitlab::VisibilityLevel::INTERNAL
_("The group and any internal projects can be viewed by any logged in user except external users.")
s_("VisibilityLevel|The group and any internal projects can be viewed by any logged in user except external users.")
when Gitlab::VisibilityLevel::PUBLIC
_("The group and any public projects can be viewed without any authentication.")
unless show_updated_public_description_for_setting(group)
return s_('VisibilityLevel|The group and any public projects can be viewed without any authentication.')
end
Kernel.format(
s_(
'VisibilityLevel|The group, any public projects, and any of their members, issues, and merge requests can be viewed without authentication. ' \
'Public groups and projects will be indexed by search engines. ' \
'Read more about %{free_user_limit_doc_link_start}free user limits%{link_end}, ' \
'or %{group_billings_link_start}upgrade to a paid tier%{link_end}.'),
free_user_limit_doc_link_start: "<a href='#{help_page_path('user/free_user_limit')}' target='_blank' rel='noopener noreferrer'>".html_safe,
group_billings_link_start: "<a href='#{group_billings_path(group)}' target='_blank' rel='noopener noreferrer'>".html_safe,
link_end: "</a>".html_safe
).html_safe
end
end

View File

@ -168,6 +168,7 @@ class Project < ApplicationRecord
alias_method :parent, :namespace
alias_attribute :parent_id, :namespace_id
has_one :catalog_resource, class_name: 'Ci::Catalog::Resource', inverse_of: :project
has_one :last_event, -> { order 'events.created_at DESC' }, class_name: 'Event'
has_many :boards

View File

@ -0,0 +1,33 @@
# frozen_string_literal: true
module Achievements
class DestroyService
attr_reader :current_user, :achievement
def initialize(current_user, achievement)
@current_user = current_user
@achievement = achievement
end
def execute
return error_no_permissions unless allowed?
achievement.delete
ServiceResponse.success(payload: achievement)
end
private
def allowed?
current_user&.can?(:admin_achievement, achievement)
end
def error_no_permissions
error('You have insufficient permissions to delete this achievement')
end
def error(message)
ServiceResponse.error(message: Array(message))
end
end
end

View File

@ -18,6 +18,12 @@ module Releases
return tag unless tag.is_a?(Gitlab::Git::Tag)
if project.catalog_resource
response = Ci::Catalog::ValidateResourceService.new(project, ref).execute
return error(response.message) if response.error?
end
create_release(tag, evidence_pipeline)
end

View File

@ -28,7 +28,7 @@ module ObjectStorage
expiration = (Time.current + expiry).utc.to_i
uri = Addressable::URI.parse(cdn_url)
uri.path = path
uri.path = Addressable::URI.encode_component(path, Addressable::URI::CharacterClasses::PATH)
# Use an Array to preserve order: Google CDN needs to have
# Expires, KeyName, and Signature in that order or it will return a 403 error:
# https://cloud.google.com/cdn/docs/troubleshooting-steps#signing

View File

@ -34,7 +34,6 @@
= dispensable_render_if_exists "shared/namespace_user_cap_reached_alert"
= dispensable_render_if_exists "shared/new_user_signups_cap_reached_alert"
= yield :page_level_alert
= yield :free_user_cap_alert
= yield :group_invite_members_banner
- unless @hide_breadcrumbs
= render "layouts/nav/breadcrumbs"

View File

@ -1,8 +1,8 @@
---
name: disable_update_max_seats_worker
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/114127
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/382725
name: arkose_labs_trial_signup_challenge
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/113985
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/395754
milestone: '15.10'
type: development
group: group::utilization
group: group::anti-abuse
default_enabled: false

View File

@ -0,0 +1,8 @@
---
name: fix_users_helper_load_max_project_member_accesses
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/114665
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/396647
milestone: '15.11'
type: development
group: 'group::pipeline execution'
default_enabled: false

View File

@ -761,9 +761,6 @@ Gitlab.ee do
Settings.cron_jobs['ldap_sync_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['ldap_sync_worker']['cron'] ||= '30 1 * * *'
Settings.cron_jobs['ldap_sync_worker']['job_class'] = 'LdapSyncWorker'
Settings.cron_jobs['update_max_seats_used_for_gitlab_com_subscriptions_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['update_max_seats_used_for_gitlab_com_subscriptions_worker']['cron'] ||= '0 12 * * *'
Settings.cron_jobs['update_max_seats_used_for_gitlab_com_subscriptions_worker']['job_class'] = 'UpdateMaxSeatsUsedForGitlabComSubscriptionsWorker'
Settings.cron_jobs['elastic_index_bulk_cron_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['elastic_index_bulk_cron_worker']['cron'] ||= '*/1 * * * *'
Settings.cron_jobs['elastic_index_bulk_cron_worker']['job_class'] ||= 'ElasticIndexBulkCronWorker'

View File

@ -7,7 +7,7 @@
available_in: [Ultimate]
documentation_link: https://docs.gitlab.com/ee/user/permissions.html#custom-roles
image_url: https://img.youtube.com/vi/46cp_-Rtxps/hqdefault.jpg
published_at: 2023-02-02 # YYYY-MM-DD
published_at: 2023-02-22 # YYYY-MM-DD
release: 15.9
- name: Manage license approval policies
description: | # Do not modify this line, instead modify the lines below.
@ -26,7 +26,7 @@
available_in: [Ultimate]
documentation_link: https://docs.gitlab.com/ee/user/compliance/license_approval_policies.html
image_url: https://img.youtube.com/vi/34qBQ9t8qO8/hqdefault.jpg
published_at: 2023-02-02 # YYYY-MM-DD
published_at: 2023-02-22 # YYYY-MM-DD
release: 15.9
- name: New License Compliance scanner
description: | # Do not modify this line, instead modify the lines below.
@ -41,7 +41,7 @@
available_in: [Ultimate]
documentation_link: https://docs.gitlab.com/ee/user/compliance/license_scanning_of_cyclonedx_files/
image_url: https://about.gitlab.com/images/15_9/new_license_scanner.png
published_at: 2023-02-02 # YYYY-MM-DD
published_at: 2023-02-22 # YYYY-MM-DD
release: 15.9
- name: Notifications now available in the GitLab for Slack app
description: | # Do not modify this line, instead modify the lines below.
@ -56,7 +56,7 @@
available_in: [Free, Premium, Ultimate]
documentation_link: https://docs.gitlab.com/ee/user/project/integrations/gitlab_slack_application.html#slack-notifications
image_url: https://about.gitlab.com/images/15_9/slack_notifications_jan_31-optimized.png
published_at: 2023-02-02 # YYYY-MM-DD
published_at: 2023-02-22 # YYYY-MM-DD
release: 15.9
- name: Code Suggestions available in closed beta
description: | # Do not modify this line, instead modify the lines below.
@ -71,5 +71,5 @@
available_in: [Ultimate]
documentation_link: https://about.gitlab.com/releases/2023/02/22/gitlab-15-9-released/#code-suggestions-available-in-closed-beta
image_url: https://about.gitlab.com/images/15_9/DemoFastApi.gif
published_at: 2023-02-02 # YYYY-MM-DD
published_at: 2023-02-22 # YYYY-MM-DD
release: 15.9

View File

@ -795,6 +795,29 @@ Input type: `AchievementsCreateInput`
| <a id="mutationachievementscreateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationachievementscreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
### `Mutation.achievementsDelete`
WARNING:
**Introduced** in 15.11.
This feature is in Alpha. It can be changed or removed at any time.
Input type: `AchievementsDeleteInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationachievementsdeleteachievementid"></a>`achievementId` | [`AchievementsAchievementID!`](#achievementsachievementid) | Global ID of the achievement being deleted. |
| <a id="mutationachievementsdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationachievementsdeleteachievement"></a>`achievement` | [`Achievement`](#achievement) | Achievement. |
| <a id="mutationachievementsdeleteclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationachievementsdeleteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
### `Mutation.achievementsRevoke`
WARNING:

View File

@ -140,7 +140,7 @@ The DORA metrics are displayed on the following charts:
The table below provides an overview of the DORA metrics' data aggregation in different charts.
| Metric name | Measured values | Data aggregation in the [Value Streams Dashboard](value_streams_dashboard.md) | Data aggregation in CI/CD analytics charts | Data aggregation in Value stream analytics | Data aggregation in Custom insights reporting |
| Metric name | Measured values | Data aggregation in the [Value Streams Dashboard](value_streams_dashboard.md) | Data aggregation in [CI/CD analytics charts](ci_cd_analytics.md) | Data aggregation in Value stream analytics | Data aggregation in [Custom insights reporting](../../user/project/insights/index.md#dora-query-parameters) |
|---------------------------|-------------------|-----------------------------------------------------|------------------------|-----------------------|----------|
| Deployment frequency | Number of successful deployments | daily average per month | daily average | daily average | `day` (default) or `month` |
| Lead time for changes | Number of seconds to successfully deliver a commit into production | daily median per month | median time | median time | `day` (default) or `month` |

View File

@ -11,45 +11,23 @@ namespace :gettext do
end
desc 'Regenerate gitlab.pot file'
task :regenerate do
task regenerate: ['gettext:setup'] do
ensure_locale_folder_presence!
# Clean up folders that do not contain a gitlab.po file
Pathname.new(locale_path).children.each do |child|
next unless child.directory?
folder_path = child.to_path
if File.exist?("#{folder_path}/gitlab.po")
# remove all translated files to speed up finding
FileUtils.rm Dir["#{folder_path}/gitlab.*"]
else
# remove empty translation folders so we don't generate un-needed .po files
puts "Deleting #{folder_path} as it does not contain a 'gitlab.po' file."
FileUtils.rm_r folder_path
end
end
# remove the `pot` file to ensure it's completely regenerated
FileUtils.rm_f(pot_file_path)
Rake::Task['gettext:find'].invoke
# leave only the required changes.
unless system(*%w(git -c core.hooksPath=/dev/null checkout -- locale/*/gitlab.po))
raise 'failed to cleanup generated locale/*/gitlab.po files'
end
Rake::Task['gettext:pot:create'].invoke
raise 'gitlab.pot file not generated' unless File.exist?(pot_file_path)
# Remove timestamps from the pot file
pot_content = File.read pot_file_path
pot_content.gsub!(/^"POT?\-(?:Creation|Revision)\-Date\:.*\n/, '')
pot_content.gsub!(/^"POT?-(?:Creation|Revision)-Date:.*\n/, '')
File.write pot_file_path, pot_content
puts <<~MSG
All done. Please commit the changes to `locale/gitlab.pot`.
All done. Please commit the changes to `locale/gitlab.pot`.
MSG
end
@ -86,19 +64,7 @@ namespace :gettext do
end
end
task :updated_check do
# Removing all pre-translated files speeds up `gettext:find` as the
# files don't need to be merged.
# Having `LC_MESSAGES/gitlab.mo files present also confuses the output.
FileUtils.rm Dir['locale/**/gitlab.*']
FileUtils.rm_f pot_file_path
# `gettext:find` writes touches to temp files to `stderr` which would cause
# `static-analysis` to report failures. We can ignore these.
silence_stderr do
Rake::Task['gettext:find'].invoke
end
task updated_check: [:regenerate] do
pot_diff = `git diff -- #{pot_file_path} | grep -E '^(\\+|-)msgid'`.strip
# reset the locale folder for potential next tasks
@ -159,7 +125,7 @@ namespace :gettext do
def ensure_locale_folder_presence!
unless Dir.exist?(locale_path)
raise <<~MSG
Cannot find '#{locale_path}' folder. Please ensure you're running this task from the gitlab repo.
Cannot find '#{locale_path}' folder. Please ensure you're running this task from the gitlab repo.
MSG
end

View File

@ -33673,9 +33673,6 @@ msgstr ""
msgid "Project URL"
msgstr ""
msgid "Project access must be granted explicitly to each user. If this project is part of a group, access is granted to members of the group."
msgstr ""
msgid "Project access token creation is disabled in this group. You can still use and manage existing tokens. %{link_start}Learn more.%{link_end}"
msgstr ""
@ -43627,15 +43624,6 @@ msgstr ""
msgid "The global settings require you to enable Two-Factor Authentication for your account."
msgstr ""
msgid "The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "The group and any public projects can be viewed without any authentication."
msgstr ""
msgid "The group and its projects can only be viewed by members."
msgstr ""
msgid "The group export can be downloaded from:"
msgstr ""
@ -43795,12 +43783,6 @@ msgstr ""
msgid "The pipelines schedule runs pipelines in the future, repeatedly, for specific branches or tags. Those scheduled pipelines will inherit limited project access based on their associated user."
msgstr ""
msgid "The project can be accessed by any logged in user except external users."
msgstr ""
msgid "The project can be accessed without any authentication."
msgstr ""
msgid "The project has already been added to your dashboard."
msgstr ""
@ -48058,9 +48040,30 @@ msgstr ""
msgid "VisibilityLevel|Private"
msgstr ""
msgid "VisibilityLevel|Project access must be granted explicitly to each user. If this project is part of a group, access is granted to members of the group."
msgstr ""
msgid "VisibilityLevel|Public"
msgstr ""
msgid "VisibilityLevel|The group and any internal projects can be viewed by any logged in user except external users."
msgstr ""
msgid "VisibilityLevel|The group and any public projects can be viewed without any authentication."
msgstr ""
msgid "VisibilityLevel|The group and its projects can only be viewed by members."
msgstr ""
msgid "VisibilityLevel|The group, any public projects, and any of their members, issues, and merge requests can be viewed without authentication. Public groups and projects will be indexed by search engines. Read more about %{free_user_limit_doc_link_start}free user limits%{link_end}, or %{group_billings_link_start}upgrade to a paid tier%{link_end}."
msgstr ""
msgid "VisibilityLevel|The project can be accessed by any logged in user except external users."
msgstr ""
msgid "VisibilityLevel|The project can be accessed without any authentication."
msgstr ""
msgid "VisibilityLevel|Unknown"
msgstr ""

View File

@ -0,0 +1,56 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Mutations::Achievements::Delete, feature_category: :user_profile do
include GraphqlHelpers
let_it_be(:developer) { create(:user) }
let_it_be(:maintainer) { create(:user) }
let_it_be(:recipient) { create(:user) }
let_it_be(:group) { create(:group) }
let(:achievement) { create(:achievement, namespace: group) }
describe '#resolve' do
subject(:resolve_mutation) do
described_class.new(object: nil, context: { current_user: current_user }, field: nil).resolve(
achievement_id: achievement&.to_global_id
)
end
before_all do
group.add_developer(developer)
group.add_maintainer(maintainer)
end
context 'when the user does not have permission' do
let(:current_user) { developer }
it 'raises an error' do
expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable)
.with_message(Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR)
end
end
context 'when the user has permission' do
let(:current_user) { maintainer }
context 'when the params are invalid' do
let(:achievement) { nil }
it 'returns the validation error' do
expect { resolve_mutation }.to raise_error { Gitlab::Graphql::Errors::ArgumentError }
end
end
it 'deletes the achievement' do
resolve_mutation
expect(Achievements::Achievement.find_by(id: achievement.id)).to be_nil
end
end
end
specify { expect(described_class).to require_graphql_authorizations(:admin_achievement) }
end

View File

@ -524,4 +524,54 @@ RSpec.describe UsersHelper do
})
end
end
describe '#load_max_project_member_accesses' do
let_it_be(:projects) { create_list(:project, 3) }
before(:all) do
projects.first.add_developer(user)
end
context 'without current_user' do
before do
allow(helper).to receive(:current_user).and_return(nil)
end
it 'executes no queries' do
sample = ActiveRecord::QueryRecorder.new do
helper.load_max_project_member_accesses(projects)
end
expect(sample).not_to exceed_query_limit(0)
end
end
context 'when current_user is present', :request_store do
before do
allow(helper).to receive(:current_user).and_return(user)
end
it 'preloads ProjectPolicy#lookup_access_level! and UsersHelper#max_member_project_member_access for current_user in two queries', :aggregate_failures do
preload_queries = ActiveRecord::QueryRecorder.new do
helper.load_max_project_member_accesses(projects)
end
helper_queries = ActiveRecord::QueryRecorder.new do
projects.each do |project|
helper.max_project_member_access(project)
end
end
access_queries = ActiveRecord::QueryRecorder.new do
projects.each do |project|
user.can?(:read_code, project)
end
end
expect(preload_queries).not_to exceed_query_limit(2)
expect(helper_queries).not_to exceed_query_limit(0)
expect(access_queries).not_to exceed_query_limit(0)
end
end
end
end

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe VisibilityLevelHelper do
RSpec.describe VisibilityLevelHelper, feature_category: :system_access do
include ProjectForksHelper
let(:project) { build(:project) }
@ -78,6 +78,23 @@ RSpec.describe VisibilityLevelHelper do
expect(descriptions.uniq.size).to eq(descriptions.size)
expect(descriptions).to all match /group/i
end
it 'returns default description for public group' do
expect(descriptions[2]).to eq('The group and any public projects can be viewed without any authentication.')
end
context 'when application setting `should_check_namespace_plan` is true', if: Gitlab.ee? do
let(:group) { create(:group) }
let(:public_option_description) { visibility_level_description(Gitlab::VisibilityLevel::PUBLIC, group) }
before do
allow(Gitlab::CurrentSettings.current_application_settings).to receive(:should_check_namespace_plan?) { true }
end
it 'returns updated description for public visibility option in group general settings' do
expect(public_option_description).to match /^The group, any public projects, and any of their members, issues, and merge requests can be viewed without authentication./
end
end
end
end

View File

@ -493,6 +493,7 @@ container_repositories:
- project
- name
project:
- catalog_resource
- external_status_checks
- base_tags
- project_topics
@ -998,3 +999,5 @@ resource_iteration_events:
iterations_cadence:
- group
- iterations
catalog_resource:
- project

View File

@ -43,6 +43,7 @@ RSpec.describe Project, factory_default: :keep, feature_category: :projects do
it { is_expected.to have_many(:exported_protected_branches) }
it { is_expected.to have_one(:wiki_repository).class_name('Projects::WikiRepository').inverse_of(:project) }
it { is_expected.to have_one(:slack_integration) }
it { is_expected.to have_one(:catalog_resource) }
it { is_expected.to have_one(:microsoft_teams_integration) }
it { is_expected.to have_one(:mattermost_integration) }
it { is_expected.to have_one(:hangouts_chat_integration) }

View File

@ -0,0 +1,79 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Mutations::Achievements::Delete, feature_category: :user_profile do
include GraphqlHelpers
let_it_be(:developer) { create(:user) }
let_it_be(:maintainer) { create(:user) }
let_it_be(:group) { create(:group) }
let!(:achievement) { create(:achievement, namespace: group) }
let(:mutation) { graphql_mutation(:achievements_delete, params) }
let(:achievement_id) { achievement&.to_global_id }
let(:params) { { achievement_id: achievement_id } }
subject { post_graphql_mutation(mutation, current_user: current_user) }
def mutation_response
graphql_mutation_response(:achievements_delete)
end
before_all do
group.add_developer(developer)
group.add_maintainer(maintainer)
end
context 'when the user does not have permission' do
let(:current_user) { developer }
it_behaves_like 'a mutation that returns a top-level access error'
it 'does not revoke any achievements' do
expect { subject }.not_to change { Achievements::Achievement.count }
end
end
context 'when the user has permission' do
let(:current_user) { maintainer }
context 'when the params are invalid' do
let(:achievement) { nil }
it 'returns the validation error' do
subject
expect(graphql_errors.to_s).to include('invalid value for achievementId (Expected value to not be null)')
end
end
context 'when the achievement_id is invalid' do
let(:achievement_id) { "gid://gitlab/Achievements::Achievement/#{non_existing_record_id}" }
it 'returns the validation error' do
subject
expect(graphql_errors.to_s)
.to include("The resource that you are attempting to access does not exist or you don't have permission")
end
end
context 'when the feature flag is disabled' do
before do
stub_feature_flags(achievements: false)
end
it 'returns the relevant error' do
subject
expect(graphql_errors.to_s)
.to include("The resource that you are attempting to access does not exist or you don't have permission")
end
end
it 'deletes the achievement' do
expect { subject }.to change { Achievements::Achievement.count }.by(-1)
end
end
end

View File

@ -0,0 +1,39 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Achievements::DestroyService, feature_category: :user_profile do
describe '#execute' do
let_it_be(:developer) { create(:user) }
let_it_be(:maintainer) { create(:user) }
let_it_be(:group) { create(:group) }
let(:achievement) { create(:achievement, namespace: group) }
subject(:response) { described_class.new(current_user, achievement).execute }
before_all do
group.add_developer(developer)
group.add_maintainer(maintainer)
end
context 'when user does not have permission' do
let(:current_user) { developer }
it 'returns an error' do
expect(response).to be_error
expect(response.message).to match_array(
['You have insufficient permissions to delete this achievement'])
end
end
context 'when user has permission' do
let(:current_user) { maintainer }
it 'deletes the achievement' do
expect(response).to be_success
expect(Achievements::Achievement.find_by(id: achievement.id)).to be_nil
end
end
end
end

View File

@ -55,6 +55,26 @@ RSpec.describe Releases::CreateService, feature_category: :continuous_integratio
end
end
context 'when project is a catalog resource' do
let(:ref) { 'master' }
let!(:catalog_resource) { create(:catalog_resource, project: project) }
context 'and it is valid' do
let_it_be(:project) { create(:project, :repository, description: 'our components') }
it_behaves_like 'a successful release creation'
end
context 'and it is invalid' do
it 'raises an error and does not update the release' do
result = service.execute
expect(result[:status]).to eq(:error)
expect(result[:message]).to eq('Project must have a description')
end
end
end
context 'when ref is provided' do
let(:ref) { 'master' }
let(:tag_name) { 'foobar' }

View File

@ -3310,7 +3310,6 @@
- './ee/spec/workers/sync_seat_link_worker_spec.rb'
- './ee/spec/workers/todos_destroyer/confidential_epic_worker_spec.rb'
- './ee/spec/workers/update_all_mirrors_worker_spec.rb'
- './ee/spec/workers/update_max_seats_used_for_gitlab_com_subscriptions_worker_spec.rb'
- './ee/spec/workers/vulnerabilities/historical_statistics/deletion_worker_spec.rb'
- './ee/spec/workers/vulnerabilities/statistics/adjustment_worker_spec.rb'
- './ee/spec/workers/vulnerabilities/statistics/schedule_worker_spec.rb'
@ -10049,7 +10048,6 @@
- './spec/tasks/cache/clear/redis_spec.rb'
- './spec/tasks/config_lint_spec.rb'
- './spec/tasks/dev_rake_spec.rb'
- './spec/tasks/gettext_rake_spec.rb'
- './spec/tasks/gitlab/artifacts/check_rake_spec.rb'
- './spec/tasks/gitlab/artifacts/migrate_rake_spec.rb'
- './spec/tasks/gitlab/background_migrations_rake_spec.rb'

View File

@ -2,7 +2,7 @@
require 'rake_helper'
RSpec.describe 'gettext', :silence_stdout do
RSpec.describe 'gettext', :silence_stdout, feature_category: :internationalization do
let(:locale_path) { Rails.root.join('tmp/gettext_spec') }
let(:pot_file_path) { File.join(locale_path, 'gitlab.pot') }
@ -35,9 +35,16 @@ RSpec.describe 'gettext', :silence_stdout do
end
describe ':regenerate' do
let(:locale_nz_path) { File.join(locale_path, 'en_NZ') }
let(:po_file_path) { File.join(locale_nz_path, 'gitlab.po') }
before do
FileUtils.mkdir(locale_nz_path)
File.write(po_file_path, fixture_file('valid.po'))
Rake::Task['gettext:setup'].invoke
# this task takes a *really* long time to complete, so stub it for the spec
allow(Rake::Task['gettext:find']).to receive(:invoke) { invoke_find.call }
allow(Rake::Task['gettext:pot:create']).to receive(:invoke) { invoke_find.call }
end
context 'when the locale folder is not found' do
@ -53,39 +60,6 @@ RSpec.describe 'gettext', :silence_stdout do
end
end
context 'where there are existing /**/gitlab.po files' do
let(:locale_nz_path) { File.join(locale_path, 'en_NZ') }
let(:po_file_path) { File.join(locale_nz_path, 'gitlab.po') }
let(:invoke_find) { -> { File.write pot_file_path, 'pot file test updates' } }
before do
FileUtils.mkdir(locale_nz_path)
File.write(po_file_path, fixture_file('valid.po'))
end
it 'does not remove that locale' do
expect { run_rake_task('gettext:regenerate') }
.not_to change { Dir.exist?(locale_nz_path) }
end
end
context 'when there are locale folders without a gitlab.po file' do
let(:empty_locale_path) { File.join(locale_path, 'en_NZ') }
let(:invoke_find) { -> { File.write pot_file_path, 'pot file test updates' } }
before do
FileUtils.mkdir(empty_locale_path)
end
it 'removes those folders' do
expect { run_rake_task('gettext:regenerate') }
.to change { Dir.exist?(empty_locale_path) }
.to eq false
end
end
context 'when the gitlab.pot file cannot be generated' do
let(:invoke_find) { -> { true } }
@ -95,7 +69,7 @@ RSpec.describe 'gettext', :silence_stdout do
end
end
context 'when gettext:find changes the revision dates' do
context 'when gettext:pot:create changes the revision dates' do
let(:invoke_find) { -> { File.write pot_file_path, fixture_file('valid.po') } }
before do

View File

@ -99,9 +99,10 @@ RSpec.describe ObjectStorage::CDN::GoogleCDN,
let(:path) { '/path/to/file.txt' }
let(:expiration) { (Time.current + 10.minutes).utc.to_i }
let(:cdn_query_params) { "Expires=#{expiration}&KeyName=#{key_name}" }
let(:encoded_path) { Addressable::URI.encode_component(path, Addressable::URI::CharacterClasses::PATH) }
def verify_signature(url, unsigned_url)
expect(url).to start_with("#{options[:url]}#{path}")
expect(url).to start_with("#{options[:url]}#{encoded_path}")
uri = Addressable::URI.parse(url)
query = uri.query_values
@ -116,6 +117,16 @@ RSpec.describe ObjectStorage::CDN::GoogleCDN,
end
end
context 'with UTF-8 characters in path' do
let(:path) { "/path/to/©job🧪" }
let(:url) { subject.signed_url(path) }
let(:unsigned_url) { "#{options[:url]}#{encoded_path}?#{cdn_query_params}" }
it 'returns a valid signed URL' do
verify_signature(url, unsigned_url)
end
end
context 'with default query parameters' do
let(:url) { subject.signed_url(path) }
let(:unsigned_url) { "#{options[:url]}#{path}?#{cdn_query_params}" }

View File

@ -10,9 +10,7 @@ RSpec.describe AuthorizedProjectUpdate::UserRefreshOverUserRangeWorker, feature_
let(:end_user_id) { start_user_id }
let(:execute_worker) { subject.perform(start_user_id, end_user_id) }
it_behaves_like 'worker with data consistency',
described_class,
data_consistency: :delayed
it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
describe '#perform' do
context 'checks if project authorization update is required' do

View File

@ -42,7 +42,5 @@ RSpec.describe BuildHooksWorker, feature_category: :continuous_integration do
end
end
it_behaves_like 'worker with data consistency',
described_class,
data_consistency: :delayed
it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
end

View File

@ -24,7 +24,5 @@ RSpec.describe BuildQueueWorker, feature_category: :continuous_integration do
end
end
it_behaves_like 'worker with data consistency',
described_class,
data_consistency: :sticky
it_behaves_like 'worker with data consistency', described_class, data_consistency: :sticky
end

View File

@ -9,8 +9,7 @@ RSpec.describe Ci::JobArtifacts::TrackArtifactReportWorker, feature_category: :c
let_it_be(:user) { create(:user) }
let_it_be(:pipeline) do
create(:ci_pipeline, :with_test_reports, :with_coverage_reports,
project: project, user: user)
create(:ci_pipeline, :with_test_reports, :with_coverage_reports, project: project, user: user)
end
subject(:perform) { described_class.new.perform(pipeline_id) }

View File

@ -73,9 +73,11 @@ RSpec.describe WorkerContext, feature_category: :shared do
describe '.bulk_perform_async_with_contexts' do
subject do
worker.bulk_perform_async_with_contexts(%w(hello world),
context_proc: -> (_) { { user: build_stubbed(:user) } },
arguments_proc: -> (word) { word })
worker.bulk_perform_async_with_contexts(
%w(hello world),
context_proc: -> (_) { { user: build_stubbed(:user) } },
arguments_proc: -> (word) { word }
)
end
it 'calls bulk_perform_async with the arguments' do
@ -89,10 +91,12 @@ RSpec.describe WorkerContext, feature_category: :shared do
describe '.bulk_perform_in_with_contexts' do
subject do
worker.bulk_perform_in_with_contexts(10.minutes,
%w(hello world),
context_proc: -> (_) { { user: build_stubbed(:user) } },
arguments_proc: -> (word) { word })
worker.bulk_perform_in_with_contexts(
10.minutes,
%w(hello world),
context_proc: -> (_) { { user: build_stubbed(:user) } },
arguments_proc: -> (word) { word }
)
end
it 'calls bulk_perform_in with the arguments and delay' do

View File

@ -60,8 +60,6 @@ RSpec.describe Deployments::HooksWorker, feature_category: :continuous_delivery
worker.perform(deployment_id: deployment.id, status_changed_at: status_changed_at)
end
it_behaves_like 'worker with data consistency',
described_class,
data_consistency: :delayed
it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
end
end

View File

@ -57,9 +57,11 @@ RSpec.describe DesignManagement::NewVersionWorker, feature_category: :design_man
context 'the version includes multiple types of action' do
let_it_be(:version) do
create(:design_version, :with_lfs_file,
created_designs: create_list(:design, 1, :with_lfs_file),
modified_designs: create_list(:design, 1))
create(
:design_version, :with_lfs_file,
created_designs: create_list(:design, 1, :with_lfs_file),
modified_designs: create_list(:design, 1)
)
end
it 'creates two system notes' do

View File

@ -493,7 +493,7 @@ RSpec.describe 'Every Sidekiq worker', feature_category: :shared do
it 'uses specified numbers of retries for workers with exceptions encoded here', :aggregate_failures do
retry_exception_workers.each do |worker|
expect(worker.retries).to eq(retry_exceptions[worker.klass.to_s]),
"#{worker.klass} has #{worker.retries} retries, expected #{retry_exceptions[worker.klass]}"
"#{worker.klass} has #{worker.retries} retries, expected #{retry_exceptions[worker.klass]}"
end
end
end

View File

@ -88,10 +88,11 @@ RSpec.describe Integrations::IrkerWorker, '#perform', feature_category: :integra
context 'with new commits to existing branch' do
it 'sends a correct message with a compare url' do
compare_url = Gitlab::Routing.url_helpers
.project_compare_url(project,
from: Commit.truncate_sha(push_data[:before]),
to: Commit.truncate_sha(push_data[:after]))
compare_url = Gitlab::Routing.url_helpers.project_compare_url(
project,
from: Commit.truncate_sha(push_data[:before]),
to: Commit.truncate_sha(push_data[:after])
)
message = "pushed #{push_data['total_commits_count']} " \
"new commits to master: #{compare_url}"

View File

@ -5,9 +5,7 @@ require 'spec_helper'
RSpec.describe JiraConnect::SyncBranchWorker, feature_category: :integrations do
include AfterNextHelpers
it_behaves_like 'worker with data consistency',
described_class,
data_consistency: :delayed
it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
describe '#perform' do
let_it_be(:group) { create(:group) }

View File

@ -5,9 +5,7 @@ require 'spec_helper'
RSpec.describe ::JiraConnect::SyncBuildsWorker, feature_category: :integrations do
include AfterNextHelpers
it_behaves_like 'worker with data consistency',
described_class,
data_consistency: :delayed
it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
describe '#perform' do
let_it_be(:pipeline) { create(:ci_pipeline) }

View File

@ -5,9 +5,7 @@ require 'spec_helper'
RSpec.describe ::JiraConnect::SyncDeploymentsWorker, feature_category: :integrations do
include AfterNextHelpers
it_behaves_like 'worker with data consistency',
described_class,
data_consistency: :delayed
it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
describe '#perform' do
let_it_be(:deployment) { create(:deployment) }

View File

@ -5,9 +5,7 @@ require 'spec_helper'
RSpec.describe ::JiraConnect::SyncFeatureFlagsWorker, feature_category: :integrations do
include AfterNextHelpers
it_behaves_like 'worker with data consistency',
described_class,
data_consistency: :delayed
it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
describe '#perform' do
let_it_be(:feature_flag) { create(:operations_feature_flag) }

View File

@ -5,9 +5,7 @@ require 'spec_helper'
RSpec.describe JiraConnect::SyncMergeRequestWorker, feature_category: :integrations do
include AfterNextHelpers
it_behaves_like 'worker with data consistency',
described_class,
data_consistency: :delayed
it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
describe '#perform' do
let_it_be(:group) { create(:group) }

View File

@ -5,9 +5,7 @@ require 'spec_helper'
RSpec.describe JiraConnect::SyncProjectWorker, factory_default: :keep, feature_category: :integrations do
include AfterNextHelpers
it_behaves_like 'worker with data consistency',
described_class,
data_consistency: :delayed
it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
describe '#perform' do
let_it_be(:project) { create_default(:project).freeze }

View File

@ -12,8 +12,11 @@ RSpec.describe MergeRequests::DeleteSourceBranchWorker, feature_category: :sourc
describe '#perform' do
before do
allow_next_instance_of(::Projects::DeleteBranchWorker) do |instance|
allow(instance).to receive(:perform).with(merge_request.source_project.id, user.id,
merge_request.source_branch)
allow(instance).to receive(:perform).with(
merge_request.source_project.id,
user.id,
merge_request.source_branch
)
end
end
@ -36,8 +39,11 @@ RSpec.describe MergeRequests::DeleteSourceBranchWorker, feature_category: :sourc
context 'with existing user and merge request' do
it 'calls delete branch worker' do
expect_next_instance_of(::Projects::DeleteBranchWorker) do |instance|
expect(instance).to receive(:perform).with(merge_request.source_project.id, user.id,
merge_request.source_branch)
expect(instance).to receive(:perform).with(
merge_request.source_project.id,
user.id,
merge_request.source_branch
)
end
worker.perform(merge_request.id, sha, user.id)

View File

@ -74,9 +74,12 @@ RSpec.describe MergeRequests::UpdateHeadPipelineWorker, feature_category: :code_
context 'when there is no pipeline for source branch' do
it "does not update merge request head pipeline" do
merge_request = create(:merge_request, source_branch: 'feature',
target_branch: "branch_1",
source_project: project)
merge_request = create(
:merge_request,
source_branch: 'feature',
target_branch: "branch_1",
source_project: project
)
subject
@ -96,10 +99,13 @@ RSpec.describe MergeRequests::UpdateHeadPipelineWorker, feature_category: :code_
end
it 'updates head pipeline for merge request' do
merge_request = create(:merge_request, source_branch: 'feature',
target_branch: "master",
source_project: project,
target_project: target_project)
merge_request = create(
:merge_request,
source_branch: 'feature',
target_branch: "master",
source_project: project,
target_project: target_project
)
subject
@ -109,9 +115,12 @@ RSpec.describe MergeRequests::UpdateHeadPipelineWorker, feature_category: :code_
context 'when the pipeline is not the latest for the branch' do
it 'does not update merge request head pipeline' do
merge_request = create(:merge_request, source_branch: 'master',
target_branch: "branch_1",
source_project: project)
merge_request = create(
:merge_request,
source_branch: 'master',
target_branch: "branch_1",
source_project: project
)
create(:ci_pipeline, project: pipeline.project, ref: pipeline.ref)
@ -127,9 +136,12 @@ RSpec.describe MergeRequests::UpdateHeadPipelineWorker, feature_category: :code_
end
it 'updates merge request head pipeline reference' do
merge_request = create(:merge_request, source_branch: 'master',
target_branch: 'feature',
source_project: project)
merge_request = create(
:merge_request,
source_branch: 'master',
target_branch: 'feature',
source_project: project
)
subject

View File

@ -90,9 +90,7 @@ RSpec.describe Namespaces::RootStatisticsWorker, '#perform', feature_category: :
end
end
it_behaves_like 'worker with data consistency',
described_class,
data_consistency: :sticky
it_behaves_like 'worker with data consistency', described_class, data_consistency: :sticky
it 'has the `until_executed` deduplicate strategy' do
expect(described_class.get_deduplicate_strategy).to eq(:until_executed)

View File

@ -16,9 +16,13 @@ RSpec.describe ObjectPool::DestroyWorker, feature_category: :shared do
subject { described_class.new }
it 'requests Gitaly to remove the object pool' do
expect(Gitlab::GitalyClient).to receive(:call)
.with(pool.shard_name, :object_pool_service, :delete_object_pool,
Object, timeout: Gitlab::GitalyClient.long_timeout)
expect(Gitlab::GitalyClient).to receive(:call).with(
pool.shard_name,
:object_pool_service,
:delete_object_pool,
Object,
timeout: Gitlab::GitalyClient.long_timeout
)
subject.perform(pool.id)
end

View File

@ -37,7 +37,5 @@ RSpec.describe PipelineHooksWorker, feature_category: :continuous_integration do
end
end
it_behaves_like 'worker with data consistency',
described_class,
data_consistency: :delayed
it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
end

View File

@ -6,19 +6,19 @@ RSpec.describe PipelineMetricsWorker, feature_category: :continuous_integration
let(:project) { create(:project, :repository) }
let!(:merge_request) do
create(:merge_request, source_project: project,
source_branch: pipeline.ref,
head_pipeline: pipeline)
create(:merge_request, source_project: project, source_branch: pipeline.ref, head_pipeline: pipeline)
end
let(:pipeline) do
create(:ci_empty_pipeline,
status: status,
project: project,
ref: 'master',
sha: project.repository.commit('master').id,
started_at: 1.hour.ago,
finished_at: Time.current)
create(
:ci_empty_pipeline,
status: status,
project: project,
ref: 'master',
sha: project.repository.commit('master').id,
started_at: 1.hour.ago,
finished_at: Time.current
)
end
let(:status) { 'pending' }

View File

@ -82,11 +82,13 @@ RSpec.describe ProcessCommitWorker, feature_category: :source_code_management do
context 'when commit is a merge request merge commit to the default branch' do
let(:merge_request) do
create(:merge_request,
description: "Closes #{issue.to_reference}",
source_branch: 'feature-merged',
target_branch: 'master',
source_project: project)
create(
:merge_request,
description: "Closes #{issue.to_reference}",
source_branch: 'feature-merged',
target_branch: 'master',
source_project: project
)
end
let(:commit) do

View File

@ -92,8 +92,11 @@ RSpec.describe Projects::InactiveProjectsDeletionCronWorker, feature_category: :
it 'invokes Projects::InactiveProjectsDeletionNotificationWorker for inactive projects' do
Gitlab::Redis::SharedState.with do |redis|
expect(redis).to receive(:hset).with('inactive_projects_deletion_warning_email_notified',
"project:#{inactive_large_project.id}", Date.current)
expect(redis).to receive(:hset).with(
'inactive_projects_deletion_warning_email_notified',
"project:#{inactive_large_project.id}",
Date.current
)
end
expect(::Projects::InactiveProjectsDeletionNotificationWorker).to receive(:perform_async).with(
inactive_large_project.id, deletion_date).and_call_original
@ -104,8 +107,11 @@ RSpec.describe Projects::InactiveProjectsDeletionCronWorker, feature_category: :
it 'does not invoke InactiveProjectsDeletionNotificationWorker for already notified inactive projects' do
Gitlab::Redis::SharedState.with do |redis|
redis.hset('inactive_projects_deletion_warning_email_notified', "project:#{inactive_large_project.id}",
Date.current.to_s)
redis.hset(
'inactive_projects_deletion_warning_email_notified',
"project:#{inactive_large_project.id}",
Date.current.to_s
)
end
expect(::Projects::InactiveProjectsDeletionNotificationWorker).not_to receive(:perform_async)
@ -116,8 +122,11 @@ RSpec.describe Projects::InactiveProjectsDeletionCronWorker, feature_category: :
it 'invokes Projects::DestroyService for projects that are inactive even after being notified' do
Gitlab::Redis::SharedState.with do |redis|
redis.hset('inactive_projects_deletion_warning_email_notified', "project:#{inactive_large_project.id}",
15.months.ago.to_date.to_s)
redis.hset(
'inactive_projects_deletion_warning_email_notified',
"project:#{inactive_large_project.id}",
15.months.ago.to_date.to_s
)
end
expect(::Projects::InactiveProjectsDeletionNotificationWorker).not_to receive(:perform_async)
@ -129,8 +138,9 @@ RSpec.describe Projects::InactiveProjectsDeletionCronWorker, feature_category: :
expect(inactive_large_project.reload.pending_delete).to eq(true)
Gitlab::Redis::SharedState.with do |redis|
expect(redis.hget('inactive_projects_deletion_warning_email_notified',
"project:#{inactive_large_project.id}")).to be_nil
expect(
redis.hget('inactive_projects_deletion_warning_email_notified', "project:#{inactive_large_project.id}")
).to be_nil
end
end

View File

@ -22,14 +22,15 @@ RSpec.describe Projects::InactiveProjectsDeletionNotificationWorker, feature_cat
worker.perform(project.id, deletion_date)
Gitlab::Redis::SharedState.with do |redis|
expect(redis.hget('inactive_projects_deletion_warning_email_notified',
"project:#{project.id}")).to eq(Date.current.to_s)
expect(
redis.hget('inactive_projects_deletion_warning_email_notified', "project:#{project.id}")
).to eq(Date.current.to_s)
end
end
it 'rescues and logs the exception if project does not exist' do
expect(Gitlab::ErrorTracking).to receive(:log_exception).with(instance_of(ActiveRecord::RecordNotFound),
{ project_id: non_existing_project_id })
expect(Gitlab::ErrorTracking).to receive(:log_exception)
.with(instance_of(ActiveRecord::RecordNotFound), { project_id: non_existing_project_id })
worker.perform(non_existing_project_id, deletion_date)
end

View File

@ -10,11 +10,13 @@ RSpec.describe RebaseWorker, '#perform', feature_category: :source_code_manageme
let(:forked_project) { fork_project(upstream_project, nil, repository: true) }
let(:merge_request) do
create(:merge_request,
source_project: forked_project,
source_branch: 'feature_conflict',
target_project: upstream_project,
target_branch: 'master')
create(
:merge_request,
source_project: forked_project,
source_branch: 'feature_conflict',
target_project: upstream_project,
target_branch: 'master'
)
end
it 'sets the correct project for running hooks' do

View File

@ -30,8 +30,10 @@ RSpec.describe RemoteMirrorNotificationWorker, :mailer, feature_category: :sourc
end
it 'does nothing when a notification has already been sent' do
mirror.update_columns(last_error: "There was a problem fetching",
error_notification_sent: true)
mirror.update_columns(
last_error: "There was a problem fetching",
error_notification_sent: true
)
expect(NotificationService).not_to receive(:new)

View File

@ -35,8 +35,10 @@ RSpec.describe RemoveExpiredMembersWorker, feature_category: :system_access do
new_job = Sidekiq::Worker.jobs.last
expect(new_job).to include('meta.project' => expired_project_member.project.full_path,
'meta.user' => expired_project_member.user.username)
expect(new_job).to include(
'meta.project' => expired_project_member.project.full_path,
'meta.user' => expired_project_member.user.username
)
end
end
@ -60,8 +62,7 @@ RSpec.describe RemoveExpiredMembersWorker, feature_category: :system_access do
worker.perform
expect(
Users::GhostUserMigration.where(user: expired_project_bot,
initiator_user: nil)
Users::GhostUserMigration.where(user: expired_project_bot, initiator_user: nil)
).to be_exists
end
end
@ -116,8 +117,10 @@ RSpec.describe RemoveExpiredMembersWorker, feature_category: :system_access do
new_job = Sidekiq::Worker.jobs.last
expect(new_job).to include('meta.root_namespace' => expired_group_member.group.full_path,
'meta.user' => expired_group_member.user.username)
expect(new_job).to include(
'meta.root_namespace' => expired_group_member.group.full_path,
'meta.user' => expired_group_member.user.username
)
end
end

View File

@ -13,15 +13,19 @@ RSpec.describe RemoveUnacceptedMemberInvitesWorker, feature_category: :system_ac
it 'removes unaccepted members', :aggregate_failures do
unaccepted_group_invitee = create(
:group_member, invite_token: 't0ken',
invite_email: 'group_invitee@example.com',
user: nil,
created_at: Time.current - 5.days)
:group_member,
invite_token: 't0ken',
invite_email: 'group_invitee@example.com',
user: nil,
created_at: Time.current - 5.days
)
unaccepted_project_invitee = create(
:project_member, invite_token: 't0ken',
invite_email: 'project_invitee@example.com',
user: nil,
created_at: Time.current - 5.days)
:project_member,
invite_token: 't0ken',
invite_email: 'project_invitee@example.com',
user: nil,
created_at: Time.current - 5.days
)
expect { worker.perform }.to change { Member.count }.by(-2)
@ -33,13 +37,17 @@ RSpec.describe RemoveUnacceptedMemberInvitesWorker, feature_category: :system_ac
context 'invited members still within expiration threshold' do
it 'leaves invited members', :aggregate_failures do
group_invitee = create(
:group_member, invite_token: 't0ken',
invite_email: 'group_invitee@example.com',
user: nil)
:group_member,
invite_token: 't0ken',
invite_email: 'group_invitee@example.com',
user: nil
)
project_invitee = create(
:project_member, invite_token: 't0ken',
invite_email: 'project_invitee@example.com',
user: nil)
:project_member,
invite_token: 't0ken',
invite_email: 'project_invitee@example.com',
user: nil
)
expect { worker.perform }.not_to change { Member.count }
@ -56,15 +64,19 @@ RSpec.describe RemoveUnacceptedMemberInvitesWorker, feature_category: :system_ac
it 'leaves accepted members', :aggregate_failures do
user = create(:user)
accepted_group_invitee = create(
:group_member, invite_token: 't0ken',
invite_email: 'group_invitee@example.com',
user: user,
created_at: Time.current - 5.days)
:group_member,
invite_token: 't0ken',
invite_email: 'group_invitee@example.com',
user: user,
created_at: Time.current - 5.days
)
accepted_project_invitee = create(
:project_member, invite_token: nil,
invite_email: 'project_invitee@example.com',
user: user,
created_at: Time.current - 5.days)
:project_member,
invite_token: nil,
invite_email: 'project_invitee@example.com',
user: user,
created_at: Time.current - 5.days
)
expect { worker.perform }.not_to change { Member.count }

View File

@ -13,24 +13,16 @@ RSpec.describe RemoveUnreferencedLfsObjectsWorker, feature_category: :source_cod
let!(:referenced_lfs_object1) { create(:lfs_object, oid: '3' * 64) }
let!(:referenced_lfs_object2) { create(:lfs_object, oid: '4' * 64) }
let!(:lfs_objects_project1_1) do
create(:lfs_objects_project,
project: project1,
lfs_object: referenced_lfs_object1
create(:lfs_objects_project, project: project1, lfs_object: referenced_lfs_object1
)
end
let!(:lfs_objects_project2_1) do
create(:lfs_objects_project,
project: project2,
lfs_object: referenced_lfs_object1
)
create(:lfs_objects_project, project: project2, lfs_object: referenced_lfs_object1)
end
let!(:lfs_objects_project1_2) do
create(:lfs_objects_project,
project: project1,
lfs_object: referenced_lfs_object2
)
create(:lfs_objects_project, project: project1, lfs_object: referenced_lfs_object2)
end
it 'removes unreferenced lfs objects' do

View File

@ -57,14 +57,16 @@ RSpec.describe RepositoryUpdateRemoteMirrorWorker, :clean_gitlab_redis_shared_st
end
it 'retries 3 times for the worker to finish before rescheduling' do
expect(subject).to receive(:in_lock)
.with("#{described_class.name}:#{remote_mirror.id}",
retries: 3,
ttl: remote_mirror.max_runtime,
sleep_sec: described_class::LOCK_WAIT_TIME)
.and_raise(Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError)
expect(described_class).to receive(:perform_in)
.with(remote_mirror.backoff_delay, remote_mirror.id, scheduled_time, 0)
expect(subject).to receive(:in_lock).with(
"#{described_class.name}:#{remote_mirror.id}",
retries: 3,
ttl: remote_mirror.max_runtime,
sleep_sec: described_class::LOCK_WAIT_TIME
).and_raise(Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError)
expect(described_class)
.to receive(:perform_in)
.with(remote_mirror.backoff_delay, remote_mirror.id, scheduled_time, 0)
subject.perform(remote_mirror.id, scheduled_time)
end

View File

@ -137,9 +137,11 @@ RSpec.describe RunPipelineScheduleWorker, feature_category: :continuous_integrat
expect(Gitlab::ErrorTracking)
.to receive(:track_and_raise_for_dev_exception)
.with(ActiveRecord::StatementInvalid,
issue_url: 'https://gitlab.com/gitlab-org/gitlab-foss/issues/41231',
schedule_id: pipeline_schedule.id).once
.with(
ActiveRecord::StatementInvalid,
issue_url: 'https://gitlab.com/gitlab-org/gitlab-foss/issues/41231',
schedule_id: pipeline_schedule.id
).once
end
it 'increments Prometheus counter' do

View File

@ -66,11 +66,13 @@ RSpec.describe UpdateHeadPipelineForMergeRequestWorker, feature_category: :conti
context 'when a merge request pipeline exists' do
let_it_be(:merge_request_pipeline) do
create(:ci_pipeline,
project: project,
source: :merge_request_event,
sha: latest_sha,
merge_request: merge_request)
create(
:ci_pipeline,
project: project,
source: :merge_request_event,
sha: latest_sha,
merge_request: merge_request
)
end
it 'sets the merge request pipeline as the head pipeline' do

View File

@ -28,8 +28,6 @@ RSpec.describe WebHookWorker, feature_category: :integrations do
.to change { Gitlab::WebHooks::RecursionDetection::UUID.instance.request_uuid }.to(uuid)
end
it_behaves_like 'worker with data consistency',
described_class,
data_consistency: :delayed
it_behaves_like 'worker with data consistency', described_class, data_consistency: :delayed
end
end