diff options
-rw-r--r-- | CHANGELOG | 5 | ||||
-rw-r--r-- | app/assets/javascripts/ci/build.coffee | 21 | ||||
-rw-r--r-- | app/controllers/admin/runners_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/projects/builds_controller.rb | 8 | ||||
-rw-r--r-- | app/controllers/projects/runners_controller.rb | 2 | ||||
-rw-r--r-- | app/helpers/projects_helper.rb | 4 | ||||
-rw-r--r-- | app/models/ci/build.rb | 8 | ||||
-rw-r--r-- | app/models/ci/runner.rb | 3 | ||||
-rw-r--r-- | app/views/admin/runners/show.html.haml | 22 | ||||
-rw-r--r-- | app/views/projects/builds/show.html.haml | 7 | ||||
-rw-r--r-- | app/views/projects/commits/_commits.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/runners/_form.html.haml | 25 | ||||
-rw-r--r-- | app/views/projects/runners/edit.html.haml | 26 | ||||
-rw-r--r-- | config/routes.rb | 1 | ||||
-rw-r--r-- | doc/integration/cas.md | 19 | ||||
-rw-r--r-- | lib/ci/ansi2html.rb | 83 | ||||
-rw-r--r-- | lib/gitlab/metrics/instrumentation.rb | 2 | ||||
-rw-r--r-- | spec/lib/ci/ansi2html_spec.rb | 111 | ||||
-rw-r--r-- | spec/lib/gitlab/metrics/instrumentation_spec.rb | 6 |
19 files changed, 226 insertions, 131 deletions
diff --git a/CHANGELOG b/CHANGELOG index 7cd8f63321f..efb6dc6f610 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -32,10 +32,12 @@ v 8.8.0 (unreleased) - Backport GitHub Enterprise import support from EE - Create tags using Rugged for performance reasons. !3745 - API: Expose Issue#user_notes_count. !3126 (Anton Popov) + - Don't show forks button when user can't view forks - Files over 5MB can only be viewed in their raw form, files over 1MB without highlighting !3718 - Add support for supressing text diffs using .gitattributes on the default branch (Matt Oakes) - Add eager load paths to help prevent dependency load issues in Sidekiq workers. !3724 - Added multiple colors for labels in dropdowns when dups happen. + - Always group commits by server timezone, not commit timestamp - Improve description for the Two-factor Authentication sign-in screen. (Connor Shea) - API support for the 'since' and 'until' operators on commit requests (Paco Guzman) - Fix Gravatar hint in user profile when Gravatar is disabled. !3988 (Artem Sidorenko) @@ -43,10 +45,13 @@ v 8.8.0 (unreleased) - Fix unintentional filtering bug in issues sorted by milestone due (Takuya Noguchi) - Fix adding a todo for private group members (Ahmad Sherif) - Bump ace-rails-ap gem version from 2.0.1 to 4.0.2 which upgrades Ace Editor from 1.1.2 to 1.2.3 + - Total method execution timings are no longer tracked - Allow Admins to remove the Login with buttons for OAuth services and still be able to import !4034. (Andrei Gliga) v 8.7.5 - Fix relative links in wiki pages. !4050 + - Fix always showing build notification message when switching between merge requests !4086 + - Fix an issue when filtering merge requests with more than one label. !3886 v 8.7.4 - Links for Redmine issue references are generated correctly again !4048 (Benedikt Huss) diff --git a/app/assets/javascripts/ci/build.coffee b/app/assets/javascripts/ci/build.coffee index 7afe8bf79e2..fca0c3bae5c 100644 --- a/app/assets/javascripts/ci/build.coffee +++ b/app/assets/javascripts/ci/build.coffee @@ -1,9 +1,12 @@ class CiBuild @interval: null + @state: null - constructor: (build_url, build_status) -> + constructor: (build_url, build_status, build_state) -> clearInterval(CiBuild.interval) + @state = build_state + @initScrollButtonAffix() if build_status == "running" || build_status == "pending" @@ -26,14 +29,18 @@ class CiBuild CiBuild.interval = setInterval => if window.location.href.split("#").first() is build_url $.ajax - url: build_url + url: build_url + "/trace.json?state=" + encodeURIComponent(@state) dataType: "json" - success: (build) => - if build.status == "running" - $('#build-trace code').html build.trace_html - $('#build-trace code').append '<i class="fa fa-refresh fa-spin"/>' + success: (log) => + @state = log.state + if log.status is "running" + if log.append + $('.fa-refresh').before log.html + else + $('#build-trace code').html log.html + $('#build-trace code').append '<i class="fa fa-refresh fa-spin"/>' @checkAutoscroll() - else if build.status != build_status + else if log.status isnt build_status Turbolinks.visit build_url , 4000 diff --git a/app/controllers/admin/runners_controller.rb b/app/controllers/admin/runners_controller.rb index a701d49b844..8b8a7320072 100644 --- a/app/controllers/admin/runners_controller.rb +++ b/app/controllers/admin/runners_controller.rb @@ -58,6 +58,6 @@ class Admin::RunnersController < Admin::ApplicationController end def runner_params - params.require(:runner).permit(:token, :description, :tag_list, :active) + params.require(:runner).permit(Ci::Runner::FORM_EDITABLE) end end diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb index b8b9e78427d..bb1f6c5e980 100644 --- a/app/controllers/projects/builds_controller.rb +++ b/app/controllers/projects/builds_controller.rb @@ -38,6 +38,14 @@ class Projects::BuildsController < Projects::ApplicationController end end + def trace + respond_to do |format| + format.json do + render json: @build.trace_with_state(params[:state]).merge!(id: @build.id, status: @build.status) + end + end + end + def retry unless @build.retryable? return render_404 diff --git a/app/controllers/projects/runners_controller.rb b/app/controllers/projects/runners_controller.rb index 0dd2d6a99be..3a9d67aff64 100644 --- a/app/controllers/projects/runners_controller.rb +++ b/app/controllers/projects/runners_controller.rb @@ -64,6 +64,6 @@ class Projects::RunnersController < Projects::ApplicationController end def runner_params - params.require(:runner).permit(:description, :tag_list, :active) + params.require(:runner).permit(Ci::Runner::FORM_EDITABLE) end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 85f8854d2eb..e1ab78df69e 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -138,10 +138,10 @@ module ProjectsHelper private def get_project_nav_tabs(project, current_user) - nav_tabs = [:home, :forks] + nav_tabs = [:home] if !project.empty_repo? && can?(current_user, :download_code, project) - nav_tabs << [:files, :commits, :network, :graphs] + nav_tabs << [:files, :commits, :network, :graphs, :forks] end if project.repo_exists? && can?(current_user, :read_merge_request, project) diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index c9506dd3057..4a3f92ad34a 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -95,8 +95,12 @@ module Ci end def trace_html - html = Ci::Ansi2html::convert(trace) if trace.present? - html || '' + trace_with_state[:html] || '' + end + + def trace_with_state(state = nil) + trace_with_state = Ci::Ansi2html::convert(trace, state) if trace.present? + trace_with_state || {} end def timeout diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb index 0cdb64d6c33..819064f99bb 100644 --- a/app/models/ci/runner.rb +++ b/app/models/ci/runner.rb @@ -3,7 +3,8 @@ module Ci extend Ci::Model LAST_CONTACT_TIME = 5.minutes.ago - AVAILABLE_SCOPES = ['specific', 'shared', 'active', 'paused', 'online'] + AVAILABLE_SCOPES = %w[specific shared active paused online] + FORM_EDITABLE = %i[description tag_list active] has_many :builds, class_name: 'Ci::Build' has_many :runner_projects, dependent: :destroy, class_name: 'Ci::RunnerProject' diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml index 8700b4820cd..4dfb3ed05bb 100644 --- a/app/views/admin/runners/show.html.haml +++ b/app/views/admin/runners/show.html.haml @@ -22,25 +22,9 @@ %h4 This runner will process builds only from ASSIGNED projects %p You can't make this a shared runner. %hr -= form_for @runner, url: admin_runner_path(@runner), html: { class: 'form-horizontal' } do |f| - .form-group - = label_tag :token, class: 'control-label' do - Token - .col-sm-10 - = f.text_field :token, class: 'form-control', readonly: true - .form-group - = label_tag :description, class: 'control-label' do - Description - .col-sm-10 - = f.text_field :description, class: 'form-control' - .form-group - = label_tag :tag_list, class: 'control-label' do - Tags - .col-sm-10 - = f.text_field :tag_list, value: @runner.tag_list.to_s, class: 'form-control' - .help-block You can setup builds to only use runners with specific tags - .form-actions - = f.submit 'Save', class: 'btn btn-save' + +.append-bottom-20 + = render '/projects/runners/form', runner: @runner, runner_form_url: admin_runner_path(@runner) .row .col-md-6 diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml index c0f7a7686f0..c7b9c36a3ab 100644 --- a/app/views/projects/builds/show.html.haml +++ b/app/views/projects/builds/show.html.haml @@ -1,5 +1,6 @@ - page_title "#{@build.name} (##{@build.id})", "Builds" = render "header_title" +- trace_with_state = @build.trace_with_state .build-page .row-content-block.top-block @@ -85,7 +86,9 @@ %pre.trace#build-trace %code.bash = preserve do - = raw @build.trace_html + = raw trace_with_state[:html] + - if @build.active? + %i{:class => "fa fa-refresh fa-spin"} %div#down-build-trace @@ -216,4 +219,4 @@ :javascript - new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{@build.status}") + new CiBuild("#{namespace_project_build_url(@project.namespace, @project, @build)}", "#{@build.status}", "#{trace_with_state[:state]}") diff --git a/app/views/projects/commits/_commits.html.haml b/app/views/projects/commits/_commits.html.haml index 64e8da9201d..82f39e59284 100644 --- a/app/views/projects/commits/_commits.html.haml +++ b/app/views/projects/commits/_commits.html.haml @@ -3,7 +3,7 @@ - commits, hidden = limited_commits(@commits) -- commits.group_by { |c| c.committed_date.to_date }.sort.reverse.each do |day, commits| +- commits.group_by { |c| c.committed_date.in_time_zone.to_date }.sort.reverse.each do |day, commits| .row.commits-row .col-md-2.hidden-xs.hidden-sm %h5.commits-row-date diff --git a/app/views/projects/runners/_form.html.haml b/app/views/projects/runners/_form.html.haml new file mode 100644 index 00000000000..2d6c964ae94 --- /dev/null +++ b/app/views/projects/runners/_form.html.haml @@ -0,0 +1,25 @@ += form_for runner, url: runner_form_url, html: { class: 'form-horizontal' } do |f| + .form-group + = label :active, "Active", class: 'control-label' + .col-sm-10 + .checkbox + = f.check_box :active + %span.light Paused runners don't accept new builds + .form-group + = label_tag :token, class: 'control-label' do + Token + .col-sm-10 + = f.text_field :token, class: 'form-control', readonly: true + .form-group + = label_tag :description, class: 'control-label' do + Description + .col-sm-10 + = f.text_field :description, class: 'form-control' + .form-group + = label_tag :tag_list, class: 'control-label' do + Tags + .col-sm-10 + = f.text_field :tag_list, value: runner.tag_list.to_s, class: 'form-control' + .help-block You can setup jobs to only use runners with specific tags + .form-actions + = f.submit 'Save changes', class: 'btn btn-save' diff --git a/app/views/projects/runners/edit.html.haml b/app/views/projects/runners/edit.html.haml index eba03028af8..771947d7908 100644 --- a/app/views/projects/runners/edit.html.haml +++ b/app/views/projects/runners/edit.html.haml @@ -2,28 +2,4 @@ %h4 Runner ##{@runner.id} %hr -= form_for @runner, url: runner_path(@runner), html: { class: 'form-horizontal' } do |f| - .form-group - = label :active, "Active", class: 'control-label' - .col-sm-10 - .checkbox - = f.check_box :active - %span.light Paused runners don't accept new builds - .form-group - = label_tag :token, class: 'control-label' do - Token - .col-sm-10 - = f.text_field :token, class: 'form-control', readonly: true - .form-group - = label_tag :description, class: 'control-label' do - Description - .col-sm-10 - = f.text_field :description, class: 'form-control' - .form-group - = label_tag :tag_list, class: 'control-label' do - Tags - .col-sm-10 - = f.text_field :tag_list, value: @runner.tag_list.to_s, class: 'form-control' - .help-block You can setup jobs to only use runners with specific tags - .form-actions - = f.submit 'Save changes', class: 'btn btn-save' + = render 'form', runner: @runner, runner_form_url: runner_path(@runner) diff --git a/config/routes.rb b/config/routes.rb index 881de37f10e..dd946305181 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -668,6 +668,7 @@ Rails.application.routes.draw do post :cancel post :retry post :erase + get :trace get :raw end diff --git a/doc/integration/cas.md b/doc/integration/cas.md index e6b2071f193..e34e306f9ac 100644 --- a/doc/integration/cas.md +++ b/doc/integration/cas.md @@ -27,17 +27,18 @@ To enable the CAS OmniAuth provider you must register your application with your ```ruby gitlab_rails['omniauth_providers'] = [ { - name: "cas3", - label: "cas", - args: { - url: 'CAS_SERVER', - login_url: '/CAS_PATH/login', - service_validate_url: '/CAS_PATH/p3/serviceValidate', - logout_url: '/CAS_PATH/logout'} } - } + "name"=> "cas3", + "label"=> "cas", + "args"=> { + "url"=> 'CAS_SERVER', + "login_url"=> '/CAS_PATH/login', + "service_validate_url"=> '/CAS_PATH/p3/serviceValidate', + "logout_url"=> '/CAS_PATH/logout' + } } ] ``` + For installations from source: @@ -57,6 +58,8 @@ To enable the CAS OmniAuth provider you must register your application with your 1. Save the configuration file. +1. Run `gitlab-ctl reconfigure` for the omnibus package. + 1. Restart GitLab for the changes to take effect. On the sign in page there should now be a CAS tab in the sign in form. diff --git a/lib/ci/ansi2html.rb b/lib/ci/ansi2html.rb index ac6d667cf8d..5fed43aaebd 100644 --- a/lib/ci/ansi2html.rb +++ b/lib/ci/ansi2html.rb @@ -23,8 +23,8 @@ module Ci cross: 0x10, } - def self.convert(ansi) - Converter.new().convert(ansi) + def self.convert(ansi, state = nil) + Converter.new.convert(ansi, state) end class Converter @@ -84,22 +84,36 @@ module Ci def on_107(s) set_bg_color(7, 'l') end def on_109(s) set_bg_color(9, 'l') end - def convert(ansi) - @out = "" - @n_open_tags = 0 - reset() + attr_accessor :offset, :n_open_tags, :fg_color, :bg_color, :style_mask + + STATE_PARAMS = [:offset, :n_open_tags, :fg_color, :bg_color, :style_mask] + + def convert(raw, new_state) + reset_state + restore_state(raw, new_state) if new_state + + start = @offset + ansi = raw[@offset..-1] + + open_new_tag - s = StringScanner.new(ansi.gsub("<", "<")) + s = StringScanner.new(ansi) while(!s.eos?) if s.scan(/\e([@-_])(.*?)([@-~])/) handle_sequence(s) + elsif s.scan(/\e(([@-_])(.*?)?)?$/) + break + elsif s.scan(/</) + @out << '<' else @out << s.scan(/./m) end + @offset += s.matched_size end close_open_tags() - @out + + { state: state, html: @out, text: ansi[0, @offset - start], append: start > 0 } end def handle_sequence(s) @@ -121,6 +135,20 @@ module Ci evaluate_command_stack(commands) + open_new_tag + end + + def evaluate_command_stack(stack) + return unless command = stack.shift() + + if self.respond_to?("on_#{command}", true) + self.send("on_#{command}", stack) + end + + evaluate_command_stack(stack) + end + + def open_new_tag css_classes = [] unless @fg_color.nil? @@ -138,20 +166,8 @@ module Ci css_classes << "term-#{css_class}" if @style_mask & flag != 0 end - open_new_tag(css_classes) if css_classes.length > 0 - end + return if css_classes.empty? - def evaluate_command_stack(stack) - return unless command = stack.shift() - - if self.respond_to?("on_#{command}", true) - self.send("on_#{command}", stack) - end - - evaluate_command_stack(stack) - end - - def open_new_tag(css_classes) @out << %{<span class="#{css_classes.join(' ')}">} @n_open_tags += 1 end @@ -163,6 +179,31 @@ module Ci end end + def reset_state + @offset = 0 + @n_open_tags = 0 + @out = '' + reset + end + + def state + state = STATE_PARAMS.inject({}) do |h, param| + h[param] = send(param) + h + end + Base64.urlsafe_encode64(state.to_json) + end + + def restore_state(raw, new_state) + state = Base64.urlsafe_decode64(new_state) + state = JSON.parse(state, symbolize_names: true) + return if state[:offset].to_i > raw.length + + STATE_PARAMS.each do |param| + send("#{param}=".to_sym, state[param]) + end + end + def reset @fg_color = nil @bg_color = nil diff --git a/lib/gitlab/metrics/instrumentation.rb b/lib/gitlab/metrics/instrumentation.rb index 708ef79f304..0f115893a15 100644 --- a/lib/gitlab/metrics/instrumentation.rb +++ b/lib/gitlab/metrics/instrumentation.rb @@ -154,8 +154,6 @@ module Gitlab duration = (Time.now - start) * 1000.0 if duration >= Gitlab::Metrics.method_call_threshold - trans.increment(:method_duration, duration) - trans.add_metric(Gitlab::Metrics::Instrumentation::SERIES, { duration: duration }, method: #{label.inspect}) diff --git a/spec/lib/ci/ansi2html_spec.rb b/spec/lib/ci/ansi2html_spec.rb index 3a2b568f4c7..04afbd06929 100644 --- a/spec/lib/ci/ansi2html_spec.rb +++ b/spec/lib/ci/ansi2html_spec.rb @@ -4,131 +4,176 @@ describe Ci::Ansi2html, lib: true do subject { Ci::Ansi2html } it "prints non-ansi as-is" do - expect(subject.convert("Hello")).to eq('Hello') + expect(subject.convert("Hello")[:html]).to eq('Hello') end it "strips non-color-changing controll sequences" do - expect(subject.convert("Hello \e[2Kworld")).to eq('Hello world') + expect(subject.convert("Hello \e[2Kworld")[:html]).to eq('Hello world') end it "prints simply red" do - expect(subject.convert("\e[31mHello\e[0m")).to eq('<span class="term-fg-red">Hello</span>') + expect(subject.convert("\e[31mHello\e[0m")[:html]).to eq('<span class="term-fg-red">Hello</span>') end it "prints simply red without trailing reset" do - expect(subject.convert("\e[31mHello")).to eq('<span class="term-fg-red">Hello</span>') + expect(subject.convert("\e[31mHello")[:html]).to eq('<span class="term-fg-red">Hello</span>') end it "prints simply yellow" do - expect(subject.convert("\e[33mHello\e[0m")).to eq('<span class="term-fg-yellow">Hello</span>') + expect(subject.convert("\e[33mHello\e[0m")[:html]).to eq('<span class="term-fg-yellow">Hello</span>') end it "prints default on blue" do - expect(subject.convert("\e[39;44mHello")).to eq('<span class="term-bg-blue">Hello</span>') + expect(subject.convert("\e[39;44mHello")[:html]).to eq('<span class="term-bg-blue">Hello</span>') end it "prints red on blue" do - expect(subject.convert("\e[31;44mHello")).to eq('<span class="term-fg-red term-bg-blue">Hello</span>') + expect(subject.convert("\e[31;44mHello")[:html]).to eq('<span class="term-fg-red term-bg-blue">Hello</span>') end it "resets colors after red on blue" do - expect(subject.convert("\e[31;44mHello\e[0m world")).to eq('<span class="term-fg-red term-bg-blue">Hello</span> world') + expect(subject.convert("\e[31;44mHello\e[0m world")[:html]).to eq('<span class="term-fg-red term-bg-blue">Hello</span> world') end it "performs color change from red/blue to yellow/blue" do - expect(subject.convert("\e[31;44mHello \e[33mworld")).to eq('<span class="term-fg-red term-bg-blue">Hello </span><span class="term-fg-yellow term-bg-blue">world</span>') + expect(subject.convert("\e[31;44mHello \e[33mworld")[:html]).to eq('<span class="term-fg-red term-bg-blue">Hello </span><span class="term-fg-yellow term-bg-blue">world</span>') end it "performs color change from red/blue to yellow/green" do - expect(subject.convert("\e[31;44mHello \e[33;42mworld")).to eq('<span class="term-fg-red term-bg-blue">Hello </span><span class="term-fg-yellow term-bg-green">world</span>') + expect(subject.convert("\e[31;44mHello \e[33;42mworld")[:html]).to eq('<span class="term-fg-red term-bg-blue">Hello </span><span class="term-fg-yellow term-bg-green">world</span>') end it "performs color change from red/blue to reset to yellow/green" do - expect(subject.convert("\e[31;44mHello\e[0m \e[33;42mworld")).to eq('<span class="term-fg-red term-bg-blue">Hello</span> <span class="term-fg-yellow term-bg-green">world</span>') + expect(subject.convert("\e[31;44mHello\e[0m \e[33;42mworld")[:html]).to eq('<span class="term-fg-red term-bg-blue">Hello</span> <span class="term-fg-yellow term-bg-green">world</span>') end it "ignores unsupported codes" do - expect(subject.convert("\e[51mHello\e[0m")).to eq('Hello') + expect(subject.convert("\e[51mHello\e[0m")[:html]).to eq('Hello') end it "prints light red" do - expect(subject.convert("\e[91mHello\e[0m")).to eq('<span class="term-fg-l-red">Hello</span>') + expect(subject.convert("\e[91mHello\e[0m")[:html]).to eq('<span class="term-fg-l-red">Hello</span>') end it "prints default on light red" do - expect(subject.convert("\e[101mHello\e[0m")).to eq('<span class="term-bg-l-red">Hello</span>') + expect(subject.convert("\e[101mHello\e[0m")[:html]).to eq('<span class="term-bg-l-red">Hello</span>') end it "performs color change from red/blue to default/blue" do - expect(subject.convert("\e[31;44mHello \e[39mworld")).to eq('<span class="term-fg-red term-bg-blue">Hello </span><span class="term-bg-blue">world</span>') + expect(subject.convert("\e[31;44mHello \e[39mworld")[:html]).to eq('<span class="term-fg-red term-bg-blue">Hello </span><span class="term-bg-blue">world</span>') end it "performs color change from light red/blue to default/blue" do - expect(subject.convert("\e[91;44mHello \e[39mworld")).to eq('<span class="term-fg-l-red term-bg-blue">Hello </span><span class="term-bg-blue">world</span>') + expect(subject.convert("\e[91;44mHello \e[39mworld")[:html]).to eq('<span class="term-fg-l-red term-bg-blue">Hello </span><span class="term-bg-blue">world</span>') end it "prints bold text" do - expect(subject.convert("\e[1mHello")).to eq('<span class="term-bold">Hello</span>') + expect(subject.convert("\e[1mHello")[:html]).to eq('<span class="term-bold">Hello</span>') end it "resets bold text" do - expect(subject.convert("\e[1mHello\e[21m world")).to eq('<span class="term-bold">Hello</span> world') - expect(subject.convert("\e[1mHello\e[22m world")).to eq('<span class="term-bold">Hello</span> world') + expect(subject.convert("\e[1mHello\e[21m world")[:html]).to eq('<span class="term-bold">Hello</span> world') + expect(subject.convert("\e[1mHello\e[22m world")[:html]).to eq('<span class="term-bold">Hello</span> world') end it "prints italic text" do - expect(subject.convert("\e[3mHello")).to eq('<span class="term-italic">Hello</span>') + expect(subject.convert("\e[3mHello")[:html]).to eq('<span class="term-italic">Hello</span>') end it "resets italic text" do - expect(subject.convert("\e[3mHello\e[23m world")).to eq('<span class="term-italic">Hello</span> world') + expect(subject.convert("\e[3mHello\e[23m world")[:html]).to eq('<span class="term-italic">Hello</span> world') end it "prints underlined text" do - expect(subject.convert("\e[4mHello")).to eq('<span class="term-underline">Hello</span>') + expect(subject.convert("\e[4mHello")[:html]).to eq('<span class="term-underline">Hello</span>') end it "resets underlined text" do - expect(subject.convert("\e[4mHello\e[24m world")).to eq('<span class="term-underline">Hello</span> world') + expect(subject.convert("\e[4mHello\e[24m world")[:html]).to eq('<span class="term-underline">Hello</span> world') end it "prints concealed text" do - expect(subject.convert("\e[8mHello")).to eq('<span class="term-conceal">Hello</span>') + expect(subject.convert("\e[8mHello")[:html]).to eq('<span class="term-conceal">Hello</span>') end it "resets concealed text" do - expect(subject.convert("\e[8mHello\e[28m world")).to eq('<span class="term-conceal">Hello</span> world') + expect(subject.convert("\e[8mHello\e[28m world")[:html]).to eq('<span class="term-conceal">Hello</span> world') end it "prints crossed-out text" do - expect(subject.convert("\e[9mHello")).to eq('<span class="term-cross">Hello</span>') + expect(subject.convert("\e[9mHello")[:html]).to eq('<span class="term-cross">Hello</span>') end it "resets crossed-out text" do - expect(subject.convert("\e[9mHello\e[29m world")).to eq('<span class="term-cross">Hello</span> world') + expect(subject.convert("\e[9mHello\e[29m world")[:html]).to eq('<span class="term-cross">Hello</span> world') end it "can print 256 xterm fg colors" do - expect(subject.convert("\e[38;5;16mHello")).to eq('<span class="xterm-fg-16">Hello</span>') + expect(subject.convert("\e[38;5;16mHello")[:html]).to eq('<span class="xterm-fg-16">Hello</span>') end it "can print 256 xterm fg colors on normal magenta background" do - expect(subject.convert("\e[38;5;16;45mHello")).to eq('<span class="xterm-fg-16 term-bg-magenta">Hello</span>') + expect(subject.convert("\e[38;5;16;45mHello")[:html]).to eq('<span class="xterm-fg-16 term-bg-magenta">Hello</span>') end it "can print 256 xterm bg colors" do - expect(subject.convert("\e[48;5;240mHello")).to eq('<span class="xterm-bg-240">Hello</span>') + expect(subject.convert("\e[48;5;240mHello")[:html]).to eq('<span class="xterm-bg-240">Hello</span>') end it "can print 256 xterm bg colors on normal magenta foreground" do - expect(subject.convert("\e[48;5;16;35mHello")).to eq('<span class="term-fg-magenta xterm-bg-16">Hello</span>') + expect(subject.convert("\e[48;5;16;35mHello")[:html]).to eq('<span class="term-fg-magenta xterm-bg-16">Hello</span>') end it "prints bold colored text vividly" do - expect(subject.convert("\e[1;31mHello\e[0m")).to eq('<span class="term-fg-l-red term-bold">Hello</span>') + expect(subject.convert("\e[1;31mHello\e[0m")[:html]).to eq('<span class="term-fg-l-red term-bold">Hello</span>') end it "prints bold light colored text correctly" do - expect(subject.convert("\e[1;91mHello\e[0m")).to eq('<span class="term-fg-l-red term-bold">Hello</span>') + expect(subject.convert("\e[1;91mHello\e[0m")[:html]).to eq('<span class="term-fg-l-red term-bold">Hello</span>') + end + + it "prints <" do + expect(subject.convert("<")[:html]).to eq('<') + end + + describe "incremental update" do + shared_examples 'stateable converter' do + let(:pass1) { subject.convert(pre_text) } + let(:pass2) { subject.convert(pre_text + text, pass1[:state]) } + + it "to returns html to append" do + expect(pass2[:append]).to be_truthy + expect(pass2[:html]).to eq(html) + expect(pass1[:text] + pass2[:text]).to eq(pre_text + text) + expect(pass1[:html] + pass2[:html]).to eq(pre_html + html) + end + end + + context "with split word" do + let(:pre_text) { "\e[1mHello" } + let(:pre_html) { "<span class=\"term-bold\">Hello</span>" } + let(:text) { "\e[1mWorld" } + let(:html) { "<span class=\"term-bold\"></span><span class=\"term-bold\">World</span>" } + + it_behaves_like 'stateable converter' + end + + context "with split sequence" do + let(:pre_text) { "\e[1m" } + let(:pre_html) { "<span class=\"term-bold\"></span>" } + let(:text) { "Hello" } + let(:html) { "<span class=\"term-bold\">Hello</span>" } + + it_behaves_like 'stateable converter' + end + + context "with partial sequence" do + let(:pre_text) { "Hello\e" } + let(:pre_html) { "Hello" } + let(:text) { "[1m World" } + let(:html) { "<span class=\"term-bold\"> World</span>" } + + it_behaves_like 'stateable converter' + end end end diff --git a/spec/lib/gitlab/metrics/instrumentation_spec.rb b/spec/lib/gitlab/metrics/instrumentation_spec.rb index 5c885a7a982..7b86450a223 100644 --- a/spec/lib/gitlab/metrics/instrumentation_spec.rb +++ b/spec/lib/gitlab/metrics/instrumentation_spec.rb @@ -56,9 +56,6 @@ describe Gitlab::Metrics::Instrumentation do allow(described_class).to receive(:transaction). and_return(transaction) - expect(transaction).to receive(:increment). - with(:method_duration, a_kind_of(Numeric)) - expect(transaction).to receive(:add_metric). with(described_class::SERIES, an_instance_of(Hash), method: 'Dummy.foo') @@ -139,9 +136,6 @@ describe Gitlab::Metrics::Instrumentation do allow(described_class).to receive(:transaction). and_return(transaction) - expect(transaction).to receive(:increment). - with(:method_duration, a_kind_of(Numeric)) - expect(transaction).to receive(:add_metric). with(described_class::SERIES, an_instance_of(Hash), method: 'Dummy#bar') |