mirror of
https://github.com/gitlabhq/gitlabhq.git
synced 2025-07-21 23:37:47 +00:00
Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
@ -405,7 +405,10 @@ Gitlab/NamespacedClass:
|
||||
- 'app/policies/protected_branch_policy.rb'
|
||||
- 'app/policies/release_policy.rb'
|
||||
- 'app/policies/repository_policy.rb'
|
||||
- 'app/policies/resource_event_policy.rb'
|
||||
- 'app/policies/resource_label_event_policy.rb'
|
||||
- 'app/policies/resource_milestone_event_policy.rb'
|
||||
- 'app/policies/resource_state_event_policy.rb'
|
||||
- 'app/policies/suggestion_policy.rb'
|
||||
- 'app/policies/system_hook_policy.rb'
|
||||
- 'app/policies/timebox_policy.rb'
|
||||
@ -961,6 +964,8 @@ Gitlab/NamespacedClass:
|
||||
- 'ee/app/policies/issuable_metric_image_policy.rb'
|
||||
- 'ee/app/policies/iteration_policy.rb'
|
||||
- 'ee/app/policies/push_rule_policy.rb'
|
||||
- 'ee/app/policies/resource_iteration_event_policy.rb'
|
||||
- 'ee/app/policies/resource_weight_event_policy.rb'
|
||||
- 'ee/app/policies/saml_provider_policy.rb'
|
||||
- 'ee/app/policies/vulnerability_policy.rb'
|
||||
- 'ee/app/presenters/approval_rule_presenter.rb'
|
||||
|
@ -11,7 +11,7 @@ module MembershipActions
|
||||
.new(current_user, update_params)
|
||||
.execute(member)
|
||||
|
||||
member = result[:member]
|
||||
member = result[:members].first
|
||||
|
||||
member_data = if member.expires?
|
||||
{
|
||||
|
10
app/graphql/types/ci/runner_countable_connection_type.rb
Normal file
10
app/graphql/types/ci/runner_countable_connection_type.rb
Normal file
@ -0,0 +1,10 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Types
|
||||
module Ci
|
||||
# rubocop: disable Graphql/AuthorizeTypes
|
||||
class RunnerCountableConnectionType < ::Types::CountableConnectionType
|
||||
end
|
||||
# rubocop: enable Graphql/AuthorizeTypes
|
||||
end
|
||||
end
|
@ -6,7 +6,7 @@ module Types
|
||||
graphql_name 'CiRunner'
|
||||
|
||||
edge_type_class(RunnerWebUrlEdge)
|
||||
connection_type_class(Types::CountableConnectionType)
|
||||
connection_type_class(RunnerCountableConnectionType)
|
||||
|
||||
authorize :read_runner
|
||||
present_using ::Ci::RunnerPresenter
|
||||
|
5
app/policies/resource_event_policy.rb
Normal file
5
app/policies/resource_event_policy.rb
Normal file
@ -0,0 +1,5 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ResourceEventPolicy < BasePolicy
|
||||
condition(:can_read_issuable) { can?(:"read_#{@subject.issuable.to_ability_name}", @subject.issuable) }
|
||||
end
|
@ -1,8 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ResourceLabelEventPolicy < BasePolicy
|
||||
class ResourceLabelEventPolicy < ResourceEventPolicy
|
||||
condition(:can_read_label) { @subject.label_id.nil? || can?(:read_label, @subject.label) }
|
||||
condition(:can_read_issuable) { can?(:"read_#{@subject.issuable.to_ability_name}", @subject.issuable) }
|
||||
|
||||
rule { can_read_label }.policy do
|
||||
enable :read_label
|
||||
@ -10,5 +9,6 @@ class ResourceLabelEventPolicy < BasePolicy
|
||||
|
||||
rule { can_read_label & can_read_issuable }.policy do
|
||||
enable :read_resource_label_event
|
||||
enable :read_note
|
||||
end
|
||||
end
|
||||
|
14
app/policies/resource_milestone_event_policy.rb
Normal file
14
app/policies/resource_milestone_event_policy.rb
Normal file
@ -0,0 +1,14 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ResourceMilestoneEventPolicy < ResourceEventPolicy
|
||||
condition(:can_read_milestone) { @subject.milestone_id.nil? || can?(:read_milestone, @subject.milestone) }
|
||||
|
||||
rule { can_read_milestone }.policy do
|
||||
enable :read_milestone
|
||||
end
|
||||
|
||||
rule { can_read_milestone & can_read_issuable }.policy do
|
||||
enable :read_resource_milestone_event
|
||||
enable :read_note
|
||||
end
|
||||
end
|
10
app/policies/resource_state_event_policy.rb
Normal file
10
app/policies/resource_state_event_policy.rb
Normal file
@ -0,0 +1,10 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ResourceStateEventPolicy < ResourceEventPolicy
|
||||
condition(:can_read_issuable) { can?(:"read_#{@subject.issuable.to_ability_name}", @subject.issuable) }
|
||||
|
||||
rule { can_read_issuable }.policy do
|
||||
enable :read_resource_state_event
|
||||
enable :read_note
|
||||
end
|
||||
end
|
@ -11,10 +11,9 @@ module Members
|
||||
[member.id, { human_access: member.human_access, expires_at: member.expires_at }]
|
||||
end
|
||||
|
||||
if Feature.enabled?(:bulk_update_membership_roles, current_user)
|
||||
multiple_members_update(members, permission, old_access_level_expiry_map)
|
||||
else
|
||||
single_member_update(members.first, permission, old_access_level_expiry_map)
|
||||
updated_members = update_members(members, permission)
|
||||
Member.transaction do
|
||||
updated_members.each { |member| post_update(member, permission, old_access_level_expiry_map) }
|
||||
end
|
||||
|
||||
prepare_response(members)
|
||||
@ -22,35 +21,22 @@ module Members
|
||||
|
||||
private
|
||||
|
||||
def single_member_update(member, permission, old_access_level_expiry_map)
|
||||
def update_members(members, permission)
|
||||
# `filter_map` avoids the `post_update` call for the member that resulted in no change
|
||||
Member.transaction do
|
||||
members.filter_map { |member| update_member(member, permission) }
|
||||
end
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
[]
|
||||
end
|
||||
|
||||
def update_member(member, permission)
|
||||
raise Gitlab::Access::AccessDeniedError unless has_update_permissions?(member, permission)
|
||||
|
||||
member.attributes = params
|
||||
return success(member: member) unless member.changed?
|
||||
return unless member.changed?
|
||||
|
||||
post_update(member, permission, old_access_level_expiry_map) if member.save
|
||||
end
|
||||
|
||||
def multiple_members_update(members, permission, old_access_level_expiry_map)
|
||||
begin
|
||||
updated_members =
|
||||
Member.transaction do
|
||||
# Using `next` with `filter_map` avoids the `post_update` call for the member that resulted in no change
|
||||
members.filter_map do |member|
|
||||
raise Gitlab::Access::AccessDeniedError unless has_update_permissions?(member, permission)
|
||||
|
||||
member.attributes = params
|
||||
next unless member.changed?
|
||||
|
||||
member.save!
|
||||
member
|
||||
end
|
||||
end
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
return
|
||||
end
|
||||
|
||||
updated_members.each { |member| post_update(member, permission, old_access_level_expiry_map) }
|
||||
member.tap(&:save!)
|
||||
end
|
||||
|
||||
def post_update(member, permission, old_access_level_expiry_map)
|
||||
@ -62,18 +48,13 @@ module Members
|
||||
end
|
||||
|
||||
def prepare_response(members)
|
||||
errored_member = members.detect { |member| member.errors.any? }
|
||||
if errored_member.present?
|
||||
return error(errored_member.errors.full_messages.to_sentence, pass_back: { member: errored_member })
|
||||
errored_members = members.select { |member| member.errors.any? }
|
||||
if errored_members.present?
|
||||
error_message = errored_members.flat_map { |member| member.errors.full_messages }.uniq.to_sentence
|
||||
return error(error_message, pass_back: { members: errored_members })
|
||||
end
|
||||
|
||||
# TODO: Remove the :member key when removing the bulk_update_membership_roles FF and update where it's used.
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/373257
|
||||
if members.one?
|
||||
success(member: members.first)
|
||||
else
|
||||
success(members: members)
|
||||
end
|
||||
success(members: members)
|
||||
end
|
||||
|
||||
def has_update_permissions?(member, permission)
|
||||
|
@ -10,7 +10,7 @@ module Repositories
|
||||
class HousekeepingService < BaseService
|
||||
# Timeout set to 24h
|
||||
LEASE_TIMEOUT = 86400
|
||||
PACK_REFS_PERIOD = 6
|
||||
GC_PERIOD = 200
|
||||
|
||||
class LeaseTaken < StandardError
|
||||
def to_s
|
||||
@ -74,21 +74,13 @@ module Repositories
|
||||
|
||||
if pushes_since_gc % gc_period == 0
|
||||
:gc
|
||||
elsif pushes_since_gc % full_repack_period == 0
|
||||
:full_repack
|
||||
elsif pushes_since_gc % repack_period == 0
|
||||
:incremental_repack
|
||||
else
|
||||
:pack_refs
|
||||
:incremental_repack
|
||||
end
|
||||
end
|
||||
|
||||
def period_match?
|
||||
if Feature.enabled?(:optimized_housekeeping)
|
||||
pushes_since_gc % repack_period == 0
|
||||
else
|
||||
[gc_period, full_repack_period, repack_period, PACK_REFS_PERIOD].any? { |period| pushes_since_gc % period == 0 }
|
||||
end
|
||||
[gc_period, repack_period].any? { |period| pushes_since_gc % period == 0 }
|
||||
end
|
||||
|
||||
def housekeeping_enabled?
|
||||
@ -96,11 +88,7 @@ module Repositories
|
||||
end
|
||||
|
||||
def gc_period
|
||||
Gitlab::CurrentSettings.housekeeping_gc_period
|
||||
end
|
||||
|
||||
def full_repack_period
|
||||
Gitlab::CurrentSettings.housekeeping_full_repack_period
|
||||
GC_PERIOD
|
||||
end
|
||||
|
||||
def repack_period
|
||||
|
@ -19,33 +19,15 @@
|
||||
%h4= _("Housekeeping")
|
||||
.form-group
|
||||
- help_text = _("Run housekeeping tasks to automatically optimize Git repositories. Disabling this option will cause performance to degenerate over time.")
|
||||
- help_link = link_to _('Learn more.'), help_page_path('administration/housekeeping.md', anchor: 'configure-push-based-maintenance'), target: '_blank', rel: 'noopener noreferrer'
|
||||
- help_link = link_to _('Learn more.'), help_page_path('administration/housekeeping.md', anchor: 'heuristical-housekeeping'), target: '_blank', rel: 'noopener noreferrer'
|
||||
= f.gitlab_ui_checkbox_component :housekeeping_enabled,
|
||||
_("Enable automatic repository housekeeping"),
|
||||
help_text: '%{help_text} %{help_link}'.html_safe % { help_text: help_text, help_link: help_link }
|
||||
- if Feature.enabled?(:optimized_housekeeping)
|
||||
.form-group
|
||||
= f.label :housekeeping_incremental_repack_period, _('Optimize repository period'), class: 'label-bold'
|
||||
= f.number_field :housekeeping_incremental_repack_period, class: 'form-control gl-form-input'
|
||||
.form-text.text-muted
|
||||
= _('Number of Git pushes after which Gitaly is asked to optimize a repository.')
|
||||
- else
|
||||
.form-group
|
||||
= f.label :housekeeping_incremental_repack_period, 'Incremental repack period', class: 'label-bold'
|
||||
= f.number_field :housekeeping_incremental_repack_period, class: 'form-control gl-form-input'
|
||||
.form-text.text-muted
|
||||
= html_escape(s_('Number of Git pushes after which an incremental %{code_start}git repack%{code_end} is run.')) % { code_start: '<code>'.html_safe, code_end: '</code>'.html_safe }
|
||||
.form-group
|
||||
= f.label :housekeeping_full_repack_period, 'Full repack period', class: 'label-bold'
|
||||
= f.number_field :housekeeping_full_repack_period, class: 'form-control gl-form-input'
|
||||
.form-text.text-muted
|
||||
= html_escape(s_('Number of Git pushes after which a full %{code_start}git repack%{code_end} is run.')) % { code_start: '<code>'.html_safe, code_end: '</code>'.html_safe }
|
||||
.form-group
|
||||
= f.label :housekeeping_gc_period, _('Git GC period'), class: 'label-bold'
|
||||
= f.number_field :housekeeping_gc_period, class: 'form-control gl-form-input'
|
||||
.form-text.text-muted
|
||||
= html_escape(s_('Number of Git pushes after which %{code_start}git gc%{code_end} is run.')) % { code_start: '<code>'.html_safe, code_end: '</code>'.html_safe }
|
||||
|
||||
.form-group
|
||||
= f.label :housekeeping_incremental_repack_period, _('Optimize repository period'), class: 'label-bold'
|
||||
= f.number_field :housekeeping_incremental_repack_period, class: 'form-control gl-form-input'
|
||||
.form-text.text-muted
|
||||
= _('Number of Git pushes after which Gitaly is asked to optimize a repository.')
|
||||
.sub-section
|
||||
%h4= s_("AdminSettings|Inactive project deletion")
|
||||
.js-inactive-project-deletion-form{ data: inactive_projects_deletion_data(@application_setting) }
|
||||
|
@ -82,28 +82,12 @@ module GitGarbageCollectMethods
|
||||
|
||||
def gitaly_call(task, resource)
|
||||
repository = resource.repository.raw_repository
|
||||
client = repository.gitaly_repository_client
|
||||
|
||||
if Feature.enabled?(:optimized_housekeeping, container(resource))
|
||||
client = repository.gitaly_repository_client
|
||||
|
||||
if task == :prune
|
||||
client.prune_unreachable_objects
|
||||
else
|
||||
client.optimize_repository
|
||||
end
|
||||
if task == :prune
|
||||
client.prune_unreachable_objects
|
||||
else
|
||||
client = get_gitaly_client(task, repository)
|
||||
|
||||
case task
|
||||
when :prune, :gc
|
||||
client.garbage_collect(bitmaps_enabled?, prune: task == :prune)
|
||||
when :full_repack
|
||||
client.repack_full(bitmaps_enabled?)
|
||||
when :incremental_repack
|
||||
client.repack_incremental
|
||||
when :pack_refs
|
||||
client.pack_refs
|
||||
end
|
||||
client.optimize_repository
|
||||
end
|
||||
rescue GRPC::NotFound => e
|
||||
Gitlab::GitLogger.error("#{__method__} failed:\nRepository not found")
|
||||
@ -113,22 +97,6 @@ module GitGarbageCollectMethods
|
||||
raise Gitlab::Git::CommandError, e
|
||||
end
|
||||
|
||||
def get_gitaly_client(task, repository)
|
||||
if task == :pack_refs
|
||||
Gitlab::GitalyClient::RefService
|
||||
else
|
||||
Gitlab::GitalyClient::RepositoryService
|
||||
end.new(repository)
|
||||
end
|
||||
|
||||
# The option to enable/disable bitmaps has been removed in https://gitlab.com/gitlab-org/gitlab/-/issues/353777
|
||||
# Now the options is always enabled
|
||||
# This method and all the deprecated RPCs are going to be removed in
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/353779
|
||||
def bitmaps_enabled?
|
||||
true
|
||||
end
|
||||
|
||||
def flush_ref_caches(resource)
|
||||
resource.repository.expire_branches_cache
|
||||
resource.repository.branch_names
|
||||
@ -136,8 +104,6 @@ module GitGarbageCollectMethods
|
||||
end
|
||||
|
||||
def update_repository_statistics(resource, task)
|
||||
return if task == :pack_refs
|
||||
|
||||
resource.repository.expire_statistics_caches
|
||||
|
||||
return if Gitlab::Database.read_only? # GitGarbageCollectWorker may be run on a Geo secondary
|
||||
|
@ -7,12 +7,6 @@ module Projects
|
||||
|
||||
private
|
||||
|
||||
# Used for getting a project/group out of the resource in order to scope a feature flag
|
||||
# Can be removed within https://gitlab.com/gitlab-org/gitlab/-/issues/353607
|
||||
def container(resource)
|
||||
resource
|
||||
end
|
||||
|
||||
override :find_resource
|
||||
def find_resource(id)
|
||||
Project.find(id)
|
||||
|
@ -7,12 +7,6 @@ module Wikis
|
||||
|
||||
private
|
||||
|
||||
# Used for getting a project/group out of the resource in order to scope a feature flag
|
||||
# Can be removed within https://gitlab.com/gitlab-org/gitlab/-/issues/353607
|
||||
def container(resource)
|
||||
resource.container
|
||||
end
|
||||
|
||||
override :find_resource
|
||||
def find_resource(id)
|
||||
Project.find(id).wiki
|
||||
|
@ -1,8 +0,0 @@
|
||||
---
|
||||
name: bulk_update_membership_roles
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96745
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/373257
|
||||
milestone: '15.6'
|
||||
type: development
|
||||
group: group::workspace
|
||||
default_enabled: false
|
@ -1,8 +0,0 @@
|
||||
---
|
||||
name: optimized_housekeeping
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81465
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/353607
|
||||
milestone: '14.9'
|
||||
type: development
|
||||
group: group::source code
|
||||
default_enabled: true
|
@ -34,7 +34,7 @@ Gitaly can perform housekeeping tasks in a Git repository in two ways:
|
||||
|
||||
The "eager" housekeeping strategy executes housekeeping tasks in a repository
|
||||
independent of the repository state. This is the default strategy as used by the
|
||||
[manual trigger](#manual-trigger) and the [push-based trigger](#push-based-trigger).
|
||||
[manual trigger](#manual-trigger) and the push-based trigger.
|
||||
|
||||
The eager housekeeping strategy is controlled by the GitLab application.
|
||||
Depending on the trigger that caused the housekeeping job to run, GitLab asks
|
||||
@ -45,20 +45,14 @@ be slow.
|
||||
|
||||
### Heuristical housekeeping
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/2634) in GitLab 14.9 for the [manual trigger](#manual-trigger) and the [push-based trigger](#push-based-trigger) [with a flag](feature_flags.md) named `optimized_housekeeping`. Enabled by default.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/2634) in GitLab 14.9 for the [manual trigger](#manual-trigger) and the push-based trigger [with a flag](feature_flags.md) named `optimized_housekeeping`. Enabled by default.
|
||||
> - [Enabled on GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/issues/353607) in GitLab 14.10.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is available. To hide the feature, ask an administrator to [disable the feature flag](feature_flags.md) named `optimize_repository`.
|
||||
|
||||
To make it available, ask an administrator to [enable the feature flag](feature_flags.md) named `optimized_housekeeping`.
|
||||
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/107661) in GitLab 15.8. Feature flag `optimized_housekeeping` removed.
|
||||
|
||||
The heuristical (or "opportunistic") housekeeping strategy analyzes the
|
||||
repository's state and executes housekeeping tasks only when it finds one or
|
||||
more data structures are insufficiently optimized. This is the strategy used by
|
||||
[scheduled housekeeping](#scheduled-housekeeping). It can optionally be enabled
|
||||
for the [manual trigger](#manual-trigger) and the [push-based trigger](#push-based-trigger)
|
||||
by enabling the `optimized_housekeeping` feature flag.
|
||||
[scheduled housekeeping](#scheduled-housekeeping).
|
||||
|
||||
Heuristical housekeeping uses the following information to decide on the tasks
|
||||
it needs to run:
|
||||
@ -99,7 +93,7 @@ There are different ways in which GitLab runs housekeeping tasks:
|
||||
|
||||
- A project's administrator can [manually trigger](#manual-trigger) repository
|
||||
housekeeping tasks.
|
||||
- GitLab can automatically schedule housekeeping tasks [after a number of Git pushes](#push-based-trigger).
|
||||
- GitLab can automatically schedule housekeeping tasks after a number of Git pushes.
|
||||
- GitLab can [schedule a job](#scheduled-housekeeping) that runs housekeeping
|
||||
tasks for all repositories in a configurable time frame.
|
||||
|
||||
@ -120,65 +114,10 @@ To trigger housekeeping tasks manually:
|
||||
1. Select **Run housekeeping**.
|
||||
|
||||
This starts an asynchronous background worker for the project's repository. The
|
||||
background worker executes `git gc`, which performs a number of optimizations.
|
||||
|
||||
<!--- start_remove The following content will be removed on remove_date: '2023-04-22' -->
|
||||
|
||||
### Push-based trigger
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available and superseded by [heuristical housekeeping](#heuristical-housekeeping). It is planned to be removed in 15.8. To enable the feature, ask an administrator to [disable the feature flag](feature_flags.md) named `optimize_repository`.
|
||||
|
||||
GitLab automatically runs repository housekeeping tasks after a configured
|
||||
number of pushes:
|
||||
|
||||
- [`git gc`](https://git-scm.com/docs/git-gc) runs a number of housekeeping tasks such as:
|
||||
- Compressing Git objects to reduce disk space and increase performance.
|
||||
- Removing unreachable objects that may have been created from changes to the repository, like force-overwriting branches.
|
||||
- [`git repack`](https://git-scm.com/docs/git-repack) either:
|
||||
- Runs an incremental repack, according to a [configured period](#configure-push-based-maintenance). This
|
||||
packs all loose objects into a new packfile and prunes the now-redundant loose objects.
|
||||
- Runs a full repack, according to a [configured period](#configure-push-based-maintenance). This repacks all
|
||||
packfiles and loose objects into a single new packfile, and deletes the old now-redundant loose
|
||||
objects and packfiles. It also optionally creates bitmaps for the new packfile.
|
||||
- [`git pack-refs`](https://git-scm.com/docs/git-pack-refs) compresses references
|
||||
stored as loose files into a single file.
|
||||
|
||||
#### Configure push-based maintenance
|
||||
|
||||
You can change how often these tasks run when pushes occur, or you can turn
|
||||
them off entirely:
|
||||
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, select **Settings > Repository**.
|
||||
1. Expand **Repository maintenance**.
|
||||
1. In the **Housekeeping** section, configure the housekeeping options.
|
||||
1. Select **Save changes**.
|
||||
|
||||
The following housekeeping options are available:
|
||||
|
||||
- **Enable automatic repository housekeeping**: Regularly run housekeeping tasks. If you
|
||||
keep this setting disabled for a long time, Git repository access on your GitLab server becomes
|
||||
slower and your repositories use more disk space.
|
||||
- **Incremental repack period**: Number of Git pushes after which an incremental `git repack` is
|
||||
run.
|
||||
- **Full repack period**: Number of Git pushes after which a full `git repack` is run.
|
||||
- **Git GC period**: Number of Git pushes after which `git gc` is run.
|
||||
|
||||
As an example, see the following scenario:
|
||||
|
||||
- Incremental repack period: 10.
|
||||
- Full repack period: 50.
|
||||
- Git GC period: 200.
|
||||
|
||||
When the:
|
||||
|
||||
- `pushes_since_gc` value is 50, a `repack -A -l -d --pack-kept-objects` runs.
|
||||
- `pushes_since_gc` value is 200, a `git gc` runs.
|
||||
background worker asks Gitaly to perform a number of optimizations.
|
||||
|
||||
Housekeeping also [removes unreferenced LFS files](../raketasks/cleanup.md#remove-unreferenced-lfs-files)
|
||||
from your project on the same schedule as the `git gc` operation, freeing up storage space for your
|
||||
project.
|
||||
from your project every `200` push, freeing up storage space for your project.
|
||||
|
||||
### Scheduled housekeeping
|
||||
|
||||
|
@ -90,7 +90,7 @@ module API
|
||||
.new(current_user, update_params)
|
||||
.execute(invite)
|
||||
|
||||
updated_member = result[:member]
|
||||
updated_member = result[:members].first
|
||||
|
||||
if result[:status] == :success
|
||||
present_members updated_member
|
||||
|
@ -151,7 +151,7 @@ module API
|
||||
.new(current_user, declared_params(include_missing: false))
|
||||
.execute(member)
|
||||
|
||||
updated_member = result[:member]
|
||||
updated_member = result[:members].first
|
||||
|
||||
if result[:status] == :success
|
||||
present_members updated_member
|
||||
|
@ -153,7 +153,8 @@ module Gitlab
|
||||
job_finished_at = job_started_at + Random.rand(1..PIPELINE_FINISH_RANGE_MAX_IN_MINUTES).minutes
|
||||
end
|
||||
|
||||
# Do not use the first 2 runner tags
|
||||
# Do not use the first 2 runner tags ('runner-fleet', "#{registration_prefix}runner").
|
||||
# See Gitlab::Seeders::Ci::Runner::RunnerFleetSeeder#additional_runner_args
|
||||
tags = runner.tags.offset(2).sample(Random.rand(1..5)) # rubocop: disable CodeReuse/ActiveRecord
|
||||
|
||||
build_attrs = {
|
||||
|
@ -18416,9 +18416,6 @@ msgstr ""
|
||||
msgid "Git"
|
||||
msgstr ""
|
||||
|
||||
msgid "Git GC period"
|
||||
msgstr ""
|
||||
|
||||
msgid "Git LFS Rate Limits"
|
||||
msgstr ""
|
||||
|
||||
@ -28443,18 +28440,9 @@ msgstr ""
|
||||
msgid "Number of Elasticsearch shards and replicas per index:"
|
||||
msgstr ""
|
||||
|
||||
msgid "Number of Git pushes after which %{code_start}git gc%{code_end} is run."
|
||||
msgstr ""
|
||||
|
||||
msgid "Number of Git pushes after which Gitaly is asked to optimize a repository."
|
||||
msgstr ""
|
||||
|
||||
msgid "Number of Git pushes after which a full %{code_start}git repack%{code_end} is run."
|
||||
msgstr ""
|
||||
|
||||
msgid "Number of Git pushes after which an incremental %{code_start}git repack%{code_end} is run."
|
||||
msgstr ""
|
||||
|
||||
msgid "Number of LOCs per commit"
|
||||
msgstr ""
|
||||
|
||||
|
@ -6,27 +6,27 @@ module QA
|
||||
include ApprovalConfiguration
|
||||
|
||||
attr_accessor :approval_rules,
|
||||
:source_branch,
|
||||
:target_new_branch,
|
||||
:update_existing_file,
|
||||
:assignee,
|
||||
:milestone,
|
||||
:labels,
|
||||
:file_name,
|
||||
:file_content,
|
||||
:reviewer_ids
|
||||
:source_branch,
|
||||
:target_new_branch,
|
||||
:update_existing_file,
|
||||
:assignee,
|
||||
:milestone,
|
||||
:labels,
|
||||
:file_name,
|
||||
:file_content,
|
||||
:reviewer_ids
|
||||
|
||||
attr_writer :no_preparation,
|
||||
:wait_for_merge,
|
||||
:template
|
||||
:wait_for_merge,
|
||||
:template
|
||||
|
||||
attributes :iid,
|
||||
:title,
|
||||
:description,
|
||||
:merge_when_pipeline_succeeds,
|
||||
:merge_status,
|
||||
:state,
|
||||
:reviewers
|
||||
:title,
|
||||
:description,
|
||||
:merge_when_pipeline_succeeds,
|
||||
:merge_status,
|
||||
:state,
|
||||
:reviewers
|
||||
|
||||
attribute :project do
|
||||
Project.fabricate_via_api! do |resource|
|
||||
@ -143,6 +143,13 @@ module QA
|
||||
}
|
||||
end
|
||||
|
||||
# Get merge request reviews
|
||||
#
|
||||
# @return [Array<Hash>]
|
||||
def reviews
|
||||
parse_body(api_get_from(api_reviewers_path))
|
||||
end
|
||||
|
||||
def merge_via_api!
|
||||
Support::Waiter.wait_until(sleep_interval: 1) do
|
||||
QA::Runtime::Logger.debug("Waiting until merge request with id '#{iid}' can be merged")
|
||||
|
@ -30,15 +30,18 @@ module QA
|
||||
|
||||
def verify_status_data
|
||||
stats = imported_project.project_import_status.dig(:stats, :imported)
|
||||
expect(stats).to include(
|
||||
expect(stats).to eq(
|
||||
issue: 1,
|
||||
issue_event: 16,
|
||||
pull_request: 1,
|
||||
pull_request_review: 2,
|
||||
pull_request_review_request: 1,
|
||||
diff_note: 1,
|
||||
label: 9,
|
||||
milestone: 1,
|
||||
note: 3,
|
||||
pull_request: 1,
|
||||
pull_request_review: 1,
|
||||
diff_note: 1,
|
||||
release: 1
|
||||
release: 1,
|
||||
protected_branch: 2
|
||||
)
|
||||
end
|
||||
|
||||
@ -154,7 +157,10 @@ module QA
|
||||
[
|
||||
"*Created by: gitlab-qa-github*\n\n**Review:** Commented\n\nGood but needs some improvement",
|
||||
"*Created by: gitlab-qa-github*\n\n```suggestion:-0+0\nProject for GitHub import test to GitLab\r\n```",
|
||||
"*Created by: gitlab-qa-github*\n\nSome test PR comment"
|
||||
"*Created by: gitlab-qa-github*\n\nSome test PR comment",
|
||||
"*Created by: gitlab-qa*\n\n**Review:** Approved",
|
||||
"assigned to @#{user.username}",
|
||||
"requested review from @#{user.username}"
|
||||
]
|
||||
)
|
||||
expect(events).to match_array(
|
||||
@ -163,6 +169,19 @@ module QA
|
||||
{ name: "add_milestone", label: "0.0.1" }
|
||||
]
|
||||
)
|
||||
# TODO: reenable once https://gitlab.com/gitlab-org/gitlab/-/issues/386714 fixed
|
||||
# currently this doesn't work as expected if reviewer is not matched by public email
|
||||
# event for assigning approver is created with reviewer being user doing import but mr actually doesn't
|
||||
# contain reviewers or the approved state
|
||||
#
|
||||
# reviews = merge_request.reviews.map do |review|
|
||||
# {
|
||||
# id: review.dig(:user, :id),
|
||||
# username: review.dig(:user, :username),
|
||||
# state: review[:state]
|
||||
# }
|
||||
# end
|
||||
# expect(reviews).to eq([{ id: user.id, username: user.username, state: "approved" }])
|
||||
end
|
||||
|
||||
def verify_release_import
|
||||
@ -183,7 +202,7 @@ module QA
|
||||
# @param [QA::Resource::Issuable] issuable
|
||||
# @return [Array]
|
||||
def fetch_events_and_comments(issuable)
|
||||
comments = issuable.comments.map { |comment| comment[:body] }
|
||||
comments = issuable.comments.pluck(:body)
|
||||
events = [
|
||||
*issuable.label_events.map { |e| { name: "#{e[:action]}_label", label: e.dig(:label, :name) } },
|
||||
*issuable.state_events.map { |e| { name: e[:state] } },
|
||||
|
@ -86,12 +86,6 @@ module QA
|
||||
raise
|
||||
end.not_to raise_error
|
||||
end
|
||||
|
||||
after do
|
||||
parent_group_user.remove_via_api!
|
||||
sub_group_project.remove_via_api!
|
||||
sub_group.remove_via_api!
|
||||
end
|
||||
end
|
||||
|
||||
context 'when added to sub-group' do
|
||||
@ -167,12 +161,6 @@ module QA
|
||||
end.to raise_error(Resource::ApiFabricator::ResourceFabricationFailedError,
|
||||
/403 Forbidden - You are not allowed to push into this branch/)
|
||||
end
|
||||
|
||||
after do
|
||||
sub_group_user.remove_via_api!
|
||||
parent_group_project.remove_via_api!
|
||||
sub_group.remove_via_api!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -51,12 +51,6 @@ module QA
|
||||
expect(file_form).to have_element(:commit_button)
|
||||
end
|
||||
end
|
||||
|
||||
after do
|
||||
parent_group_user.remove_via_api!
|
||||
sub_group_project.remove_via_api!
|
||||
sub_group.remove_via_api!
|
||||
end
|
||||
end
|
||||
|
||||
context 'when added to sub-group' do
|
||||
@ -97,12 +91,6 @@ module QA
|
||||
|
||||
expect(page).to have_text("You can’t edit files directly in this project.")
|
||||
end
|
||||
|
||||
after do
|
||||
sub_group_user.remove_via_api!
|
||||
parent_group_project.remove_via_api!
|
||||
sub_group.remove_via_api!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -0,0 +1,11 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Types::Ci::RunnerCountableConnectionType, feature_category: :runner_fleet do
|
||||
it 'contains attributes related to a runner connection' do
|
||||
expected_fields = %w[count]
|
||||
|
||||
expect(described_class).to include_graphql_fields(*expected_fields)
|
||||
end
|
||||
end
|
@ -2,7 +2,7 @@
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ResourceLabelEventPolicy do
|
||||
RSpec.describe ResourceLabelEventPolicy, feature_category: :team_planning do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:project) { create(:project, :private) }
|
||||
let_it_be(:issue) { create(:issue, project: project) }
|
||||
|
73
spec/policies/resource_milestone_event_policy_spec.rb
Normal file
73
spec/policies/resource_milestone_event_policy_spec.rb
Normal file
@ -0,0 +1,73 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ResourceMilestoneEventPolicy, feature_category: :team_planning do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:group) { create(:group) }
|
||||
let_it_be(:project) { create(:project, :private) }
|
||||
let_it_be(:issue) { create(:issue, project: project) }
|
||||
let_it_be(:private_project) { create(:project, :private) }
|
||||
|
||||
describe '#read_resource_milestone_event' do
|
||||
context 'with non-member user' do
|
||||
it 'does not allow to read event' do
|
||||
event = build_event(project)
|
||||
|
||||
expect(permissions(user, event)).to be_disallowed(:read_milestone, :read_resource_milestone_event, :read_note)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with member user' do
|
||||
before do
|
||||
project.add_guest(user)
|
||||
end
|
||||
|
||||
it 'allows to read event for accessible milestone' do
|
||||
event = build_event(project)
|
||||
|
||||
expect(permissions(user, event)).to be_allowed(:read_milestone, :read_resource_milestone_event, :read_note)
|
||||
end
|
||||
|
||||
it 'does not allow to read event for not accessible milestone' do
|
||||
event = build_event(private_project)
|
||||
|
||||
expect(permissions(user, event)).to be_disallowed(:read_milestone, :read_resource_milestone_event, :read_note)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#read_milestone' do
|
||||
before do
|
||||
project.add_guest(user)
|
||||
end
|
||||
|
||||
it 'allows to read deleted milestone' do
|
||||
event = build(:resource_milestone_event, issue: issue, milestone: nil)
|
||||
|
||||
expect(permissions(user, event)).to be_allowed(:read_milestone, :read_resource_milestone_event, :read_note)
|
||||
end
|
||||
|
||||
it 'allows to read accessible milestone' do
|
||||
event = build_event(project)
|
||||
|
||||
expect(permissions(user, event)).to be_allowed(:read_milestone, :read_resource_milestone_event, :read_note)
|
||||
end
|
||||
|
||||
it 'does not allow to read not accessible milestone' do
|
||||
event = build_event(private_project)
|
||||
|
||||
expect(permissions(user, event)).to be_disallowed(:read_milestone, :read_resource_milestone_event, :read_note)
|
||||
end
|
||||
end
|
||||
|
||||
def build_event(project)
|
||||
milestone = create(:milestone, project: project)
|
||||
|
||||
build(:resource_milestone_event, issue: issue, milestone: milestone)
|
||||
end
|
||||
|
||||
def permissions(user, issue)
|
||||
described_class.new(user, issue)
|
||||
end
|
||||
end
|
39
spec/policies/resource_state_event_policy_spec.rb
Normal file
39
spec/policies/resource_state_event_policy_spec.rb
Normal file
@ -0,0 +1,39 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ResourceStateEventPolicy, feature_category: :team_planning do
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:project) { create(:project, :private) }
|
||||
let_it_be(:issue) { create(:issue, project: project) }
|
||||
|
||||
describe '#read_resource_state_event' do
|
||||
context 'with non-member user' do
|
||||
it 'does not allow to read event' do
|
||||
event = build_event(project)
|
||||
|
||||
expect(permissions(user, event)).to be_disallowed(:read_resource_state_event, :read_note)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with member user' do
|
||||
before do
|
||||
project.add_guest(user)
|
||||
end
|
||||
|
||||
it 'allows to read event for a state change' do
|
||||
event = build_event(project)
|
||||
|
||||
expect(permissions(user, event)).to be_allowed(:read_resource_state_event, :read_note)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def build_event(label_project)
|
||||
build(:resource_state_event, issue: issue, state: 2)
|
||||
end
|
||||
|
||||
def permissions(user, issue)
|
||||
described_class.new(user, issue)
|
||||
end
|
||||
end
|
@ -14,10 +14,7 @@ RSpec.describe Members::UpdateService do
|
||||
let(:members) { source.members_and_requesters.where(user_id: member_users).to_a }
|
||||
let(:update_service) { described_class.new(current_user, params) }
|
||||
let(:params) { { access_level: access_level } }
|
||||
let(:updated_members) do
|
||||
result = subject
|
||||
Array.wrap(result[:members] || result[:member])
|
||||
end
|
||||
let(:updated_members) { subject[:members] }
|
||||
|
||||
before do
|
||||
member_users.first.tap do |member_user|
|
||||
@ -255,40 +252,6 @@ RSpec.describe Members::UpdateService do
|
||||
end
|
||||
end
|
||||
|
||||
context 'when :bulk_update_membership_roles feature flag is disabled' do
|
||||
let(:member) { source.members_and_requesters.find_by!(user_id: member_user1.id) }
|
||||
let(:members) { [member] }
|
||||
|
||||
subject { update_service.execute(member, permission: permission) }
|
||||
|
||||
shared_examples 'a service returning an error' do
|
||||
before do
|
||||
allow(member).to receive(:save) do
|
||||
member.errors.add(:user_id)
|
||||
member.errors.add(:access_level)
|
||||
end
|
||||
.and_return(false)
|
||||
end
|
||||
|
||||
it_behaves_like 'returns error status when params are invalid'
|
||||
|
||||
it 'returns the error' do
|
||||
response = subject
|
||||
|
||||
expect(response[:status]).to eq(:error)
|
||||
expect(response[:message]).to eq('User is invalid and Access level is invalid')
|
||||
end
|
||||
end
|
||||
|
||||
before do
|
||||
stub_feature_flags(bulk_update_membership_roles: false)
|
||||
end
|
||||
|
||||
it_behaves_like 'current user cannot update the given members'
|
||||
it_behaves_like 'updating a project'
|
||||
it_behaves_like 'updating a group'
|
||||
end
|
||||
|
||||
subject { update_service.execute(members, permission: permission) }
|
||||
|
||||
shared_examples 'a service returning an error' do
|
||||
@ -326,15 +289,14 @@ RSpec.describe Members::UpdateService do
|
||||
it_behaves_like 'updating a group'
|
||||
|
||||
context 'with a single member' do
|
||||
let(:member) { create(:group_member, group: group) }
|
||||
let(:members) { member }
|
||||
let(:members) { create(:group_member, group: group) }
|
||||
|
||||
before do
|
||||
group.add_owner(current_user)
|
||||
end
|
||||
|
||||
it 'returns the correct response' do
|
||||
expect(subject[:member]).to eq(member)
|
||||
expect(subject[:members]).to contain_exactly(members)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -65,12 +65,9 @@ RSpec.shared_examples 'housekeeps repository' do
|
||||
# At push 200
|
||||
expect(resource.git_garbage_collect_worker_klass).to receive(:perform_async).with(resource.id, :gc, :the_lease_key, :the_uuid)
|
||||
.once
|
||||
# At push 50, 100, 150
|
||||
expect(resource.git_garbage_collect_worker_klass).to receive(:perform_async).with(resource.id, :full_repack, :the_lease_key, :the_uuid)
|
||||
.exactly(3).times
|
||||
# At push 10, 20, ... (except those above)
|
||||
# At push 10, 20, ... (except the gc call)
|
||||
expect(resource.git_garbage_collect_worker_klass).to receive(:perform_async).with(resource.id, :incremental_repack, :the_lease_key, :the_uuid)
|
||||
.exactly(16).times
|
||||
.exactly(19).times
|
||||
|
||||
201.times do
|
||||
subject.increment!
|
||||
@ -79,37 +76,6 @@ RSpec.shared_examples 'housekeeps repository' do
|
||||
|
||||
expect(resource.pushes_since_gc).to eq(1)
|
||||
end
|
||||
|
||||
context 'when optimized_repository feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(optimized_housekeeping: false)
|
||||
end
|
||||
|
||||
it 'calls also the garbage collect worker with pack_refs every 6 commits' do
|
||||
allow(subject).to receive(:try_obtain_lease).and_return(:the_uuid)
|
||||
allow(subject).to receive(:lease_key).and_return(:the_lease_key)
|
||||
|
||||
# At push 200
|
||||
expect(resource.git_garbage_collect_worker_klass).to receive(:perform_async).with(resource.id, :gc, :the_lease_key, :the_uuid)
|
||||
.once
|
||||
# At push 50, 100, 150
|
||||
expect(resource.git_garbage_collect_worker_klass).to receive(:perform_async).with(resource.id, :full_repack, :the_lease_key, :the_uuid)
|
||||
.exactly(3).times
|
||||
# At push 10, 20, ... (except those above)
|
||||
expect(resource.git_garbage_collect_worker_klass).to receive(:perform_async).with(resource.id, :incremental_repack, :the_lease_key, :the_uuid)
|
||||
.exactly(16).times
|
||||
# At push 6, 12, 18, ... (except those above)
|
||||
expect(resource.git_garbage_collect_worker_klass).to receive(:perform_async).with(resource.id, :pack_refs, :the_lease_key, :the_uuid)
|
||||
.exactly(27).times
|
||||
|
||||
201.times do
|
||||
subject.increment!
|
||||
subject.execute if subject.needed?
|
||||
end
|
||||
|
||||
expect(resource.pushes_since_gc).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'runs the task specifically requested' do
|
||||
@ -136,15 +102,11 @@ RSpec.shared_examples 'housekeeps repository' do
|
||||
expect(subject.needed?).to eq(true)
|
||||
end
|
||||
|
||||
context 'when optimized_housekeeping is disabled' do
|
||||
before do
|
||||
stub_feature_flags(optimized_housekeeping: false)
|
||||
end
|
||||
it 'when incremental repack period is not multiple of gc period' do
|
||||
allow(Gitlab::CurrentSettings).to receive(:housekeeping_incremental_repack_period).and_return(12)
|
||||
allow(resource).to receive(:pushes_since_gc).and_return(200)
|
||||
|
||||
it 'returns true pack refs is needed' do
|
||||
allow(resource).to receive(:pushes_since_gc).and_return(described_class::PACK_REFS_PERIOD)
|
||||
expect(subject.needed?).to eq(true)
|
||||
end
|
||||
expect(subject.needed?).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -24,19 +24,6 @@ RSpec.shared_examples 'can collect git garbage' do |update_statistics: true|
|
||||
|
||||
subject.perform(*params)
|
||||
end
|
||||
|
||||
context 'when optimized_housekeeping feature is disabled' do
|
||||
before do
|
||||
stub_feature_flags(optimized_housekeeping: false)
|
||||
end
|
||||
|
||||
specify do
|
||||
expect(subject).to receive(:get_gitaly_client).with(task, repository.raw_repository).and_return(repository_service)
|
||||
expect(repository_service).to receive(gitaly_task)
|
||||
|
||||
subject.perform(*params)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'it updates the resource statistics' do
|
||||
@ -91,20 +78,6 @@ RSpec.shared_examples 'can collect git garbage' do |update_statistics: true|
|
||||
|
||||
expect { subject.perform(*params) }.to raise_exception(Gitlab::Git::Repository::NoRepository)
|
||||
end
|
||||
|
||||
context 'when optimized_housekeeping feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(optimized_housekeeping: false)
|
||||
end
|
||||
|
||||
it 'handles gRPC errors' do
|
||||
allow_next_instance_of(Gitlab::GitalyClient::RepositoryService, repository.raw_repository) do |instance|
|
||||
allow(instance).to receive(:garbage_collect).and_raise(GRPC::NotFound)
|
||||
end
|
||||
|
||||
expect { subject.perform(*params) }.to raise_exception(Gitlab::Git::Repository::NoRepository)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with different lease than the active one' do
|
||||
@ -161,51 +134,6 @@ RSpec.shared_examples 'can collect git garbage' do |update_statistics: true|
|
||||
end
|
||||
end
|
||||
|
||||
context 'repack_full' do
|
||||
let(:task) { :full_repack }
|
||||
let(:gitaly_task) { :repack_full }
|
||||
|
||||
before do
|
||||
expect(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
|
||||
end
|
||||
|
||||
it_behaves_like 'it calls Gitaly'
|
||||
it_behaves_like 'it updates the resource statistics' if update_statistics
|
||||
end
|
||||
|
||||
context 'pack_refs' do
|
||||
let(:task) { :pack_refs }
|
||||
let(:gitaly_task) { :pack_refs }
|
||||
|
||||
before do
|
||||
expect(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
|
||||
end
|
||||
|
||||
it_behaves_like 'it calls Gitaly' do
|
||||
let(:repository_service) { instance_double(Gitlab::GitalyClient::RefService) }
|
||||
end
|
||||
|
||||
it 'does not update the resource statistics' do
|
||||
expect(statistics_service_klass).not_to receive(:new)
|
||||
|
||||
subject.perform(*params)
|
||||
end
|
||||
end
|
||||
|
||||
context 'repack_incremental' do
|
||||
let(:task) { :incremental_repack }
|
||||
let(:gitaly_task) { :repack_incremental }
|
||||
|
||||
before do
|
||||
expect(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
|
||||
|
||||
statistics_keys.delete(:repository_size)
|
||||
end
|
||||
|
||||
it_behaves_like 'it calls Gitaly'
|
||||
it_behaves_like 'it updates the resource statistics' if update_statistics
|
||||
end
|
||||
|
||||
context 'prune' do
|
||||
before do
|
||||
expect(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
|
||||
@ -219,41 +147,5 @@ RSpec.shared_examples 'can collect git garbage' do |update_statistics: true|
|
||||
subject.perform(resource.id, 'prune', lease_key, lease_uuid)
|
||||
end
|
||||
end
|
||||
|
||||
shared_examples 'gc tasks' do
|
||||
before do
|
||||
allow(subject).to receive(:get_lease_uuid).and_return(lease_uuid)
|
||||
allow(subject).to receive(:bitmaps_enabled?).and_return(bitmaps_enabled)
|
||||
|
||||
stub_feature_flags(optimized_housekeeping: false)
|
||||
end
|
||||
|
||||
it 'cleans up repository after finishing' do
|
||||
expect(resource).to receive(:cleanup).and_call_original
|
||||
|
||||
subject.perform(resource.id, 'gc', lease_key, lease_uuid)
|
||||
end
|
||||
|
||||
it 'prune calls garbage_collect with the option prune: true' do
|
||||
repository_service = instance_double(Gitlab::GitalyClient::RepositoryService)
|
||||
|
||||
expect(subject).to receive(:get_gitaly_client).with(:prune, repository.raw_repository).and_return(repository_service)
|
||||
expect(repository_service).to receive(:garbage_collect).with(bitmaps_enabled, prune: true)
|
||||
|
||||
subject.perform(resource.id, 'prune', lease_key, lease_uuid)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with bitmaps enabled' do
|
||||
let(:bitmaps_enabled) { true }
|
||||
|
||||
include_examples 'gc tasks'
|
||||
end
|
||||
|
||||
context 'with bitmaps disabled' do
|
||||
let(:bitmaps_enabled) { false }
|
||||
|
||||
include_examples 'gc tasks'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -41,27 +41,6 @@ RSpec.describe 'admin/application_settings/_repository_check.html.haml', feature
|
||||
|
||||
expect(rendered).to have_field('Enable automatic repository housekeeping')
|
||||
expect(rendered).to have_field('Optimize repository period')
|
||||
|
||||
# TODO: Remove it along with optimized_housekeeping feature flag
|
||||
expect(rendered).not_to have_field('Incremental repack period')
|
||||
expect(rendered).not_to have_field('Full repack period')
|
||||
expect(rendered).not_to have_field('Git GC period')
|
||||
end
|
||||
|
||||
context 'when optimized_housekeeping is disabled' do
|
||||
before do
|
||||
stub_feature_flags(optimized_housekeeping: false)
|
||||
end
|
||||
|
||||
it 'renders the correct setting subsection content' do
|
||||
render
|
||||
|
||||
expect(rendered).to have_field('Enable automatic repository housekeeping')
|
||||
expect(rendered).to have_field('Incremental repack period')
|
||||
expect(rendered).to have_field('Full repack period')
|
||||
expect(rendered).to have_field('Git GC period')
|
||||
expect(rendered).not_to have_field('Optimize repository period')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Projects::GitGarbageCollectWorker do
|
||||
RSpec.describe Projects::GitGarbageCollectWorker, feature_category: :source_code_management do
|
||||
let_it_be(:project) { create(:project, :repository) }
|
||||
|
||||
it_behaves_like 'can collect git garbage' do
|
||||
@ -24,8 +24,7 @@ RSpec.describe Projects::GitGarbageCollectWorker do
|
||||
end
|
||||
|
||||
context 'when the repository has joined a pool' do
|
||||
let!(:pool) { create(:pool_repository, :ready) }
|
||||
let(:project) { pool.source_project }
|
||||
let_it_be(:pool) { create(:pool_repository, :ready, source_project: project) }
|
||||
|
||||
it 'ensures the repositories are linked' do
|
||||
expect(project.pool_repository).to receive(:link_repository).once
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Wikis::GitGarbageCollectWorker do
|
||||
RSpec.describe Wikis::GitGarbageCollectWorker, feature_category: :source_code_management do
|
||||
it_behaves_like 'can collect git garbage' do
|
||||
let_it_be(:resource) { create(:project_wiki) }
|
||||
let_it_be(:page) { create(:wiki_page, wiki: resource) }
|
||||
|
Reference in New Issue
Block a user