diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index 1c20838c039..65dd93aed65 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -7397b0e1c1a4a8fc0290347da1ddf7ac11547a18 +e02759b6d805b0eadfeba21a67bec6de75f9a750 diff --git a/app/models/namespace/aggregation_schedule.rb b/app/models/namespace/aggregation_schedule.rb index ed61c807519..72f5ab11060 100644 --- a/app/models/namespace/aggregation_schedule.rb +++ b/app/models/namespace/aggregation_schedule.rb @@ -6,13 +6,20 @@ class Namespace::AggregationSchedule < ApplicationRecord self.primary_key = :namespace_id - DEFAULT_LEASE_TIMEOUT = 1.5.hours.to_i REDIS_SHARED_KEY = 'gitlab:update_namespace_statistics_delay' belongs_to :namespace after_create :schedule_root_storage_statistics + def self.default_lease_timeout + if Feature.enabled?(:remove_namespace_aggregator_delay) + 1.hour.to_i + else + 1.5.hours.to_i + end + end + def schedule_root_storage_statistics run_after_commit_or_now do try_obtain_lease do @@ -20,7 +27,7 @@ class Namespace::AggregationSchedule < ApplicationRecord .perform_async(namespace_id) Namespaces::RootStatisticsWorker - .perform_in(DEFAULT_LEASE_TIMEOUT, namespace_id) + .perform_in(self.class.default_lease_timeout, namespace_id) end end end @@ -29,7 +36,7 @@ class Namespace::AggregationSchedule < ApplicationRecord # Used by ExclusiveLeaseGuard def lease_timeout - DEFAULT_LEASE_TIMEOUT + self.class.default_lease_timeout end # Used by ExclusiveLeaseGuard diff --git a/config/feature_flags/development/remove_namespace_aggregator_delay.yml b/config/feature_flags/development/remove_namespace_aggregator_delay.yml new file mode 100644 index 00000000000..e9e0268fb55 --- /dev/null +++ b/config/feature_flags/development/remove_namespace_aggregator_delay.yml @@ -0,0 +1,8 @@ +--- +name: remove_namespace_aggregator_delay +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/99226 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/375722 +milestone: '15.5' +type: development +group: group::utilization +default_enabled: false diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md index 5aa62d2f803..1f183431d3d 100644 --- a/doc/user/application_security/dependency_scanning/index.md +++ b/doc/user/application_security/dependency_scanning/index.md @@ -896,7 +896,7 @@ include: merge cyclonedx sboms: stage: merge-cyclonedx-sboms image: - name: cyclonedx/cyclonedx-cli:0.22.0 + name: cyclonedx/cyclonedx-cli:0.24.0 entrypoint: [""] script: - find . -name "gl-sbom-*.cdx.json" -exec /cyclonedx merge --output-file gl-sbom-all.cdx.json --input-files "{}" + diff --git a/lib/gitlab/ci/yaml_processor/result.rb b/lib/gitlab/ci/yaml_processor/result.rb index f203f88442d..c0097cd84de 100644 --- a/lib/gitlab/ci/yaml_processor/result.rb +++ b/lib/gitlab/ci/yaml_processor/result.rb @@ -32,18 +32,12 @@ module Gitlab end end - def stage_builds_attributes(stage) - jobs.values - .select { |job| job[:stage] == stage } - .map { |job| build_attributes(job[:name]) } - end - def workflow_rules @workflow_rules ||= @ci_config.workflow_rules end def root_variables - @root_variables ||= transform_to_array(variables) + @root_variables ||= transform_to_array(@ci_config.variables) end def jobs @@ -58,6 +52,38 @@ module Gitlab @included_templates ||= @ci_config.included_templates end + def variables_with_data + @ci_config.variables_with_data + end + + def yaml_variables_for(job_name) + job = jobs[job_name] + + return [] unless job + + Gitlab::Ci::Variables::Helpers.inherit_yaml_variables( + from: root_variables, + to: job[:job_variables], + inheritance: job.fetch(:root_variables_inheritance, true) + ) + end + + def stage_for(job_name) + jobs.dig(job_name, :stage) + end + + def config_metadata + @ci_config&.metadata || {} + end + + private + + def stage_builds_attributes(stage) + jobs.values + .select { |job| job[:stage] == stage } + .map { |job| build_attributes(job[:name]) } + end + def build_attributes(name) job = jobs.fetch(name.to_sym, {}) @@ -103,36 +129,6 @@ module Gitlab }.compact }.compact end - def variables_with_data - @ci_config.variables_with_data - end - - def yaml_variables_for(job_name) - job = jobs[job_name] - - return [] unless job - - Gitlab::Ci::Variables::Helpers.inherit_yaml_variables( - from: root_variables, - to: job[:job_variables], - inheritance: job.fetch(:root_variables_inheritance, true) - ) - end - - def stage_for(job_name) - jobs.dig(job_name, :stage) - end - - def config_metadata - @ci_config&.metadata || {} - end - - private - - def variables - @variables ||= @ci_config.variables - end - def release(job) job[:release] end diff --git a/qa/lib/gitlab/page/group/settings/usage_quota.stub.rb b/qa/lib/gitlab/page/group/settings/usage_quota.stub.rb index 192e71e6c90..2a5d9a6bb5e 100644 --- a/qa/lib/gitlab/page/group/settings/usage_quota.stub.rb +++ b/qa/lib/gitlab/page/group/settings/usage_quota.stub.rb @@ -5,51 +5,51 @@ module Gitlab module Group module Settings module UsageQuota - # @note Defined as +link :pipeline_tab+ - # Clicks +pipeline_tab+ - def pipeline_tab + # @note Defined as +link :seats_tab+ + # Clicks +seats_tab+ + def seats_tab # This is a stub, used for indexing. The method is dynamically generated. end # @example # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| - # expect(usage_quota.pipeline_tab_element).to exist + # expect(usage_quota.seats_tab_element).to exist # end # @return [Watir::Link] The raw +Link+ element - def pipeline_tab_element + def seats_tab_element # This is a stub, used for indexing. The method is dynamically generated. end # @example # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| - # expect(usage_quota).to be_pipeline_tab + # expect(usage_quota).to be_seats_tab # end - # @return [Boolean] true if the +pipeline_tab+ element is present on the page - def pipeline_tab? + # @return [Boolean] true if the +seats_tab+ element is present on the page + def seats_tab? # This is a stub, used for indexing. The method is dynamically generated. end - # @note Defined as +link :storage_tab+ - # Clicks +storage_tab+ - def storage_tab + # @note Defined as +link :pipelines_tab+ + # Clicks +pipelines_tab+ + def pipelines_tab # This is a stub, used for indexing. The method is dynamically generated. end # @example # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| - # expect(usage_quota.storage_tab_element).to exist + # expect(usage_quota.pipelines_tab_element).to exist # end # @return [Watir::Link] The raw +Link+ element - def storage_tab_element + def pipelines_tab_element # This is a stub, used for indexing. The method is dynamically generated. end # @example # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| - # expect(usage_quota).to be_storage_tab + # expect(usage_quota).to be_pipelines_tab # end - # @return [Boolean] true if the +storage_tab+ element is present on the page - def storage_tab? + # @return [Boolean] true if the +pipelines_tab+ element is present on the page + def pipelines_tab? # This is a stub, used for indexing. The method is dynamically generated. end @@ -77,6 +77,102 @@ module Gitlab # This is a stub, used for indexing. The method is dynamically generated. end + # @note Defined as +div :plan_ci_minutes+ + # @return [String] The text content or value of +plan_ci_minutes+ + def plan_ci_minutes + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota.plan_ci_minutes_element).to exist + # end + # @return [Watir::Div] The raw +Div+ element + def plan_ci_minutes_element + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota).to be_plan_ci_minutes + # end + # @return [Boolean] true if the +plan_ci_minutes+ element is present on the page + def plan_ci_minutes? + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @note Defined as +div :additional_ci_minutes+ + # @return [String] The text content or value of +additional_ci_minutes+ + def additional_ci_minutes + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota.additional_ci_minutes_element).to exist + # end + # @return [Watir::Div] The raw +Div+ element + def additional_ci_minutes_element + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota).to be_additional_ci_minutes + # end + # @return [Boolean] true if the +additional_ci_minutes+ element is present on the page + def additional_ci_minutes? + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @note Defined as +div :ci_purchase_successful_alert+ + # @return [String] The text content or value of +ci_purchase_successful_alert+ + def ci_purchase_successful_alert + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota.ci_purchase_successful_alert_element).to exist + # end + # @return [Watir::Div] The raw +Div+ element + def ci_purchase_successful_alert_element + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota).to be_ci_purchase_successful_alert + # end + # @return [Boolean] true if the +ci_purchase_successful_alert+ element is present on the page + def ci_purchase_successful_alert? + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @note Defined as +link :storage_tab+ + # Clicks +storage_tab+ + def storage_tab + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota.storage_tab_element).to exist + # end + # @return [Watir::Link] The raw +Link+ element + def storage_tab_element + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota).to be_storage_tab + # end + # @return [Boolean] true if the +storage_tab+ element is present on the page + def storage_tab? + # This is a stub, used for indexing. The method is dynamically generated. + end + # @note Defined as +link :buy_storage+ # Clicks +buy_storage+ def buy_storage @@ -101,123 +197,315 @@ module Gitlab # This is a stub, used for indexing. The method is dynamically generated. end - # @note Defined as +strong :additional_minutes+ - # @return [String] The text content or value of +additional_minutes+ - def additional_minutes + # @note Defined as +div :used_storage_message+ + # @return [String] The text content or value of +used_storage_message+ + def used_storage_message # This is a stub, used for indexing. The method is dynamically generated. end # @example # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| - # expect(usage_quota.additional_minutes_element).to exist - # end - # @return [Watir::Strong] The raw +Strong+ element - def additional_minutes_element - # This is a stub, used for indexing. The method is dynamically generated. - end - - # @example - # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| - # expect(usage_quota).to be_additional_minutes - # end - # @return [Boolean] true if the +additional_minutes+ element is present on the page - def additional_minutes? - # This is a stub, used for indexing. The method is dynamically generated. - end - - # @note Defined as +div :additional_minutes_usage+ - # @return [String] The text content or value of +additional_minutes_usage+ - def additional_minutes_usage - # This is a stub, used for indexing. The method is dynamically generated. - end - - # @example - # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| - # expect(usage_quota.additional_minutes_usage_element).to exist + # expect(usage_quota.used_storage_message_element).to exist # end # @return [Watir::Div] The raw +Div+ element - def additional_minutes_usage_element + def used_storage_message_element # This is a stub, used for indexing. The method is dynamically generated. end # @example # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| - # expect(usage_quota).to be_additional_minutes_usage + # expect(usage_quota).to be_used_storage_message # end - # @return [Boolean] true if the +additional_minutes_usage+ element is present on the page - def additional_minutes_usage? + # @return [Boolean] true if the +used_storage_message+ element is present on the page + def used_storage_message? # This is a stub, used for indexing. The method is dynamically generated. end - # @note Defined as +strong :plan_minutes+ - # @return [String] The text content or value of +plan_minutes+ - def plan_minutes + # @note Defined as +div :group_usage_message+ + # @return [String] The text content or value of +group_usage_message+ + def group_usage_message # This is a stub, used for indexing. The method is dynamically generated. end # @example # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| - # expect(usage_quota.plan_minutes_element).to exist - # end - # @return [Watir::Strong] The raw +Strong+ element - def plan_minutes_element - # This is a stub, used for indexing. The method is dynamically generated. - end - - # @example - # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| - # expect(usage_quota).to be_plan_minutes - # end - # @return [Boolean] true if the +plan_minutes+ element is present on the page - def plan_minutes? - # This is a stub, used for indexing. The method is dynamically generated. - end - - # @note Defined as +div :plan_minutes_usage+ - # @return [String] The text content or value of +plan_minutes_usage+ - def plan_minutes_usage - # This is a stub, used for indexing. The method is dynamically generated. - end - - # @example - # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| - # expect(usage_quota.plan_minutes_usage_element).to exist + # expect(usage_quota.group_usage_message_element).to exist # end # @return [Watir::Div] The raw +Div+ element - def plan_minutes_usage_element + def group_usage_message_element # This is a stub, used for indexing. The method is dynamically generated. end # @example # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| - # expect(usage_quota).to be_plan_minutes_usage + # expect(usage_quota).to be_group_usage_message # end - # @return [Boolean] true if the +plan_minutes_usage+ element is present on the page - def plan_minutes_usage? + # @return [Boolean] true if the +group_usage_message+ element is present on the page + def group_usage_message? # This is a stub, used for indexing. The method is dynamically generated. end - # @note Defined as +div :purchase_successful_alert+ - # @return [String] The text content or value of +purchase_successful_alert+ - def purchase_successful_alert + # @note Defined as +div :dependency_proxy_usage+ + # @return [String] The text content or value of +dependency_proxy_usage+ + def dependency_proxy_usage # This is a stub, used for indexing. The method is dynamically generated. end # @example # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| - # expect(usage_quota.purchase_successful_alert_element).to exist + # expect(usage_quota.dependency_proxy_usage_element).to exist # end # @return [Watir::Div] The raw +Div+ element - def purchase_successful_alert_element + def dependency_proxy_usage_element # This is a stub, used for indexing. The method is dynamically generated. end # @example # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| - # expect(usage_quota).to be_purchase_successful_alert + # expect(usage_quota).to be_dependency_proxy_usage # end - # @return [Boolean] true if the +purchase_successful_alert+ element is present on the page - def purchase_successful_alert? + # @return [Boolean] true if the +dependency_proxy_usage+ element is present on the page + def dependency_proxy_usage? + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @note Defined as +span :dependency_proxy_size+ + # @return [String] The text content or value of +dependency_proxy_size+ + def dependency_proxy_size + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota.dependency_proxy_size_element).to exist + # end + # @return [Watir::Span] The raw +Span+ element + def dependency_proxy_size_element + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota).to be_dependency_proxy_size + # end + # @return [Boolean] true if the +dependency_proxy_size+ element is present on the page + def dependency_proxy_size? + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @note Defined as +div :container_registry_usage+ + # @return [String] The text content or value of +container_registry_usage+ + def container_registry_usage + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota.container_registry_usage_element).to exist + # end + # @return [Watir::Div] The raw +Div+ element + def container_registry_usage_element + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota).to be_container_registry_usage + # end + # @return [Boolean] true if the +container_registry_usage+ element is present on the page + def container_registry_usage? + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @note Defined as +div :project_storage_used+ + # @return [String] The text content or value of +project_storage_used+ + def project_storage_used + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota.project_storage_used_element).to exist + # end + # @return [Watir::Div] The raw +Div+ element + def project_storage_used_element + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota).to be_project_storage_used + # end + # @return [Boolean] true if the +project_storage_used+ element is present on the page + def project_storage_used? + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @note Defined as +div :project+ + # @return [String] The text content or value of +project+ + def project + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota.project_element).to exist + # end + # @return [Watir::Div] The raw +Div+ element + def project_element + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota).to be_project + # end + # @return [Boolean] true if the +project+ element is present on the page + def project? + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @note Defined as +div :storage_type_legend+ + # @return [String] The text content or value of +storage_type_legend+ + def storage_type_legend + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota.storage_type_legend_element).to exist + # end + # @return [Watir::Div] The raw +Div+ element + def storage_type_legend_element + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota).to be_storage_type_legend + # end + # @return [Boolean] true if the +storage_type_legend+ element is present on the page + def storage_type_legend? + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @note Defined as +span :container_registry_size+ + # @return [String] The text content or value of +container_registry_size+ + def container_registry_size + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota.container_registry_size_element).to exist + # end + # @return [Watir::Span] The raw +Span+ element + def container_registry_size_element + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota).to be_container_registry_size + # end + # @return [Boolean] true if the +container_registry_size+ element is present on the page + def container_registry_size? + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @note Defined as +div :purchased_usage_total_free+ + # @return [String] The text content or value of +purchased_usage_total_free+ + def purchased_usage_total_free + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota.purchased_usage_total_free_element).to exist + # end + # @return [Watir::Div] The raw +Div+ element + def purchased_usage_total_free_element + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota).to be_purchased_usage_total_free + # end + # @return [Boolean] true if the +purchased_usage_total_free+ element is present on the page + def purchased_usage_total_free? + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @note Defined as +span :purchased_usage_total+ + # @return [String] The text content or value of +purchased_usage_total+ + def purchased_usage_total + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota.purchased_usage_total_element).to exist + # end + # @return [Watir::Span] The raw +Span+ element + def purchased_usage_total_element + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota).to be_purchased_usage_total + # end + # @return [Boolean] true if the +purchased_usage_total+ element is present on the page + def purchased_usage_total? + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @note Defined as +div :storage_purchase_successful_alert+ + # @return [String] The text content or value of +storage_purchase_successful_alert+ + def storage_purchase_successful_alert + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota.storage_purchase_successful_alert_element).to exist + # end + # @return [Watir::Div] The raw +Div+ element + def storage_purchase_successful_alert_element + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota).to be_storage_purchase_successful_alert + # end + # @return [Boolean] true if the +storage_purchase_successful_alert+ element is present on the page + def storage_purchase_successful_alert? + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @note Defined as +h2 :storage_available_alert+ + # @return [String] The text content or value of +storage_available_alert+ + def storage_available_alert + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota.storage_available_alert_element).to exist + # end + # @return [Watir::H2] The raw +H2+ element + def storage_available_alert_element + # This is a stub, used for indexing. The method is dynamically generated. + end + + # @example + # Gitlab::Page::Group::Settings::UsageQuota.perform do |usage_quota| + # expect(usage_quota).to be_storage_available_alert + # end + # @return [Boolean] true if the +storage_available_alert+ element is present on the page + def storage_available_alert? # This is a stub, used for indexing. The method is dynamically generated. end end diff --git a/qa/lib/gitlab/page/group/settings/usage_quotas.rb b/qa/lib/gitlab/page/group/settings/usage_quotas.rb index 596f9cd7748..a1ab345bf1e 100644 --- a/qa/lib/gitlab/page/group/settings/usage_quotas.rb +++ b/qa/lib/gitlab/page/group/settings/usage_quotas.rb @@ -5,15 +5,30 @@ module Gitlab module Group module Settings class UsageQuotas < Chemlab::Page + # Seats section + link :seats_tab + + # Pipelines section link :pipelines_tab - link :storage_tab link :buy_ci_minutes - link :purchase_more_storage div :plan_ci_minutes div :additional_ci_minutes - span :purchased_usage_total - div :purchased_usage_total_free, 'data-testid': 'purchased-usage-card' # Different UI for free namespace div :ci_purchase_successful_alert, text: /You have successfully purchased CI minutes/ + + # Storage section + link :storage_tab + link :purchase_more_storage + div :used_storage_message + div :group_usage_message + div :dependency_proxy_usage + span :dependency_proxy_size + div :container_registry_usage + div :project_storage_used + div :project + div :storage_type_legend + span :container_registry_size + div :purchased_usage_total_free # Different UI for free namespace + span :purchased_usage_total div :storage_purchase_successful_alert, text: /You have successfully purchased a storage/ h2 :storage_available_alert, text: /purchased storage is available/ @@ -34,6 +49,15 @@ module Gitlab false end + # Waits and Checks if storage project data loaded + # + # @return [Boolean] True if the alert presents, false if not after 5 second wait + def project_storage_data_available? + storage_type_legend_element.wait_until(timeout: 3, &:present?) + rescue Watir::Wait::TimeoutError + false + end + # Returns total purchased storage value once it's ready on page # # @return [Float] Total purchased storage value in GiB diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb index cbc83bcaee3..398f8b16f95 100644 --- a/spec/lib/gitlab/ci/yaml_processor_spec.rb +++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb @@ -15,8 +15,10 @@ module Gitlab end end - describe '#build_attributes' do - subject { described_class.new(config, user: nil).execute.build_attributes(:rspec) } + describe '#builds' do + subject(:builds) { described_class.new(config, user: nil).execute.builds } + + let(:rspec_build) { builds.find { |build| build[:name] == 'rspec' } } describe 'attributes list' do let(:config) do @@ -30,7 +32,7 @@ module Gitlab end it 'returns valid build attributes' do - expect(subject).to eq({ + expect(builds).to eq([{ stage: "test", stage_idx: 2, name: "rspec", @@ -45,7 +47,7 @@ module Gitlab job_variables: [], root_variables_inheritance: true, scheduling_type: :stage - }) + }]) end end @@ -63,7 +65,7 @@ module Gitlab end it 'returns valid build attributes' do - expect(subject).to eq({ + expect(builds).to eq([{ stage: 'test', stage_idx: 2, name: 'rspec', @@ -77,7 +79,7 @@ module Gitlab job_variables: [], root_variables_inheritance: true, scheduling_type: :stage - }) + }]) end end @@ -89,21 +91,22 @@ module Gitlab end it 'includes coverage regexp in build attributes' do - expect(subject) + expect(rspec_build) .to include(coverage_regex: 'Code coverage: \d+\.\d+') end end end describe 'tags entry with default values' do + let(:config) do + YAML.dump( + default: { tags: %w[A B] }, + rspec: { script: "rspec" } + ) + end + it 'applies default values' do - config = YAML.dump({ default: { tags: %w[A B] }, - rspec: { script: "rspec" } }) - - config_processor = Gitlab::Ci::YamlProcessor.new(config).execute - - expect(config_processor.stage_builds_attributes("test").size).to eq(1) - expect(config_processor.stage_builds_attributes("test").first).to eq({ + expect(rspec_build).to eq({ stage: "test", stage_idx: 2, name: "rspec", @@ -125,7 +128,7 @@ module Gitlab YAML.dump(rspec: { script: 'rspec', interruptible: true }) end - it { expect(subject[:interruptible]).to be_truthy } + it { expect(rspec_build[:interruptible]).to be_truthy } end describe 'interruptible job with default value' do @@ -133,7 +136,7 @@ module Gitlab YAML.dump(rspec: { script: 'rspec' }) end - it { expect(subject).not_to have_key(:interruptible) } + it { expect(rspec_build).not_to have_key(:interruptible) } end describe 'uninterruptible job' do @@ -141,7 +144,7 @@ module Gitlab YAML.dump(rspec: { script: 'rspec', interruptible: false }) end - it { expect(subject[:interruptible]).to be_falsy } + it { expect(rspec_build[:interruptible]).to be_falsy } end it "returns interruptible when overridden for job" do @@ -149,9 +152,10 @@ module Gitlab rspec: { script: "rspec" } }) config_processor = Gitlab::Ci::YamlProcessor.new(config).execute + builds = config_processor.builds.select { |b| b[:stage] == "test" } - expect(config_processor.stage_builds_attributes("test").size).to eq(1) - expect(config_processor.stage_builds_attributes("test").first).to eq({ + expect(builds.size).to eq(1) + expect(builds.first).to eq({ stage: "test", stage_idx: 2, name: "rspec", @@ -174,7 +178,7 @@ module Gitlab end it 'includes retry count in build options attribute' do - expect(subject[:options]).to include(retry: { max: 1 }) + expect(rspec_build[:options]).to include(retry: { max: 1 }) end end @@ -184,7 +188,7 @@ module Gitlab end it 'does not persist retry count in the database' do - expect(subject[:options]).not_to have_key(:retry) + expect(rspec_build[:options]).not_to have_key(:retry) end end @@ -195,7 +199,7 @@ module Gitlab end it 'does use the default value' do - expect(subject[:options]).to include(retry: { max: 1 }) + expect(rspec_build[:options]).to include(retry: { max: 1 }) end end @@ -206,7 +210,7 @@ module Gitlab end it 'does use the job value' do - expect(subject[:options]).to include(retry: { max: 2 }) + expect(rspec_build[:options]).to include(retry: { max: 2 }) end end end @@ -221,7 +225,7 @@ module Gitlab end it 'is not allowed to fail' do - expect(subject[:allow_failure]).to be false + expect(rspec_build[:allow_failure]).to be false end end @@ -232,7 +236,7 @@ module Gitlab end it 'is allowed to fail' do - expect(subject[:allow_failure]).to be true + expect(rspec_build[:allow_failure]).to be true end end @@ -244,11 +248,11 @@ module Gitlab end it 'is not allowed to fail' do - expect(subject[:allow_failure]).to be false + expect(rspec_build[:allow_failure]).to be false end it 'saves allow_failure_criteria into options' do - expect(subject[:options]).to match( + expect(rspec_build[:options]).to match( a_hash_including(allow_failure_criteria: { exit_codes: [1] })) end end @@ -262,7 +266,7 @@ module Gitlab end it 'is not allowed to fail' do - expect(subject[:allow_failure]).to be false + expect(rspec_build[:allow_failure]).to be false end end @@ -272,7 +276,7 @@ module Gitlab end it 'is not allowed to fail' do - expect(subject[:allow_failure]).to be false + expect(rspec_build[:allow_failure]).to be false end end @@ -283,11 +287,11 @@ module Gitlab end it 'is not allowed to fail' do - expect(subject[:allow_failure]).to be false + expect(rspec_build[:allow_failure]).to be false end it 'saves allow_failure_criteria into options' do - expect(subject[:options]).to match( + expect(rspec_build[:options]).to match( a_hash_including(allow_failure_criteria: { exit_codes: [1] })) end end @@ -305,8 +309,8 @@ module Gitlab end it 'has the attributes' do - expect(subject[:when]).to eq 'delayed' - expect(subject[:options][:start_in]).to eq '1 day' + expect(rspec_build[:when]).to eq 'delayed' + expect(rspec_build[:options][:start_in]).to eq '1 day' end end end @@ -321,7 +325,7 @@ module Gitlab end it 'has the attributes' do - expect(subject[:resource_group_key]).to eq 'iOS' + expect(rspec_build[:resource_group_key]).to eq 'iOS' end end end @@ -337,7 +341,7 @@ module Gitlab end it 'has the attributes' do - expect(subject[:options]).to eq( + expect(rspec_build[:options]).to eq( trigger: { project: 'namespace/project', branch: 'main' } ) end @@ -353,7 +357,7 @@ module Gitlab end it 'has the attributes' do - expect(subject[:options]).to eq( + expect(rspec_build[:options]).to eq( trigger: { project: 'namespace/project', forward: { pipeline_variables: true } } ) end @@ -682,7 +686,7 @@ module Gitlab let(:config_data) { YAML.dump(config) } let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config_data).execute } - subject { config_processor.stage_builds_attributes('test').first } + subject(:test_build) { config_processor.builds.find { |build| build[:name] == 'test' } } describe "before_script" do context "in global context" do @@ -850,9 +854,9 @@ module Gitlab rspec: { script: "rspec" } }) config_processor = Gitlab::Ci::YamlProcessor.new(config).execute + rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' } - expect(config_processor.stage_builds_attributes("test").size).to eq(1) - expect(config_processor.stage_builds_attributes("test").first).to eq({ + expect(rspec_build).to eq({ stage: "test", stage_idx: 2, name: "rspec", @@ -884,9 +888,9 @@ module Gitlab script: "rspec" } }) config_processor = Gitlab::Ci::YamlProcessor.new(config).execute + rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' } - expect(config_processor.stage_builds_attributes("test").size).to eq(1) - expect(config_processor.stage_builds_attributes("test").first).to eq({ + expect(rspec_build).to eq({ stage: "test", stage_idx: 2, name: "rspec", @@ -916,9 +920,9 @@ module Gitlab rspec: { script: "rspec" } }) config_processor = Gitlab::Ci::YamlProcessor.new(config).execute + rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' } - expect(config_processor.stage_builds_attributes("test").size).to eq(1) - expect(config_processor.stage_builds_attributes("test").first).to eq({ + expect(rspec_build).to eq({ stage: "test", stage_idx: 2, name: "rspec", @@ -944,9 +948,9 @@ module Gitlab rspec: { image: "image:1.0", services: ["postgresql", "docker:dind"], script: "rspec" } }) config_processor = Gitlab::Ci::YamlProcessor.new(config).execute + rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' } - expect(config_processor.stage_builds_attributes("test").size).to eq(1) - expect(config_processor.stage_builds_attributes("test").first).to eq({ + expect(rspec_build).to eq({ stage: "test", stage_idx: 2, name: "rspec", @@ -981,7 +985,7 @@ module Gitlab it { is_expected.to be_valid } it "returns with image" do - expect(processor.stage_builds_attributes("test")).to contain_exactly({ + expect(processor.builds).to contain_exactly({ stage: "test", stage_idx: 2, name: "test", @@ -1014,7 +1018,7 @@ module Gitlab it { is_expected.to be_valid } it "returns with service" do - expect(processor.stage_builds_attributes("test")).to contain_exactly({ + expect(processor.builds).to contain_exactly({ stage: "test", stage_idx: 2, name: "test", @@ -1362,7 +1366,7 @@ module Gitlab }) config_processor = Gitlab::Ci::YamlProcessor.new(config).execute - builds = config_processor.stage_builds_attributes("test") + builds = config_processor.builds expect(builds.size).to eq(1) expect(builds.first[:when]).to eq(when_state) @@ -1378,7 +1382,7 @@ module Gitlab end it 'creates one build and sets when:' do - builds = subject.stage_builds_attributes("test") + builds = processor.builds expect(builds.size).to eq(1) expect(builds.first[:when]).to eq('delayed') @@ -1406,7 +1410,7 @@ module Gitlab end let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config).execute } - let(:builds) { config_processor.stage_builds_attributes('test') } + let(:builds) { config_processor.builds } context 'when job is parallelized' do let(:parallel) { 5 } @@ -1522,9 +1526,9 @@ module Gitlab }) config_processor = Gitlab::Ci::YamlProcessor.new(config).execute + rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' } - expect(config_processor.stage_builds_attributes("test").size).to eq(1) - expect(config_processor.stage_builds_attributes("test").first[:cache]).to eq( + expect(rspec_build[:cache]).to eq( [ paths: ["logs/", "binaries/"], untracked: true, @@ -1546,9 +1550,9 @@ module Gitlab }) config_processor = Gitlab::Ci::YamlProcessor.new(config).execute + rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' } - expect(config_processor.stage_builds_attributes("test").size).to eq(1) - expect(config_processor.stage_builds_attributes("test").first[:cache]).to eq( + expect(rspec_build[:cache]).to eq( [ paths: ["logs/", "binaries/"], untracked: true, @@ -1571,9 +1575,9 @@ module Gitlab }) config_processor = Gitlab::Ci::YamlProcessor.new(config).execute + rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' } - expect(config_processor.stage_builds_attributes('test').size).to eq(1) - expect(config_processor.stage_builds_attributes('test').first[:cache]).to eq( + expect(rspec_build[:cache]).to eq( [ { paths: ['binaries/'], @@ -1606,9 +1610,9 @@ module Gitlab ) config_processor = Gitlab::Ci::YamlProcessor.new(config).execute + rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' } - expect(config_processor.stage_builds_attributes('test').size).to eq(1) - expect(config_processor.stage_builds_attributes('test').first[:cache]).to eq( + expect(rspec_build[:cache]).to eq( [ paths: ['binaries/'], untracked: true, @@ -1631,9 +1635,9 @@ module Gitlab ) config_processor = Gitlab::Ci::YamlProcessor.new(config).execute + rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' } - expect(config_processor.stage_builds_attributes('test').size).to eq(1) - expect(config_processor.stage_builds_attributes('test').first[:cache]).to eq( + expect(rspec_build[:cache]).to eq( [ paths: ['logs/', 'binaries/'], untracked: true, @@ -1654,9 +1658,9 @@ module Gitlab }) config_processor = Gitlab::Ci::YamlProcessor.new(config).execute + rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' } - expect(config_processor.stage_builds_attributes("test").size).to eq(1) - expect(config_processor.stage_builds_attributes("test").first[:cache]).to eq( + expect(rspec_build[:cache]).to eq( [ paths: ["test/"], untracked: false, @@ -1687,9 +1691,9 @@ module Gitlab }) config_processor = Gitlab::Ci::YamlProcessor.new(config).execute + rspec_build = config_processor.builds.find { |build| build[:name] == 'rspec' } - expect(config_processor.stage_builds_attributes("test").size).to eq(1) - expect(config_processor.stage_builds_attributes("test").first).to eq({ + expect(rspec_build).to eq({ stage: "test", stage_idx: 2, name: "rspec", @@ -1724,7 +1728,7 @@ module Gitlab }) config_processor = Gitlab::Ci::YamlProcessor.new(config).execute - builds = config_processor.stage_builds_attributes("test") + builds = config_processor.builds expect(builds.size).to eq(1) expect(builds.first[:options][:artifacts][:expire_in]).to eq('never') @@ -1740,7 +1744,7 @@ module Gitlab }) config_processor = Gitlab::Ci::YamlProcessor.new(config).execute - builds = config_processor.stage_builds_attributes("test") + builds = config_processor.builds expect(builds.size).to eq(1) expect(builds.first[:options][:artifacts][:when]).to eq(when_state) @@ -1773,7 +1777,7 @@ module Gitlab - my/test/something YAML - attributes = Gitlab::Ci::YamlProcessor.new(config).execute.build_attributes('test') + attributes = Gitlab::Ci::YamlProcessor.new(config).execute.builds.find { |build| build[:name] == 'test' } expect(attributes.dig(*%i[options artifacts exclude])).to eq(%w[my/test/something]) end @@ -1814,7 +1818,7 @@ module Gitlab end it "returns release info" do - expect(processor.stage_builds_attributes('release').first[:options]) + expect(processor.builds.first[:options]) .to eq(config[:release].except(:stage, :only)) end end @@ -1828,7 +1832,7 @@ module Gitlab subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute } - let(:builds) { subject.stage_builds_attributes('deploy') } + let(:builds) { subject.builds } context 'when a production environment is specified' do let(:environment) { 'production' } @@ -1938,7 +1942,7 @@ module Gitlab subject { Gitlab::Ci::YamlProcessor.new(YAML.dump(config)).execute } - let(:builds) { subject.stage_builds_attributes('deploy') } + let(:builds) { subject.builds } context 'when no timeout was provided' do it 'does not include job_timeout' do @@ -2365,8 +2369,8 @@ module Gitlab it 'returns a valid configuration and sets artifacts: true by default' do expect(subject).to be_valid - rspec = subject.build_attributes(:rspec) - expect(rspec.dig(:options, :cross_dependencies)).to eq( + rspec_build = subject.builds.find { |build| build[:name] == 'rspec' } + expect(rspec_build.dig(:options, :cross_dependencies)).to eq( [{ pipeline: '$THE_PIPELINE_ID', job: 'dependency-job', artifacts: true }] ) end @@ -2386,8 +2390,8 @@ module Gitlab it 'returns a valid configuration and sets artifacts: true by default' do expect(subject).to be_valid - rspec = subject.build_attributes(:rspec) - expect(rspec.dig(:options, :cross_dependencies)).to eq( + rspec_build = subject.builds.find { |build| build[:name] == 'rspec' } + expect(rspec_build.dig(:options, :cross_dependencies)).to eq( [{ pipeline: '123', job: 'dependency-job', artifacts: true }] ) end @@ -2417,7 +2421,7 @@ module Gitlab describe "Hidden jobs" do let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config).execute } - subject { config_processor.stage_builds_attributes("test") } + subject { config_processor.builds } shared_examples 'hidden_job_handling' do it "doesn't create jobs that start with dot" do @@ -2465,7 +2469,7 @@ module Gitlab describe "YAML Alias/Anchor" do let(:config_processor) { Gitlab::Ci::YamlProcessor.new(config).execute } - subject { config_processor.stage_builds_attributes("build") } + subject { config_processor.builds } shared_examples 'job_templates_handling' do it "is correctly supported for jobs" do diff --git a/spec/models/namespace/aggregation_schedule_spec.rb b/spec/models/namespace/aggregation_schedule_spec.rb index 38bf8089411..3f6a890654a 100644 --- a/spec/models/namespace/aggregation_schedule_spec.rb +++ b/spec/models/namespace/aggregation_schedule_spec.rb @@ -5,8 +5,24 @@ require 'spec_helper' RSpec.describe Namespace::AggregationSchedule, :clean_gitlab_redis_shared_state, type: :model do include ExclusiveLeaseHelpers + let(:default_timeout) { described_class.default_lease_timeout } + it { is_expected.to belong_to :namespace } + describe "#default_lease_timeout" do + subject(:default_lease_timeout) { default_timeout } + + it { is_expected.to eq 1.hour.to_i } + + context 'when remove_namespace_aggregator_delay FF is disabled' do + before do + stub_feature_flags(remove_namespace_aggregator_delay: false) + end + + it { is_expected.to eq 1.5.hours.to_i } + end + end + describe '#schedule_root_storage_statistics' do let(:namespace) { create(:namespace) } let(:aggregation_schedule) { namespace.build_aggregation_schedule } @@ -14,7 +30,7 @@ RSpec.describe Namespace::AggregationSchedule, :clean_gitlab_redis_shared_state, context "when we can't obtain the lease" do it 'does not schedule the workers' do - stub_exclusive_lease_taken(lease_key, timeout: described_class::DEFAULT_LEASE_TIMEOUT) + stub_exclusive_lease_taken(lease_key, timeout: default_timeout) expect(Namespaces::RootStatisticsWorker) .not_to receive(:perform_async) @@ -28,20 +44,20 @@ RSpec.describe Namespace::AggregationSchedule, :clean_gitlab_redis_shared_state, context 'when we can obtain the lease' do it 'schedules a root storage statistics after create' do - stub_exclusive_lease(lease_key, timeout: described_class::DEFAULT_LEASE_TIMEOUT) + stub_exclusive_lease(lease_key, timeout: default_timeout) expect(Namespaces::RootStatisticsWorker) .to receive(:perform_async).once expect(Namespaces::RootStatisticsWorker) .to receive(:perform_in).once - .with(described_class::DEFAULT_LEASE_TIMEOUT, aggregation_schedule.namespace_id) + .with(default_timeout, aggregation_schedule.namespace_id) aggregation_schedule.save! end it 'does not release the lease' do - stub_exclusive_lease(lease_key, timeout: described_class::DEFAULT_LEASE_TIMEOUT) + stub_exclusive_lease(lease_key, timeout: default_timeout) aggregation_schedule.save! @@ -58,7 +74,7 @@ RSpec.describe Namespace::AggregationSchedule, :clean_gitlab_redis_shared_state, expect(Namespaces::RootStatisticsWorker) .to receive(:perform_in).once - .with(described_class::DEFAULT_LEASE_TIMEOUT, aggregation_schedule.namespace_id) + .with(default_timeout, aggregation_schedule.namespace_id) .and_return(nil) # Scheduling workers for the first time diff --git a/spec/workers/namespaces/prune_aggregation_schedules_worker_spec.rb b/spec/workers/namespaces/prune_aggregation_schedules_worker_spec.rb index 11f2501cbe3..d8c60932d92 100644 --- a/spec/workers/namespaces/prune_aggregation_schedules_worker_spec.rb +++ b/spec/workers/namespaces/prune_aggregation_schedules_worker_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Namespaces::PruneAggregationSchedulesWorker, '#perform', :clean_g include ExclusiveLeaseHelpers let(:namespaces) { create_list(:namespace, 5, :with_aggregation_schedule) } - let(:timeout) { Namespace::AggregationSchedule::DEFAULT_LEASE_TIMEOUT } + let(:timeout) { Namespace::AggregationSchedule.default_lease_timeout } subject(:worker) { described_class.new } diff --git a/spec/workers/project_cache_worker_spec.rb b/spec/workers/project_cache_worker_spec.rb index 30c85464452..449b502a4ec 100644 --- a/spec/workers/project_cache_worker_spec.rb +++ b/spec/workers/project_cache_worker_spec.rb @@ -39,7 +39,7 @@ RSpec.describe ProjectCacheWorker do context 'with an existing project' do before do lease_key = "namespace:namespaces_root_statistics:#{project.namespace_id}" - stub_exclusive_lease_taken(lease_key, timeout: Namespace::AggregationSchedule::DEFAULT_LEASE_TIMEOUT) + stub_exclusive_lease_taken(lease_key, timeout: Namespace::AggregationSchedule.default_lease_timeout) end it 'refreshes the method caches' do