Commit 78a4189e authored by Tomasz Maczukin's avatar Tomasz Maczukin

Show timeout information on job's page

parent d633bc81
......@@ -39,6 +39,15 @@
runnerId() {
return `#${this.job.runner.id}`;
},
timeout() {
let t = `${this.job.timeout.value}`;
if (this.job.timeout.source != null) {
t += ` (from ${this.job.timeout.source})`;
}
return t;
},
renderBlock() {
return this.job.merge_request ||
this.job.duration ||
......@@ -114,6 +123,12 @@
title="Queued"
:value="queued"
/>
<detail-row
class="js-job-timeout"
v-if="job.timeout"
title="Timeout"
:value="timeout"
/>
<detail-row
class="js-job-runner"
v-if="job.runner"
......
......@@ -6,6 +6,7 @@ module Ci
include ObjectStorage::BackgroundMove
include Presentable
include Importable
include ChronicDurationAttribute
MissingDependenciesError = Class.new(StandardError)
......@@ -90,6 +91,8 @@ module Ci
after_commit :update_project_statistics_after_save, on: [:create, :update]
after_commit :update_project_statistics, on: :destroy
chronic_duration_attribute_reader :used_timeout_user_readable, :used_timeout
class << self
# This is needed for url_for to work,
# as the controller is JobsController
......@@ -120,6 +123,10 @@ module Ci
end
after_transition pending: :running do |build|
build.used_timeout = build.timeout
build.timeout_source = build.should_use_runner_timeout? ? 'Runner' : 'Project'
build.save!
build.run_after_commit do
BuildHooksWorker.perform_async(id)
end
......@@ -232,15 +239,14 @@ module Ci
end
def timeout
return runner.maximum_job_timeout if should_use_runner_timeout
return runner.maximum_job_timeout if should_use_runner_timeout?
project.build_timeout
end
def should_use_runner_timeout
def should_use_runner_timeout?
!runner.nil? && runner.defines_maximum_job_timeout? && runner.maximum_job_timeout < project.build_timeout
end
private :should_use_runner_timeout
def triggered_by?(current_user)
user == current_user
......
......@@ -5,6 +5,11 @@ class BuildDetailsEntity < JobEntity
expose :runner, using: RunnerEntity
expose :pipeline, using: PipelineEntity
expose :timeout, if: -> (*) { !build.used_timeout.nil? } do |build|
{ value: build.used_timeout_user_readable,
source: build.timeout_source }
end
expose :erased_by, if: -> (*) { build.erased? }, using: UserEntity
expose :erase_path, if: -> (*) { build.erasable? && can?(current_user, :erase_build, build) } do |build|
erase_project_job_path(project, build)
......
class AddUsedTimeoutAndTimeoutSourceColumnsToCiBuilds < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
add_column :ci_builds, :used_timeout, :integer
add_column :ci_builds, :timeout_source, :string
end
def down
remove_column :ci_builds, :used_timeout
remove_column :ci_builds, :timeout_source
end
end
......@@ -311,6 +311,8 @@ ActiveRecord::Schema.define(version: 20180327101207) do
t.integer "artifacts_metadata_store"
t.boolean "protected"
t.integer "failure_reason"
t.integer "used_timeout"
t.string "timeout_source"
end
add_index "ci_builds", ["artifacts_expire_at"], name: "index_ci_builds_on_artifacts_expire_at", where: "(artifacts_file <> ''::text)", using: :btree
......
......@@ -283,6 +283,8 @@ CommitStatus:
- retried
- protected
- failure_reason
- used_timeout
- timeout_source
Ci::Variable:
- id
- project_id
......
require 'spec_helper'
shared_examples 'ChronicDurationAttribute' do
describe 'dynamically defined methods' do
it { expect(subject.class).to be_public_method_defined(virtual_field) }
it { expect(subject.class).to be_public_method_defined("#{virtual_field}=") }
it 'parses chronic duration input' do
subject.send("#{virtual_field}=", "10m")
expect(subject.send(source_field)).to eq(600)
shared_examples 'ChronicDurationAttribute reader' do
it 'contains dynamically created reader method' do
expect(subject.class).to be_public_method_defined(virtual_field)
end
it 'outputs chronic duration formated value' do
......@@ -16,13 +10,37 @@ shared_examples 'ChronicDurationAttribute' do
expect(subject.send(virtual_field)).to eq('2m')
end
end
shared_examples 'ChronicDurationAttribute writer' do
it 'contains dynamically created writer method' do
expect(subject.class).to be_public_method_defined("#{virtual_field}=")
end
it 'parses chronic duration input' do
subject.send("#{virtual_field}=", "10m")
expect(subject.send(source_field)).to eq(600)
end
end
describe 'ChronicDurationAttribute' do
let(:source_field) { :maximum_job_timeout }
let(:virtual_field) { :maximum_job_timeout_user_readable }
subject { Ci::Runner.new }
let(:source_field) {:maximum_job_timeout}
let(:virtual_field) {:maximum_job_timeout_user_readable}
subject {Ci::Runner.new}
it_behaves_like 'ChronicDurationAttribute reader'
it_behaves_like 'ChronicDurationAttribute writer'
end
describe 'ChronicDurationAttribute - reader' do
let(:source_field) {:used_timeout}
let(:virtual_field) {:used_timeout_user_readable}
subject {Ci::Build.new}
it "doesn't contain dynamically created writer method" do
expect(subject.class).not_to be_public_method_defined("#{virtual_field}=")
end
it_behaves_like 'ChronicDurationAttribute'
it_behaves_like 'ChronicDurationAttribute reader'
end
......@@ -29,7 +29,8 @@ describe Ci::RetryBuildService do
commit_id deployments erased_by_id last_deployment project_id
runner_id tag_taggings taggings tags trigger_request_id
user_id auto_canceled_by_id retried failure_reason
artifacts_file_store artifacts_metadata_store].freeze
artifacts_file_store artifacts_metadata_store
used_timeout timeout_source].freeze
shared_examples 'build duplication' do
let(:another_pipeline) { create(:ci_empty_pipeline, project: project) }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment