Commit a7c767f1 authored by Shinya Maeda's avatar Shinya Maeda Committed by Alessio Caiazza

Add a new status to ci_builds.status

parent af51b954
...@@ -113,7 +113,7 @@ class Projects::JobsController < Projects::ApplicationController ...@@ -113,7 +113,7 @@ class Projects::JobsController < Projects::ApplicationController
def unschedule def unschedule
return respond_422 unless @build.scheduled? return respond_422 unless @build.scheduled?
@build.unschedule @build.unschedule!
redirect_to build_path(@build) redirect_to build_path(@build)
end end
......
...@@ -160,6 +160,22 @@ module Ci ...@@ -160,6 +160,22 @@ module Ci
transition created: :manual transition created: :manual
end end
event :schedule do
transition created: :scheduled
end
event :unschedule do
transition scheduled: :manual
end
before_transition created: :scheduled do |build|
build_build_schedule(execute_at: execute_at)
end
before_transition scheduled: any do |build|
build_schedule.delete!
end
after_transition any => [:pending] do |build| after_transition any => [:pending] do |build|
build.run_after_commit do build.run_after_commit do
BuildQueueWorker.perform_async(id) BuildQueueWorker.perform_async(id)
...@@ -185,12 +201,6 @@ module Ci ...@@ -185,12 +201,6 @@ module Ci
end end
end end
after_transition any => [:manual] do |build|
build.run_after_commit do
build.schedule!
end
end
before_transition any => [:failed] do |build| before_transition any => [:failed] do |build|
next unless build.project next unless build.project
next if build.retries_max.zero? next if build.retries_max.zero?
...@@ -233,25 +243,11 @@ module Ci ...@@ -233,25 +243,11 @@ module Ci
end end
def playable? def playable?
action? && (manual? || retryable?) action? && (manual? || scheduled? || retryable?)
end end
def schedulable? def schedulable?
manual? && options[:start_in].present? self.when == 'delayed' && options[:start_in].present?
end
def scheduled?
build_schedule.present?
end
def schedule!
return unless schedulable?
create_build_schedule!(execute_at: execute_at)
end
def unschedule!
build_schedule.delete!
end end
def execute_at def execute_at
...@@ -259,7 +255,7 @@ module Ci ...@@ -259,7 +255,7 @@ module Ci
end end
def action? def action?
%w[manual delayed].include?(self.when) %w[manual scheduled].include?(self.when)
end end
# rubocop: disable CodeReuse/ServiceClass # rubocop: disable CodeReuse/ServiceClass
......
...@@ -8,14 +8,24 @@ module Ci ...@@ -8,14 +8,24 @@ module Ci
belongs_to :build belongs_to :build
validate :schedule_at_future
after_create :schedule, unless: :importing? after_create :schedule, unless: :importing?
scope :stale, -> { where("execute_at < ?", Time.now) }
def execute_in def execute_in
[0, self.execute_at - Time.now].max [0, self.execute_at - Time.now].max
end end
private private
def schedule_at_future
if self.execute_at < Time.now
errors.add(:execute_at, "Excute point must be somewhere in the future")
end
end
def schedule def schedule
run_after_commit do run_after_commit do
Ci::BuildScheduleWorker.perform_at(self.execute_at, self.build_id) Ci::BuildScheduleWorker.perform_at(self.execute_at, self.build_id)
......
...@@ -26,7 +26,7 @@ class CommitStatus < ActiveRecord::Base ...@@ -26,7 +26,7 @@ class CommitStatus < ActiveRecord::Base
scope :failed_but_allowed, -> do scope :failed_but_allowed, -> do
where(allow_failure: true, status: [:failed, :canceled]) where(allow_failure: true, status: [:failed, :canceled])
end end
scope :exclude_ignored, -> do scope :exclude_ignored, -> do
# We want to ignore failed but allowed to fail jobs. # We want to ignore failed but allowed to fail jobs.
# #
...@@ -71,7 +71,7 @@ class CommitStatus < ActiveRecord::Base ...@@ -71,7 +71,7 @@ class CommitStatus < ActiveRecord::Base
end end
event :enqueue do event :enqueue do
transition [:created, :skipped, :manual] => :pending transition [:created, :skipped, :manual, :scheduled] => :pending
end end
event :run do event :run do
...@@ -91,10 +91,10 @@ class CommitStatus < ActiveRecord::Base ...@@ -91,10 +91,10 @@ class CommitStatus < ActiveRecord::Base
end end
event :cancel do event :cancel do
transition [:created, :pending, :running, :manual] => :canceled transition [:created, :pending, :running, :manual, :scheduled] => :canceled
end end
before_transition [:created, :skipped, :manual] => :pending do |commit_status| before_transition [:created, :skipped, :manual, :scheduled] => :pending do |commit_status|
commit_status.queued_at = Time.now commit_status.queued_at = Time.now
end end
......
...@@ -4,14 +4,15 @@ module HasStatus ...@@ -4,14 +4,15 @@ module HasStatus
extend ActiveSupport::Concern extend ActiveSupport::Concern
DEFAULT_STATUS = 'created'.freeze DEFAULT_STATUS = 'created'.freeze
BLOCKED_STATUS = 'manual'.freeze BLOCKED_STATUS = %w[manual scheduled].freeze
AVAILABLE_STATUSES = %w[created pending running success failed canceled skipped manual].freeze AVAILABLE_STATUSES = %w[created pending running success failed canceled skipped manual scheduled].freeze
STARTED_STATUSES = %w[running success failed skipped manual].freeze STARTED_STATUSES = %w[running success failed skipped manual scheduled].freeze
ACTIVE_STATUSES = %w[pending running].freeze ACTIVE_STATUSES = %w[pending running].freeze
COMPLETED_STATUSES = %w[success failed canceled skipped].freeze COMPLETED_STATUSES = %w[success failed canceled skipped].freeze
ORDERED_STATUSES = %w[failed pending running manual canceled success skipped created].freeze ORDERED_STATUSES = %w[failed pending running manual scheduled canceled success skipped created].freeze
STATUSES_ENUM = { created: 0, pending: 1, running: 2, success: 3, STATUSES_ENUM = { created: 0, pending: 1, running: 2, success: 3,
failed: 4, canceled: 5, skipped: 6, manual: 7 }.freeze failed: 4, canceled: 5, skipped: 6, manual: 7,
scheduled: 8 }.freeze
UnknownStatusError = Class.new(StandardError) UnknownStatusError = Class.new(StandardError)
...@@ -24,6 +25,7 @@ module HasStatus ...@@ -24,6 +25,7 @@ module HasStatus
created = scope_relevant.created.select('count(*)').to_sql created = scope_relevant.created.select('count(*)').to_sql
success = scope_relevant.success.select('count(*)').to_sql success = scope_relevant.success.select('count(*)').to_sql
manual = scope_relevant.manual.select('count(*)').to_sql manual = scope_relevant.manual.select('count(*)').to_sql
scheduled = scope_relevant.scheduled.select('count(*)').to_sql
pending = scope_relevant.pending.select('count(*)').to_sql pending = scope_relevant.pending.select('count(*)').to_sql
running = scope_relevant.running.select('count(*)').to_sql running = scope_relevant.running.select('count(*)').to_sql
skipped = scope_relevant.skipped.select('count(*)').to_sql skipped = scope_relevant.skipped.select('count(*)').to_sql
...@@ -31,6 +33,7 @@ module HasStatus ...@@ -31,6 +33,7 @@ module HasStatus
warnings = scope_warnings.select('count(*) > 0').to_sql.presence || 'false' warnings = scope_warnings.select('count(*) > 0').to_sql.presence || 'false'
"(CASE "(CASE
WHEN (#{scheduled})>0 THEN 'scheduled'
WHEN (#{builds})=(#{skipped}) AND (#{warnings}) THEN 'success' WHEN (#{builds})=(#{skipped}) AND (#{warnings}) THEN 'success'
WHEN (#{builds})=(#{skipped}) THEN 'skipped' WHEN (#{builds})=(#{skipped}) THEN 'skipped'
WHEN (#{builds})=(#{success}) THEN 'success' WHEN (#{builds})=(#{success}) THEN 'success'
...@@ -92,8 +95,7 @@ module HasStatus ...@@ -92,8 +95,7 @@ module HasStatus
scope :failed_or_canceled, -> { where(status: [:failed, :canceled]) } scope :failed_or_canceled, -> { where(status: [:failed, :canceled]) }
scope :cancelable, -> do scope :cancelable, -> do
where("status IN ('running', 'pending', 'created') OR " \ where("status IN ('running', 'pending', 'created', 'scheduled')")
"(status = 'manual' AND EXISTS (select 1 from ci_build_schedules where ci_builds.id = ci_build_schedules.build_id))")
end end
end end
......
...@@ -37,7 +37,7 @@ module Ci ...@@ -37,7 +37,7 @@ module Ci
def process_build(build, current_status) def process_build(build, current_status)
if valid_statuses_for_when(build.when).include?(current_status) if valid_statuses_for_when(build.when).include?(current_status)
build.action? ? build.actionize : enqueue_build(build) proceed_build(build)
true true
else else
build.skip build.skip
...@@ -53,8 +53,10 @@ module Ci ...@@ -53,8 +53,10 @@ module Ci
%w[failed] %w[failed]
when 'always' when 'always'
%w[success failed skipped] %w[success failed skipped]
when 'manual', 'delayed' when 'manual'
%w[success skipped] %w[success skipped]
when 'delayed'
%w[success skipped] # This might be `success` only
else else
[] []
end end
...@@ -102,8 +104,14 @@ module Ci ...@@ -102,8 +104,14 @@ module Ci
end end
# rubocop: enable CodeReuse/ActiveRecord # rubocop: enable CodeReuse/ActiveRecord
def enqueue_build(build) def proceed_build(build)
Ci::EnqueueBuildService.new(project, @user).execute(build) if build.schedulable?
build.schedule!
elsif build.action?
build.actionize
else
Ci::EnqueueBuildService.new(project, @user).execute(build)
end
end end
end end
end end
...@@ -6,10 +6,9 @@ module Ci ...@@ -6,10 +6,9 @@ module Ci
include PipelineQueue include PipelineQueue
def perform(build_id) def perform(build_id)
::Ci::Build.preload(:build_schedule).find_by(id: build_id).try do |build| ::Ci::Build.find_by(id: build_id).try do |build|
break unless build.scheduled? break unless build.scheduled?
build.unschedule!
Ci::PlayBuildService.new(build.project, build.user).execute(build) Ci::PlayBuildService.new(build.project, build.user).execute(build)
end end
end end
......
...@@ -151,7 +151,7 @@ module API ...@@ -151,7 +151,7 @@ module API
present build, with: Entities::Job present build, with: Entities::Job
end end
desc 'Trigger a manual job' do desc 'Trigger a actionable job (manual, scheduled, etc)' do
success Entities::Job success Entities::Job
detail 'This feature was added in GitLab 8.11' detail 'This feature was added in GitLab 8.11'
end end
......
...@@ -35,11 +35,11 @@ module Gitlab ...@@ -35,11 +35,11 @@ module Gitlab
validates :dependencies, array_of_strings: true validates :dependencies, array_of_strings: true
validates :extends, type: String validates :extends, type: String
with_options if: :manual_action? do with_options if: :delayed? do
validates :start_in, duration: true, allow_nil: true validates :start_in, duration: true, allow_nil: false
end end
with_options unless: :manual_action? do with_options unless: :delayed? do
validates :start_in, presence: false validates :start_in, presence: false
end end
end end
...@@ -119,7 +119,11 @@ module Gitlab ...@@ -119,7 +119,11 @@ module Gitlab
end end
def manual_action? def manual_action?
%w[manual delayed].include?(self.when) self.when == 'manual'
end
def delayed?
self.when == 'delayed'
end end
def ignored? def ignored?
......
...@@ -39,7 +39,7 @@ module Gitlab ...@@ -39,7 +39,7 @@ module Gitlab
end end
def self.matches?(build, user) def self.matches?(build, user)
build.schedulable? && !build.canceled? build.scheduled?
end end
private private
......
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