Commit 3fc4c096 authored by Shinya Maeda's avatar Shinya Maeda Committed by Alessio Caiazza

Squashed commit of the following:

commit 9d9594ba20097dc4598f7eb42a9f9d78d73eae54
Author: Shinya Maeda <shinya@gitlab.com>
Date:   Thu Sep 13 20:18:31 2018 +0900

    Cancel scheduled jobs

commit f31c7172e07a9eb03b58c1e62eaa18cda4064aa6
Author: Shinya Maeda <shinya@gitlab.com>
Date:   Thu Sep 13 11:18:42 2018 +0900

    Add Ci::BuildSchedule

commit fb6b3ca638f40f9e1ee38b1fdd892bda4f6fede7
Author: Shinya Maeda <shinya@gitlab.com>
Date:   Wed Sep 12 20:02:50 2018 +0900

    Scheduled jobs
parent d5184e0d
...@@ -22,6 +22,7 @@ module Ci ...@@ -22,6 +22,7 @@ module Ci
}.freeze }.freeze
has_one :last_deployment, -> { order('deployments.id DESC') }, as: :deployable, class_name: 'Deployment' has_one :last_deployment, -> { order('deployments.id DESC') }, as: :deployable, class_name: 'Deployment'
has_one :build_schedule, class_name: 'Ci::BuildSchedule', foreign_key: :build_id
has_many :trace_sections, class_name: 'Ci::BuildTraceSection' has_many :trace_sections, class_name: 'Ci::BuildTraceSection'
has_many :trace_chunks, class_name: 'Ci::BuildTraceChunk', foreign_key: :build_id has_many :trace_chunks, class_name: 'Ci::BuildTraceChunk', foreign_key: :build_id
...@@ -184,6 +185,12 @@ module Ci ...@@ -184,6 +185,12 @@ module Ci
end end
end end
after_transition any => [:manual] do |build|
build.run_after_commit do
build.schedule_delayed_execution
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?
...@@ -229,6 +236,20 @@ module Ci ...@@ -229,6 +236,20 @@ module Ci
action? && (manual? || retryable?) action? && (manual? || retryable?)
end end
def autoplay?
manual? && options[:autoplay_in].present?
end
def autoplay_at
ChronicDuration.parse(options[:autoplay_in])&.seconds&.from_now
end
def schedule_delayed_execution
return unless autoplay?
create_build_schedule!(execute_at: autoplay_at)
end
def action? def action?
self.when == 'manual' self.when == 'manual'
end end
......
# frozen_string_literal: true
module Ci
class BuildSchedule < ActiveRecord::Base
extend Gitlab::Ci::Model
include Importable
include AfterCommitQueue
belongs_to :build
after_create :schedule, unless: :importing?
def execute_in
self.execute_at - Time.now
end
private
def schedule
run_after_commit do
Ci::BuildScheduleWorker.perform_at(self.execute_at, self.build_id)
end
end
end
end
...@@ -92,7 +92,8 @@ module HasStatus ...@@ -92,7 +92,8 @@ 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: [:running, :pending, :created]) where("status IN ('running', 'pending', 'created') OR " \
"(status = 'manual' AND EXISTS (select 1 from ci_build_schedules where ci_builds.id = ci_build_schedules.build_id))")
end end
end end
......
This diff is collapsed.
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
- pipeline_default:build_trace_sections - pipeline_default:build_trace_sections
- pipeline_default:pipeline_metrics - pipeline_default:pipeline_metrics
- pipeline_default:pipeline_notification - pipeline_default:pipeline_notification
- pipeline_default:ci_build_schedule
- pipeline_hooks:build_hooks - pipeline_hooks:build_hooks
- pipeline_hooks:pipeline_hooks - pipeline_hooks:pipeline_hooks
- pipeline_processing:build_finished - pipeline_processing:build_finished
......
...@@ -9,6 +9,7 @@ class BuildFinishedWorker ...@@ -9,6 +9,7 @@ class BuildFinishedWorker
# rubocop: disable CodeReuse/ActiveRecord # rubocop: disable CodeReuse/ActiveRecord
def perform(build_id) def perform(build_id)
Ci::Build.find_by(id: build_id).try do |build| Ci::Build.find_by(id: build_id).try do |build|
build&.build_schedule&.delete
# We execute that in sync as this access the files in order to access local file, and reduce IO # We execute that in sync as this access the files in order to access local file, and reduce IO
BuildTraceSectionsWorker.new.perform(build.id) BuildTraceSectionsWorker.new.perform(build.id)
BuildCoverageWorker.new.perform(build.id) BuildCoverageWorker.new.perform(build.id)
......
# frozen_string_literal: true
module Ci
class BuildScheduleWorker
include ApplicationWorker
include PipelineQueue
def perform(build_id)
::Ci::Build.preload(:build_schedule).find_by(id: build_id).try do |build|
break unless build.build_schedule.present?
Ci::PlayBuildService.new(build.project, build.user).execute(build)
end
end
end
end
# frozen_string_literal: true
class CreateBuildSchedules < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
def change
create_table :ci_build_schedules, id: :bigserial do |t|
t.integer :build_id, null: false
t.datetime :execute_at, null: false
t.foreign_key :ci_builds, column: :build_id, on_delete: :cascade
t.index :build_id, unique: true
end
end
end
...@@ -260,6 +260,13 @@ ActiveRecord::Schema.define(version: 20180924141949) do ...@@ -260,6 +260,13 @@ ActiveRecord::Schema.define(version: 20180924141949) do
add_index "chat_teams", ["namespace_id"], name: "index_chat_teams_on_namespace_id", unique: true, using: :btree add_index "chat_teams", ["namespace_id"], name: "index_chat_teams_on_namespace_id", unique: true, using: :btree
create_table "ci_build_schedules", id: :bigserial, force: :cascade do |t|
t.integer "build_id", null: false
t.datetime "execute_at", null: false
end
add_index "ci_build_schedules", ["build_id"], name: "index_ci_build_schedules_on_build_id", unique: true, using: :btree
create_table "ci_build_trace_chunks", id: :bigserial, force: :cascade do |t| create_table "ci_build_trace_chunks", id: :bigserial, force: :cascade do |t|
t.integer "build_id", null: false t.integer "build_id", null: false
t.integer "chunk_index", null: false t.integer "chunk_index", null: false
...@@ -2288,6 +2295,7 @@ ActiveRecord::Schema.define(version: 20180924141949) do ...@@ -2288,6 +2295,7 @@ ActiveRecord::Schema.define(version: 20180924141949) do
add_foreign_key "boards", "namespaces", column: "group_id", on_delete: :cascade add_foreign_key "boards", "namespaces", column: "group_id", on_delete: :cascade
add_foreign_key "boards", "projects", name: "fk_f15266b5f9", on_delete: :cascade add_foreign_key "boards", "projects", name: "fk_f15266b5f9", on_delete: :cascade
add_foreign_key "chat_teams", "namespaces", on_delete: :cascade add_foreign_key "chat_teams", "namespaces", on_delete: :cascade
add_foreign_key "ci_build_schedules", "ci_builds", column: "build_id", on_delete: :cascade
add_foreign_key "ci_build_trace_chunks", "ci_builds", column: "build_id", on_delete: :cascade add_foreign_key "ci_build_trace_chunks", "ci_builds", column: "build_id", on_delete: :cascade
add_foreign_key "ci_build_trace_section_names", "projects", on_delete: :cascade add_foreign_key "ci_build_trace_section_names", "projects", on_delete: :cascade
add_foreign_key "ci_build_trace_sections", "ci_build_trace_section_names", column: "section_name_id", name: "fk_264e112c66", on_delete: :cascade add_foreign_key "ci_build_trace_sections", "ci_build_trace_section_names", column: "section_name_id", name: "fk_264e112c66", on_delete: :cascade
......
...@@ -10,7 +10,7 @@ module Gitlab ...@@ -10,7 +10,7 @@ module Gitlab
include Attributable include Attributable
ALLOWED_KEYS = %i[tags script only except type image services ALLOWED_KEYS = %i[tags script only except type image services
allow_failure type stage when artifacts cache allow_failure type stage when autoplay_in artifacts cache
dependencies before_script after_script variables dependencies before_script after_script variables
environment coverage retry extends].freeze environment coverage retry extends].freeze
...@@ -34,6 +34,14 @@ module Gitlab ...@@ -34,6 +34,14 @@ 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
validates :autoplay_in, duration: true, allow_nil: true
end
with_options unless: :manual_action? do
validates :autoplay_in, presence: false
end
end end
end end
...@@ -84,7 +92,7 @@ module Gitlab ...@@ -84,7 +92,7 @@ module Gitlab
:artifacts, :commands, :environment, :coverage, :retry :artifacts, :commands, :environment, :coverage, :retry
attributes :script, :tags, :allow_failure, :when, :dependencies, attributes :script, :tags, :allow_failure, :when, :dependencies,
:retry, :extends :retry, :extends, :autoplay_in
def compose!(deps = nil) def compose!(deps = nil)
super do super do
......
...@@ -5,6 +5,7 @@ module Gitlab ...@@ -5,6 +5,7 @@ module Gitlab
class Factory < Status::Factory class Factory < Status::Factory
def self.extended_statuses def self.extended_statuses
[[Status::Build::Erased, [[Status::Build::Erased,
Status::Build::ManualWithAutoPlay,
Status::Build::Manual, Status::Build::Manual,
Status::Build::Canceled, Status::Build::Canceled,
Status::Build::Created, Status::Build::Created,
......
module Gitlab
module Ci
module Status
module Build
class ManualWithAutoPlay < Status::Extended
###
# TODO: Those are random values. We have to fix accoding to the UX review
###
###
# Core override
###
def text
s_('CiStatusText|scheduled')
end
def label
s_('CiStatusLabel|scheduled')
end
def icon
'timer'
end
def favicon
'favicon_status_manual_with_auto_play'
end
###
# Extension override
###
def illustration
{
image: 'illustrations/canceled-job_empty.svg',
size: 'svg-394',
title: _('This job is a scheduled job with manual actions!'),
content: _('auto playyyyyyyyyyyyyy! This job depends on a user to trigger its process. Often they are used to deploy code to production environments')
}
end
def status_tooltip
@status.status_tooltip + " (scheulded) : Execute in #{subject.build_schedule.execute_in.round} sec"
end
def self.matches?(build, user)
build.autoplay? && !build.canceled?
end
end
end
end
end
end
...@@ -49,7 +49,8 @@ module Gitlab ...@@ -49,7 +49,8 @@ module Gitlab
script: job[:script], script: job[:script],
after_script: job[:after_script], after_script: job[:after_script],
environment: job[:environment], environment: job[:environment],
retry: job[:retry] retry: job[:retry],
autoplay_in: job[:autoplay_in],
}.compact } }.compact }
end end
......
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