From ae78b85a25cb0c19c3d6a2e4e6c7ca91ed50787d Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Mon, 24 Feb 2020 12:09:00 +0000 Subject: Add latest changes from gitlab-org/gitlab@master --- lib/api/entities/internal.rb | 19 ---- lib/api/entities/internal/pages/lookup_path.rb | 14 +++ lib/api/entities/internal/pages/virtual_domain.rb | 14 +++ .../entities/internal/serverless/lookup_path.rb | 13 +++ .../entities/internal/serverless/virtual_domain.rb | 14 +++ lib/api/internal/pages.rb | 23 ++++- lib/gitlab/ci/config/entry/bridge.rb | 90 +++--------------- lib/gitlab/ci/config/entry/job.rb | 102 ++++----------------- lib/gitlab/ci/config/entry/processable.rb | 102 +++++++++++++++++++++ lib/gitlab/ci/config/entry/root.rb | 4 +- lib/gitlab/config/entry/configurable.rb | 12 ++- lib/gitlab/danger/helper.rb | 3 + lib/gitlab/gon_helper.rb | 1 + lib/gitlab/import_export/members_mapper.rb | 12 ++- lib/gitlab/kubernetes/helm.rb | 2 +- lib/gitlab/reference_counter.rb | 55 ++++++++++- 16 files changed, 283 insertions(+), 197 deletions(-) delete mode 100644 lib/api/entities/internal.rb create mode 100644 lib/api/entities/internal/pages/lookup_path.rb create mode 100644 lib/api/entities/internal/pages/virtual_domain.rb create mode 100644 lib/api/entities/internal/serverless/lookup_path.rb create mode 100644 lib/api/entities/internal/serverless/virtual_domain.rb create mode 100644 lib/gitlab/ci/config/entry/processable.rb (limited to 'lib') diff --git a/lib/api/entities/internal.rb b/lib/api/entities/internal.rb deleted file mode 100644 index 8f79bd14833..00000000000 --- a/lib/api/entities/internal.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -module API - module Entities - module Internal - module Pages - class LookupPath < Grape::Entity - expose :project_id, :access_control, - :source, :https_only, :prefix - end - - class VirtualDomain < Grape::Entity - expose :certificate, :key - expose :lookup_paths, using: LookupPath - end - end - end - end -end diff --git a/lib/api/entities/internal/pages/lookup_path.rb b/lib/api/entities/internal/pages/lookup_path.rb new file mode 100644 index 00000000000..1bf94f74fb4 --- /dev/null +++ b/lib/api/entities/internal/pages/lookup_path.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module API + module Entities + module Internal + module Pages + class LookupPath < Grape::Entity + expose :project_id, :access_control, + :source, :https_only, :prefix + end + end + end + end +end diff --git a/lib/api/entities/internal/pages/virtual_domain.rb b/lib/api/entities/internal/pages/virtual_domain.rb new file mode 100644 index 00000000000..27eb7571368 --- /dev/null +++ b/lib/api/entities/internal/pages/virtual_domain.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module API + module Entities + module Internal + module Pages + class VirtualDomain < Grape::Entity + expose :certificate, :key + expose :lookup_paths, using: LookupPath + end + end + end + end +end diff --git a/lib/api/entities/internal/serverless/lookup_path.rb b/lib/api/entities/internal/serverless/lookup_path.rb new file mode 100644 index 00000000000..8ca40b4f128 --- /dev/null +++ b/lib/api/entities/internal/serverless/lookup_path.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module API + module Entities + module Internal + module Serverless + class LookupPath < Grape::Entity + expose :source + end + end + end + end +end diff --git a/lib/api/entities/internal/serverless/virtual_domain.rb b/lib/api/entities/internal/serverless/virtual_domain.rb new file mode 100644 index 00000000000..8b53aa51bf5 --- /dev/null +++ b/lib/api/entities/internal/serverless/virtual_domain.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module API + module Entities + module Internal + module Serverless + class VirtualDomain < Grape::Entity + expose :certificate, :key + expose :lookup_paths, using: LookupPath + end + end + end + end +end diff --git a/lib/api/internal/pages.rb b/lib/api/internal/pages.rb index a2fe3e09df8..e2e1351c939 100644 --- a/lib/api/internal/pages.rb +++ b/lib/api/internal/pages.rb @@ -24,13 +24,26 @@ module API requires :host, type: String, desc: 'The host to query for' end get "/" do - host = Namespace.find_by_pages_host(params[:host]) || PagesDomain.find_by_domain(params[:host]) - no_content! unless host + serverless_domain_finder = ServerlessDomainFinder.new(params[:host]) + if serverless_domain_finder.serverless? + # Handle Serverless domains + serverless_domain = serverless_domain_finder.execute + no_content! unless serverless_domain - virtual_domain = host.pages_virtual_domain - no_content! unless virtual_domain + virtual_domain = Serverless::VirtualDomain.new(serverless_domain) + no_content! unless virtual_domain - present virtual_domain, with: Entities::Internal::Pages::VirtualDomain + present virtual_domain, with: Entities::Internal::Serverless::VirtualDomain + else + # Handle Pages domains + host = Namespace.find_by_pages_host(params[:host]) || PagesDomain.find_by_domain(params[:host]) + no_content! unless host + + virtual_domain = host.pages_virtual_domain + no_content! unless virtual_domain + + present virtual_domain, with: Entities::Internal::Pages::VirtualDomain + end end end end diff --git a/lib/gitlab/ci/config/entry/bridge.rb b/lib/gitlab/ci/config/entry/bridge.rb index c0247dca73d..721c7c8b6d7 100644 --- a/lib/gitlab/ci/config/entry/bridge.rb +++ b/lib/gitlab/ci/config/entry/bridge.rb @@ -9,34 +9,21 @@ module Gitlab # defining a downstream project trigger. # class Bridge < ::Gitlab::Config::Entry::Node - include ::Gitlab::Config::Entry::Configurable - include ::Gitlab::Config::Entry::Attributable - include ::Gitlab::Config::Entry::Inheritable + include ::Gitlab::Ci::Config::Entry::Processable - ALLOWED_KEYS = %i[trigger stage allow_failure only except - when extends variables needs rules].freeze + ALLOWED_KEYS = %i[trigger allow_failure when variables needs].freeze validations do - validates :config, allowed_keys: ALLOWED_KEYS - validates :config, presence: true - validates :name, presence: true - validates :name, type: Symbol - validates :config, disallowed_keys: { - in: %i[only except when start_in], - message: 'key may not be used with `rules`' - }, - if: :has_rules? + validates :config, allowed_keys: ALLOWED_KEYS + PROCESSABLE_ALLOWED_KEYS with_options allow_nil: true do validates :when, inclusion: { in: %w[on_success on_failure always], message: 'should be on_success, on_failure or always' } - validates :extends, type: String - validates :rules, array_of_hashes: true end validate on: :composed do - unless trigger.present? || bridge_needs.present? + unless trigger_defined? || bridge_needs.present? errors.add(:config, 'should contain either a trigger or a needs:pipeline') end end @@ -58,32 +45,13 @@ module Gitlab inherit: false, metadata: { allowed_needs: %i[job bridge] } - entry :stage, ::Gitlab::Ci::Config::Entry::Stage, - description: 'Pipeline stage this job will be executed into.', - inherit: false - - entry :only, ::Gitlab::Ci::Config::Entry::Policy, - description: 'Refs policy this job will be executed for.', - default: ::Gitlab::Ci::Config::Entry::Policy::DEFAULT_ONLY, - inherit: false - - entry :except, ::Gitlab::Ci::Config::Entry::Policy, - description: 'Refs policy this job will be executed for.', - inherit: false - - entry :rules, ::Gitlab::Ci::Config::Entry::Rules, - description: 'List of evaluable Rules to determine job inclusion.', - inherit: false, - metadata: { - allowed_when: %w[on_success on_failure always never manual delayed].freeze - } - entry :variables, ::Gitlab::Ci::Config::Entry::Variables, description: 'Environment variables available for this job.', inherit: false - helpers(*ALLOWED_KEYS) - attributes(*ALLOWED_KEYS) + helpers :trigger, :needs, :variables + + attributes :when, :allow_failure def self.matching?(name, config) !name.to_s.start_with?('.') && @@ -95,56 +63,20 @@ module Gitlab true end - def compose!(deps = nil) - super do - has_workflow_rules = deps&.workflow&.has_rules? - - # If workflow:rules: or rules: are used - # they are considered not compatible - # with `only/except` defaults - # - # Context: https://gitlab.com/gitlab-org/gitlab/merge_requests/21742 - if has_rules? || has_workflow_rules - # Remove only/except defaults - # defaults are not considered as defined - @entries.delete(:only) unless only_defined? - @entries.delete(:except) unless except_defined? - end - end - end - - def has_rules? - @config&.key?(:rules) - end - - def name - @metadata[:name] - end - def value - { name: name, + super.merge( trigger: (trigger_value if trigger_defined?), needs: (needs_value if needs_defined?), ignore: !!allow_failure, - stage: stage_value, - when: when_value, - extends: extends_value, + when: self.when, variables: (variables_value if variables_defined?), - rules: (rules_value if has_rules?), - only: only_value, - except: except_value, - scheduling_type: needs_defined? && !bridge_needs ? :dag : :stage }.compact + scheduling_type: needs_defined? && !bridge_needs ? :dag : :stage + ).compact end def bridge_needs needs_value[:bridge] if needs_value end - - private - - def overwrite_entry(deps, key, current_entry) - deps.default[key] unless current_entry.specified? - end end end end diff --git a/lib/gitlab/ci/config/entry/job.rb b/lib/gitlab/ci/config/entry/job.rb index 666c6e23eb4..931f769e920 100644 --- a/lib/gitlab/ci/config/entry/job.rb +++ b/lib/gitlab/ci/config/entry/job.rb @@ -8,33 +8,21 @@ module Gitlab # Entry that represents a concrete CI/CD job. # class Job < ::Gitlab::Config::Entry::Node - include ::Gitlab::Config::Entry::Configurable - include ::Gitlab::Config::Entry::Attributable - include ::Gitlab::Config::Entry::Inheritable + include ::Gitlab::Ci::Config::Entry::Processable ALLOWED_WHEN = %w[on_success on_failure always manual delayed].freeze - ALLOWED_KEYS = %i[tags script only except rules type image services - allow_failure type stage when start_in artifacts cache + ALLOWED_KEYS = %i[tags script type image services + allow_failure type when start_in artifacts cache dependencies before_script needs after_script variables - environment coverage retry parallel extends interruptible timeout + environment coverage retry parallel interruptible timeout resource_group release].freeze REQUIRED_BY_NEEDS = %i[stage].freeze validations do - validates :config, type: Hash - validates :config, allowed_keys: ALLOWED_KEYS + validates :config, allowed_keys: ALLOWED_KEYS + PROCESSABLE_ALLOWED_KEYS validates :config, required_keys: REQUIRED_BY_NEEDS, if: :has_needs? - validates :config, presence: true validates :script, presence: true - validates :name, presence: true - validates :name, type: Symbol - validates :config, - disallowed_keys: { - in: %i[only except when start_in], - message: 'key may not be used with `rules`' - }, - if: :has_rules? validates :config, disallowed_keys: { in: %i[release], @@ -53,8 +41,6 @@ module Gitlab } validates :dependencies, array_of_strings: true - validates :extends, array_of_strings_or_string: true - validates :rules, array_of_hashes: true validates :resource_group, type: String end @@ -81,10 +67,6 @@ module Gitlab description: 'Commands that will be executed in this job.', inherit: false - entry :stage, Entry::Stage, - description: 'Pipeline stage this job will be executed into.', - inherit: false - entry :type, Entry::Stage, description: 'Deprecated: stage this job will be executed into.', inherit: false @@ -125,22 +107,6 @@ module Gitlab description: 'Artifacts configuration for this job.', inherit: true - entry :only, Entry::Policy, - description: 'Refs policy this job will be executed for.', - default: ::Gitlab::Ci::Config::Entry::Policy::DEFAULT_ONLY, - inherit: false - - entry :except, Entry::Policy, - description: 'Refs policy this job will be executed for.', - inherit: false - - entry :rules, Entry::Rules, - description: 'List of evaluable Rules to determine job inclusion.', - inherit: false, - metadata: { - allowed_when: %w[on_success on_failure always never manual delayed].freeze - } - entry :needs, Entry::Needs, description: 'Needs configuration for this job.', metadata: { allowed_needs: %i[job cross_dependency] }, @@ -162,13 +128,13 @@ module Gitlab description: 'This job will produce a release.', inherit: false - helpers :before_script, :script, :stage, :type, :after_script, - :cache, :image, :services, :only, :except, :variables, - :artifacts, :environment, :coverage, :retry, :rules, - :parallel, :needs, :interruptible, :release, :tags + helpers :before_script, :script, :type, :after_script, + :cache, :image, :services, :variables, + :artifacts, :environment, :coverage, :retry, + :needs, :interruptible, :release, :tags attributes :script, :tags, :allow_failure, :when, :dependencies, - :needs, :retry, :parallel, :extends, :start_in, :rules, + :needs, :retry, :parallel, :start_in, :interruptible, :timeout, :resource_group, :release def self.matching?(name, config) @@ -187,31 +153,9 @@ module Gitlab end @entries.delete(:type) - - has_workflow_rules = deps&.workflow&.has_rules? - - # If workflow:rules: or rules: are used - # they are considered not compatible - # with `only/except` defaults - # - # Context: https://gitlab.com/gitlab-org/gitlab/merge_requests/21742 - if has_rules? || has_workflow_rules - # Remove only/except defaults - # defaults are not considered as defined - @entries.delete(:only) unless only_defined? - @entries.delete(:except) unless except_defined? - end end end - def name - @metadata[:name] - end - - def value - @config.merge(to_hash.compact) - end - def manual_action? self.when == 'manual' end @@ -220,38 +164,27 @@ module Gitlab self.when == 'delayed' end - def has_rules? - @config.try(:key?, :rules) - end - def ignored? allow_failure.nil? ? manual_action? : allow_failure end - private - - def overwrite_entry(deps, key, current_entry) - deps.default[key] unless current_entry.specified? - end - - def to_hash - { name: name, + def value + super.merge( before_script: before_script_value, script: script_value, image: image_value, services: services_value, - stage: stage_value, cache: cache_value, tags: tags_value, - only: only_value, - except: except_value, - rules: has_rules? ? rules_value : nil, + when: self.when, + start_in: self.start_in, + dependencies: dependencies, variables: variables_defined? ? variables_value : {}, environment: environment_defined? ? environment_value : nil, environment_name: environment_defined? ? environment_value[:name] : nil, coverage: coverage_defined? ? coverage_value : nil, retry: retry_defined? ? retry_value : nil, - parallel: parallel_defined? ? parallel_value.to_i : nil, + parallel: has_parallel? ? parallel.to_i : nil, interruptible: interruptible_defined? ? interruptible_value : nil, timeout: has_timeout? ? ChronicDuration.parse(timeout.to_s) : nil, artifacts: artifacts_value, @@ -260,7 +193,8 @@ module Gitlab ignore: ignored?, needs: needs_defined? ? needs_value : nil, resource_group: resource_group, - scheduling_type: needs_defined? ? :dag : :stage } + scheduling_type: needs_defined? ? :dag : :stage + ).compact end end end diff --git a/lib/gitlab/ci/config/entry/processable.rb b/lib/gitlab/ci/config/entry/processable.rb new file mode 100644 index 00000000000..19e6601e31f --- /dev/null +++ b/lib/gitlab/ci/config/entry/processable.rb @@ -0,0 +1,102 @@ +# frozen_string_literal: true + +module Gitlab + module Ci + class Config + module Entry + ## + # Entry that represents a CI/CD Processable (a job) + # + module Processable + extend ActiveSupport::Concern + + include ::Gitlab::Config::Entry::Configurable + include ::Gitlab::Config::Entry::Attributable + include ::Gitlab::Config::Entry::Inheritable + + PROCESSABLE_ALLOWED_KEYS = %i[extends stage only except rules].freeze + + included do + validations do + validates :config, presence: true + validates :name, presence: true + validates :name, type: Symbol + + validates :config, disallowed_keys: { + in: %i[only except when start_in], + message: 'key may not be used with `rules`' + }, + if: :has_rules? + + with_options allow_nil: true do + validates :extends, array_of_strings_or_string: true + validates :rules, array_of_hashes: true + end + end + + entry :stage, Entry::Stage, + description: 'Pipeline stage this job will be executed into.', + inherit: false + + entry :only, ::Gitlab::Ci::Config::Entry::Policy, + description: 'Refs policy this job will be executed for.', + default: ::Gitlab::Ci::Config::Entry::Policy::DEFAULT_ONLY, + inherit: false + + entry :except, ::Gitlab::Ci::Config::Entry::Policy, + description: 'Refs policy this job will be executed for.', + inherit: false + + entry :rules, ::Gitlab::Ci::Config::Entry::Rules, + description: 'List of evaluable Rules to determine job inclusion.', + inherit: false, + metadata: { + allowed_when: %w[on_success on_failure always never manual delayed].freeze + } + + helpers :stage, :only, :except, :rules + + attributes :extends, :rules + end + + def compose!(deps = nil) + super do + has_workflow_rules = deps&.workflow&.has_rules? + + # If workflow:rules: or rules: are used + # they are considered not compatible + # with `only/except` defaults + # + # Context: https://gitlab.com/gitlab-org/gitlab/merge_requests/21742 + if has_rules? || has_workflow_rules + # Remove only/except defaults + # defaults are not considered as defined + @entries.delete(:only) unless only_defined? # rubocop:disable Gitlab/ModuleWithInstanceVariables + @entries.delete(:except) unless except_defined? # rubocop:disable Gitlab/ModuleWithInstanceVariables + end + + yield if block_given? + end + end + + def name + metadata[:name] + end + + def overwrite_entry(deps, key, current_entry) + deps.default[key] unless current_entry.specified? + end + + def value + { name: name, + stage: stage_value, + extends: extends, + rules: rules_value, + only: only_value, + except: except_value }.compact + end + end + end + end + end +end diff --git a/lib/gitlab/ci/config/entry/root.rb b/lib/gitlab/ci/config/entry/root.rb index 12dd942fc1c..620f6a95e9d 100644 --- a/lib/gitlab/ci/config/entry/root.rb +++ b/lib/gitlab/ci/config/entry/root.rb @@ -67,7 +67,9 @@ module Gitlab entry :workflow, Entry::Workflow, description: 'List of evaluable rules to determine Pipeline status' - helpers :default, :jobs, :stages, :types, :variables, :workflow + helpers :default, :stages, :types, :variables, :workflow + + helpers :jobs, dynamic: true delegate :before_script_value, :image_value, diff --git a/lib/gitlab/config/entry/configurable.rb b/lib/gitlab/config/entry/configurable.rb index e7d441bb21c..75e15cd8cb1 100644 --- a/lib/gitlab/config/entry/configurable.rb +++ b/lib/gitlab/config/entry/configurable.rb @@ -75,6 +75,8 @@ module Gitlab # rubocop: disable CodeReuse/ActiveRecord def entry(key, entry, description: nil, default: nil, inherit: nil, reserved: nil, metadata: {}) + raise ArgumentError, "Entry #{key} already defined" if @nodes.to_h[key.to_sym] + factory = ::Gitlab::Config::Entry::Factory.new(entry) .with(description: description) .with(default: default) @@ -86,8 +88,16 @@ module Gitlab end # rubocop: enable CodeReuse/ActiveRecord - def helpers(*nodes) + def helpers(*nodes, dynamic: false) nodes.each do |symbol| + if method_defined?("#{symbol}_defined?") || method_defined?("#{symbol}_value") + raise ArgumentError, "Method #{symbol}_defined? or #{symbol}_value already defined" + end + + unless @nodes.to_h[symbol] + raise ArgumentError, "Entry for #{symbol} is undefined" unless dynamic + end + define_method("#{symbol}_defined?") do entries[symbol]&.specified? end diff --git a/lib/gitlab/danger/helper.rb b/lib/gitlab/danger/helper.rb index 5363533ace5..3c3f95e5b78 100644 --- a/lib/gitlab/danger/helper.rb +++ b/lib/gitlab/danger/helper.rb @@ -128,9 +128,12 @@ module Gitlab %r{\A(ee/)?db/(?!fixtures)[^/]+} => :database, %r{\A(ee/)?lib/gitlab/(database|background_migration|sql|github_import)(/|\.rb)} => :database, %r{\A(app/models/project_authorization|app/services/users/refresh_authorized_projects_service)(/|\.rb)} => :database, + %r{\A(ee/)?app/finders/} => :database, %r{\Arubocop/cop/migration(/|\.rb)} => :database, %r{\A(\.gitlab-ci\.yml\z|\.gitlab\/ci)} => :engineering_productivity, + %r{\A\.overcommit\.yml\.example\z} => :engineering_productivity, + %r{\Atooling/overcommit/} => :engineering_productivity, %r{Dangerfile\z} => :engineering_productivity, %r{\A(ee/)?(danger/|lib/gitlab/danger/)} => :engineering_productivity, %r{\A(ee/)?scripts/} => :engineering_productivity, diff --git a/lib/gitlab/gon_helper.rb b/lib/gitlab/gon_helper.rb index 3db6c3b51c0..e4e69241bd9 100644 --- a/lib/gitlab/gon_helper.rb +++ b/lib/gitlab/gon_helper.rb @@ -46,6 +46,7 @@ module Gitlab push_frontend_feature_flag(:monaco_snippets, default_enabled: false) push_frontend_feature_flag(:monaco_blobs, default_enabled: false) push_frontend_feature_flag(:monaco_ci, default_enabled: false) + push_frontend_feature_flag(:snippets_edit_vue, default_enabled: false) end # Exposes the state of a feature flag to the frontend code. diff --git a/lib/gitlab/import_export/members_mapper.rb b/lib/gitlab/import_export/members_mapper.rb index 2a70344374b..e7eae0a8c31 100644 --- a/lib/gitlab/import_export/members_mapper.rb +++ b/lib/gitlab/import_export/members_mapper.rb @@ -51,7 +51,7 @@ module Gitlab @importable.members.destroy_all # rubocop: disable DestroyAll - relation_class.create!(user: @user, access_level: relation_class::MAINTAINER, source_id: @importable.id, importing: true) + relation_class.create!(user: @user, access_level: highest_access_level, source_id: @importable.id, importing: true) rescue => e raise e, "Error adding importer user to #{@importable.class} members. #{e.message}" end @@ -59,7 +59,7 @@ module Gitlab def user_already_member? member = @importable.members&.first - member&.user == @user && member.access_level >= relation_class::MAINTAINER + member&.user == @user && member.access_level >= highest_access_level end def add_team_member(member, existing_user = nil) @@ -72,7 +72,7 @@ module Gitlab parsed_hash(member).merge( 'source_id' => @importable.id, 'importing' => true, - 'access_level' => [member['access_level'], relation_class::MAINTAINER].min + 'access_level' => [member['access_level'], highest_access_level].min ).except('user_id') end @@ -97,6 +97,12 @@ module Gitlab GroupMember end end + + def highest_access_level + return relation_class::OWNER if relation_class == GroupMember + + relation_class::MAINTAINER + end end end end diff --git a/lib/gitlab/kubernetes/helm.rb b/lib/gitlab/kubernetes/helm.rb index 9f66f35b5ab..3e201d68297 100644 --- a/lib/gitlab/kubernetes/helm.rb +++ b/lib/gitlab/kubernetes/helm.rb @@ -3,7 +3,7 @@ module Gitlab module Kubernetes module Helm - HELM_VERSION = '2.16.1' + HELM_VERSION = '2.16.3' KUBECTL_VERSION = '1.13.12' NAMESPACE = 'gitlab-managed-apps' NAMESPACE_LABELS = { 'app.gitlab.com/managed_by' => :gitlab }.freeze diff --git a/lib/gitlab/reference_counter.rb b/lib/gitlab/reference_counter.rb index 1c43de35816..5fdfa5e75ed 100644 --- a/lib/gitlab/reference_counter.rb +++ b/lib/gitlab/reference_counter.rb @@ -1,20 +1,42 @@ # frozen_string_literal: true module Gitlab + # Reference Counter + # + # A reference counter is used as a mechanism to identify when + # a repository is being accessed by a writable operation. + # + # Maintenance operations would use this as a clue to when it should + # execute significant changes in order to avoid disrupting running traffic class ReferenceCounter REFERENCE_EXPIRE_TIME = 600 attr_reader :gl_repository, :key + # Reference Counter instance + # + # @example + # Gitlab::ReferenceCounter.new('project-1') + # + # @see Gitlab::GlRepository::RepoType.identifier_for_repositorable + # @param [String] gl_repository repository identifier def initialize(gl_repository) @gl_repository = gl_repository @key = "git-receive-pack-reference-counter:#{gl_repository}" end + # Return the actual counter value + # + # @return [Integer] value def value - Gitlab::Redis::SharedState.with { |redis| (redis.get(key) || 0).to_i } + Gitlab::Redis::SharedState.with do |redis| + (redis.get(key) || 0).to_i + end end + # Increase the counter + # + # @return [Boolean] whether operation was a success def increase redis_cmd do |redis| redis.incr(key) @@ -22,26 +44,51 @@ module Gitlab end end - # rubocop:disable Gitlab/RailsLogger + # Decrease the counter + # + # @return [Boolean] whether operation was a success def decrease redis_cmd do |redis| current_value = redis.decr(key) if current_value < 0 + # rubocop:disable Gitlab/RailsLogger Rails.logger.warn("Reference counter for #{gl_repository} decreased" \ - " when its value was less than 1. Reseting the counter.") + " when its value was less than 1. Resetting the counter.") + # rubocop:enable Gitlab/RailsLogger redis.del(key) end end end - # rubocop:enable Gitlab/RailsLogger + + # Reset the reference counter + # + # @private Used internally by SRE and debugging purpose + # @return [Boolean] whether reset was a success + def reset! + redis_cmd do |redis| + redis.del(key) + end + end + + # When the reference counter would expire + # + # @api private Used internally by SRE and debugging purpose + # @return [Integer] Number in seconds until expiration or false if never + def expires_in + Gitlab::Redis::SharedState.with do |redis| + redis.ttl(key) + end + end private def redis_cmd Gitlab::Redis::SharedState.with { |redis| yield(redis) } + true rescue => e Rails.logger.warn("GitLab: An unexpected error occurred in writing to Redis: #{e}") # rubocop:disable Gitlab/RailsLogger + false end end -- cgit v1.2.1