diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/api/branches.rb | 7 | ||||
-rw-r--r-- | lib/banzai/filter/abstract_reference_filter.rb | 5 | ||||
-rw-r--r-- | lib/banzai/filter/issue_reference_filter.rb | 2 | ||||
-rw-r--r-- | lib/banzai/filter/reference_filter.rb | 4 | ||||
-rw-r--r-- | lib/banzai/filter/syntax_highlight_filter.rb | 6 | ||||
-rw-r--r-- | lib/banzai/filter/user_reference_filter.rb | 4 | ||||
-rw-r--r-- | lib/banzai/filter/video_link_filter.rb | 3 | ||||
-rw-r--r-- | lib/banzai/pipeline/gfm_pipeline.rb | 6 | ||||
-rw-r--r-- | lib/banzai/renderer.rb | 4 | ||||
-rw-r--r-- | lib/ci/api/builds.rb | 25 | ||||
-rw-r--r-- | lib/gitlab/job_waiter.rb | 27 | ||||
-rw-r--r-- | lib/gitlab/sidekiq_status.rb | 66 | ||||
-rw-r--r-- | lib/gitlab/sidekiq_status/client_middleware.rb | 10 | ||||
-rw-r--r-- | lib/gitlab/sidekiq_status/server_middleware.rb | 13 | ||||
-rw-r--r-- | lib/gitlab/visibility_level.rb | 1 | ||||
-rw-r--r-- | lib/tasks/gitlab/info.rake | 5 |
16 files changed, 162 insertions, 26 deletions
diff --git a/lib/api/branches.rb b/lib/api/branches.rb index 0950c3d2e88..be659fa4a6a 100644 --- a/lib/api/branches.rb +++ b/lib/api/branches.rb @@ -129,12 +129,7 @@ module API end end - # Delete all merged branches - # - # Parameters: - # id (required) - The ID of a project - # Example Request: - # DELETE /projects/:id/repository/branches/delete_merged + desc 'Delete all merged branches' delete ":id/repository/merged_branches" do DeleteMergedBranchesService.new(user_project, current_user).async_execute diff --git a/lib/banzai/filter/abstract_reference_filter.rb b/lib/banzai/filter/abstract_reference_filter.rb index 6d04f68c8f9..a3d495a5da0 100644 --- a/lib/banzai/filter/abstract_reference_filter.rb +++ b/lib/banzai/filter/abstract_reference_filter.rb @@ -153,7 +153,7 @@ module Banzai title = object_link_title(object) klass = reference_class(object_sym) - data = data_attributes_for(link_content || match, project, object) + data = data_attributes_for(link_content || match, project, object, link: !!link_content) if matches.names.include?("url") && matches[:url] url = matches[:url] @@ -172,9 +172,10 @@ module Banzai end end - def data_attributes_for(text, project, object) + def data_attributes_for(text, project, object, link: false) data_attribute( original: text, + link: link, project: project.id, object_sym => object.id ) diff --git a/lib/banzai/filter/issue_reference_filter.rb b/lib/banzai/filter/issue_reference_filter.rb index 4d1bc687696..fd6b9704132 100644 --- a/lib/banzai/filter/issue_reference_filter.rb +++ b/lib/banzai/filter/issue_reference_filter.rb @@ -62,7 +62,7 @@ module Banzai end end - def data_attributes_for(text, project, object) + def data_attributes_for(text, project, object, link: false) if object.is_a?(ExternalIssue) data_attribute( project: project.id, diff --git a/lib/banzai/filter/reference_filter.rb b/lib/banzai/filter/reference_filter.rb index ab7af1cad21..6640168bfa2 100644 --- a/lib/banzai/filter/reference_filter.rb +++ b/lib/banzai/filter/reference_filter.rb @@ -53,6 +53,10 @@ module Banzai context[:project] end + def skip_project_check? + context[:skip_project_check] + end + def reference_class(type) "gfm gfm-#{type} has-tooltip" end diff --git a/lib/banzai/filter/syntax_highlight_filter.rb b/lib/banzai/filter/syntax_highlight_filter.rb index 026b81ac175..a447e2b8bff 100644 --- a/lib/banzai/filter/syntax_highlight_filter.rb +++ b/lib/banzai/filter/syntax_highlight_filter.rb @@ -20,17 +20,19 @@ module Banzai code = node.text css_classes = "code highlight" lexer = lexer_for(language) + lang = lexer.tag begin code = format(lex(lexer, code)) - css_classes << " js-syntax-highlight #{lexer.tag}" + css_classes << " js-syntax-highlight #{lang}" rescue + lang = nil # Gracefully handle syntax highlighter bugs/errors to ensure # users can still access an issue/comment/etc. end - highlighted = %(<pre class="#{css_classes}" v-pre="true"><code>#{code}</code></pre>) + highlighted = %(<pre class="#{css_classes}" lang="#{lang}" v-pre="true"><code>#{code}</code></pre>) # Extracted to a method to measure it replace_parent_pre_element(node, highlighted) diff --git a/lib/banzai/filter/user_reference_filter.rb b/lib/banzai/filter/user_reference_filter.rb index f842b1fb779..1aa9355b256 100644 --- a/lib/banzai/filter/user_reference_filter.rb +++ b/lib/banzai/filter/user_reference_filter.rb @@ -24,7 +24,7 @@ module Banzai end def call - return doc if project.nil? + return doc if project.nil? && !skip_project_check? ref_pattern = User.reference_pattern ref_pattern_start = /\A#{ref_pattern}\z/ @@ -58,7 +58,7 @@ module Banzai # have `gfm` and `gfm-project_member` class names attached for styling. def user_link_filter(text, link_content: nil) self.class.references_in(text) do |match, username| - if username == 'all' + if username == 'all' && !skip_project_check? link_to_all(link_content: link_content) elsif namespace = namespaces[username] link_to_namespace(namespace, link_content: link_content) || match diff --git a/lib/banzai/filter/video_link_filter.rb b/lib/banzai/filter/video_link_filter.rb index ac7bbcb0d10..b64a1287d4d 100644 --- a/lib/banzai/filter/video_link_filter.rb +++ b/lib/banzai/filter/video_link_filter.rb @@ -35,7 +35,8 @@ module Banzai src: element['src'], width: '400', controls: true, - 'data-setup' => '{}') + 'data-setup' => '{}', + 'data-title' => element['title'] || element['alt']) link = doc.document.create_element( 'a', diff --git a/lib/banzai/pipeline/gfm_pipeline.rb b/lib/banzai/pipeline/gfm_pipeline.rb index 5a1f873496c..ac95a79009b 100644 --- a/lib/banzai/pipeline/gfm_pipeline.rb +++ b/lib/banzai/pipeline/gfm_pipeline.rb @@ -1,6 +1,12 @@ module Banzai module Pipeline class GfmPipeline < BasePipeline + # These filters convert GitLab Flavored Markdown (GFM) to HTML. + # The handlers defined in app/assets/javascripts/copy_as_gfm.js.es6 + # consequently convert that same HTML to GFM to be copied to the clipboard. + # Every filter that generates HTML from GFM should have a handler in + # app/assets/javascripts/copy_as_gfm.js.es6, in reverse order. + # The GFM-to-HTML-to-GFM cycle is tested in spec/features/copy_as_gfm_spec.rb. def self.filters @filters ||= FilterArray[ Filter::SyntaxHighlightFilter, diff --git a/lib/banzai/renderer.rb b/lib/banzai/renderer.rb index f31fb6c3f71..74663556cbb 100644 --- a/lib/banzai/renderer.rb +++ b/lib/banzai/renderer.rb @@ -52,9 +52,9 @@ module Banzai end # Same as +render_field+, but without consulting or updating the cache field - def cacheless_render_field(object, field) + def cacheless_render_field(object, field, options = {}) text = object.__send__(field) - context = object.banzai_render_context(field) + context = object.banzai_render_context(field).merge(options) cacheless_render(text, context) end diff --git a/lib/ci/api/builds.rb b/lib/ci/api/builds.rb index c4bdef781f7..8b939663ffd 100644 --- a/lib/ci/api/builds.rb +++ b/lib/ci/api/builds.rb @@ -18,24 +18,31 @@ module Ci if current_runner.is_runner_queue_value_latest?(params[:last_update]) header 'X-GitLab-Last-Update', params[:last_update] + Gitlab::Metrics.add_event(:build_not_found_cached) return build_not_found! end new_update = current_runner.ensure_runner_queue_value - build = Ci::RegisterBuildService.new.execute(current_runner) + result = Ci::RegisterBuildService.new(current_runner).execute - if build - Gitlab::Metrics.add_event(:build_found, - project: build.project.path_with_namespace) + if result.valid? + if result.build + Gitlab::Metrics.add_event(:build_found, + project: result.build.project.path_with_namespace) - present build, with: Entities::BuildDetails - else - Gitlab::Metrics.add_event(:build_not_found) + present result.build, with: Entities::BuildDetails + else + Gitlab::Metrics.add_event(:build_not_found) - header 'X-GitLab-Last-Update', new_update + header 'X-GitLab-Last-Update', new_update - build_not_found! + build_not_found! + end + else + # We received build that is invalid due to concurrency conflict + Gitlab::Metrics.add_event(:build_invalid) + conflict! end end diff --git a/lib/gitlab/job_waiter.rb b/lib/gitlab/job_waiter.rb new file mode 100644 index 00000000000..8db91d25a4b --- /dev/null +++ b/lib/gitlab/job_waiter.rb @@ -0,0 +1,27 @@ +module Gitlab + # JobWaiter can be used to wait for a number of Sidekiq jobs to complete. + class JobWaiter + # The sleep interval between checking keys, in seconds. + INTERVAL = 0.1 + + # jobs - The job IDs to wait for. + def initialize(jobs) + @jobs = jobs + end + + # Waits for all the jobs to be completed. + # + # timeout - The maximum amount of seconds to block the caller for. This + # ensures we don't indefinitely block a caller in case a job takes + # long to process, or is never processed. + def wait(timeout = 60) + start = Time.current + + while (Time.current - start) <= timeout + break if SidekiqStatus.all_completed?(@jobs) + + sleep(INTERVAL) # to not overload Redis too much. + end + end + end +end diff --git a/lib/gitlab/sidekiq_status.rb b/lib/gitlab/sidekiq_status.rb new file mode 100644 index 00000000000..aadc401ff8d --- /dev/null +++ b/lib/gitlab/sidekiq_status.rb @@ -0,0 +1,66 @@ +module Gitlab + # The SidekiqStatus module and its child classes can be used for checking if a + # Sidekiq job has been processed or not. + # + # To check if a job has been completed, simply pass the job ID to the + # `completed?` method: + # + # job_id = SomeWorker.perform_async(...) + # + # if Gitlab::SidekiqStatus.completed?(job_id) + # ... + # end + # + # For each job ID registered a separate key is stored in Redis, making lookups + # much faster than using Sidekiq's built-in job finding/status API. These keys + # expire after a certain period of time to prevent storing too many keys in + # Redis. + module SidekiqStatus + STATUS_KEY = 'gitlab-sidekiq-status:%s'.freeze + + # The default time (in seconds) after which a status key is expired + # automatically. The default of 30 minutes should be more than sufficient + # for most jobs. + DEFAULT_EXPIRATION = 30.minutes.to_i + + # Starts tracking of the given job. + # + # jid - The Sidekiq job ID + # expire - The expiration time of the Redis key. + def self.set(jid, expire = DEFAULT_EXPIRATION) + Sidekiq.redis do |redis| + redis.set(key_for(jid), 1, ex: expire) + end + end + + # Stops the tracking of the given job. + # + # jid - The Sidekiq job ID to remove. + def self.unset(jid) + Sidekiq.redis do |redis| + redis.del(key_for(jid)) + end + end + + # Returns true if all the given job have been completed. + # + # jids - The Sidekiq job IDs to check. + # + # Returns true or false. + def self.all_completed?(jids) + keys = jids.map { |jid| key_for(jid) } + + responses = Sidekiq.redis do |redis| + redis.pipelined do + keys.each { |key| redis.exists(key) } + end + end + + responses.all? { |value| !value } + end + + def self.key_for(jid) + STATUS_KEY % jid + end + end +end diff --git a/lib/gitlab/sidekiq_status/client_middleware.rb b/lib/gitlab/sidekiq_status/client_middleware.rb new file mode 100644 index 00000000000..779a9998b22 --- /dev/null +++ b/lib/gitlab/sidekiq_status/client_middleware.rb @@ -0,0 +1,10 @@ +module Gitlab + module SidekiqStatus + class ClientMiddleware + def call(_, job, _, _) + SidekiqStatus.set(job['jid']) + yield + end + end + end +end diff --git a/lib/gitlab/sidekiq_status/server_middleware.rb b/lib/gitlab/sidekiq_status/server_middleware.rb new file mode 100644 index 00000000000..31dfa46ff9d --- /dev/null +++ b/lib/gitlab/sidekiq_status/server_middleware.rb @@ -0,0 +1,13 @@ +module Gitlab + module SidekiqStatus + class ServerMiddleware + def call(worker, job, queue) + ret = yield + + SidekiqStatus.unset(job['jid']) + + ret + end + end + end +end diff --git a/lib/gitlab/visibility_level.rb b/lib/gitlab/visibility_level.rb index 9462f3368e6..c7953af29dd 100644 --- a/lib/gitlab/visibility_level.rb +++ b/lib/gitlab/visibility_level.rb @@ -11,6 +11,7 @@ module Gitlab included do scope :public_only, -> { where(visibility_level: PUBLIC) } scope :public_and_internal_only, -> { where(visibility_level: [PUBLIC, INTERNAL] ) } + scope :non_public_only, -> { where.not(visibility_level: PUBLIC) } scope :public_to_user, -> (user) { user && !user.external ? public_and_internal_only : public_only } end diff --git a/lib/tasks/gitlab/info.rake b/lib/tasks/gitlab/info.rake index dffea8ed155..f7c831892ee 100644 --- a/lib/tasks/gitlab/info.rake +++ b/lib/tasks/gitlab/info.rake @@ -11,8 +11,10 @@ namespace :gitlab do gem_version = run_command(%W(gem --version)) # check Bundler version bunder_version = run_and_match(%W(bundle --version), /[\d\.]+/).try(:to_s) - # check Bundler version + # check Rake version rake_version = run_and_match(%W(rake --version), /[\d\.]+/).try(:to_s) + # check redis version + redis_version = run_and_match(%W(redis-cli --version), /redis-cli (\d+\.\d+\.\d+)/).to_a puts "" puts "System information".color(:yellow) @@ -24,6 +26,7 @@ namespace :gitlab do puts "Gem Version:\t#{gem_version || "unknown".color(:red)}" puts "Bundler Version:#{bunder_version || "unknown".color(:red)}" puts "Rake Version:\t#{rake_version || "unknown".color(:red)}" + puts "Redis Version:\t#{redis_version[1] || "unknown".color(:red)}" puts "Sidekiq Version:#{Sidekiq::VERSION}" |