diff options
-rw-r--r-- | app/controllers/projects/pipeline_schedules_controller.rb | 63 | ||||
-rw-r--r-- | app/helpers/gitlab_routing_helper.rb | 4 | ||||
-rw-r--r-- | app/models/ci/trigger_schedule.rb | 12 | ||||
-rw-r--r-- | app/models/project.rb | 1 | ||||
-rw-r--r-- | app/services/ci/create_pipeline_schedule_service.rb | 18 | ||||
-rw-r--r-- | app/services/ci/create_trigger_request_service.rb | 5 | ||||
-rw-r--r-- | app/views/projects/pipeline_schedules/_form.html.haml | 21 | ||||
-rw-r--r-- | app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/pipeline_schedules/_tabs.html.haml | 18 | ||||
-rw-r--r-- | app/views/projects/pipeline_schedules/destroy.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/pipeline_schedules/edit.html.haml | 7 | ||||
-rw-r--r-- | app/views/projects/pipeline_schedules/index.html.haml | 20 | ||||
-rw-r--r-- | app/views/projects/pipeline_schedules/new.html.haml | 7 | ||||
-rw-r--r-- | app/views/projects/pipeline_schedules/show.html.haml | 2 | ||||
-rw-r--r-- | app/views/projects/pipelines/_head.html.haml | 6 | ||||
-rw-r--r-- | config/routes/project.rb | 4 |
16 files changed, 189 insertions, 3 deletions
diff --git a/app/controllers/projects/pipeline_schedules_controller.rb b/app/controllers/projects/pipeline_schedules_controller.rb new file mode 100644 index 00000000000..fd03eab7340 --- /dev/null +++ b/app/controllers/projects/pipeline_schedules_controller.rb @@ -0,0 +1,63 @@ +class Projects::PipelineSchedulesController < Projects::ApplicationController + before_action :authorize_create_pipeline!, only: [:new, :create, :edit] + before_action :authorize_update_pipeline!, only: [:retry, :cancel] # TODO set this right, its own authorize method + before_action :pipeline_schedule, only: [:edit, :update, :destroy] + + # TODO test for N+1 queries + def index + @all_schedules = @project.pipeline_schedules.order('created_at DESC') + + @scope = params[:scope] + @schedules = + case @scope + when 'active' + @all_schedules.active + when 'inactive' + @all_schedules.inactive + else + @all_schedules + end + end + + def new + @pipeline_schedule = project.pipeline_schedules.new + end + + def create + @pipeline_schedule = Ci::CreatePipelineScheduleService. + new(@project, current_user, pipeline_schedule_params). + execute + + if @pipeline_schedule.persisted? + redirect_to project_pipeline_schedules_path(@project) + else + render :new + end + end + + def edit + end + + def update + if @pipeline_schedule.update_attributes(pipeline_schedule_params).valid? + redirect_to project_pipeline_schedules_path(@project) + else + render :edit + end + end + + def destroy + end + + private + + def pipeline_schedule + @pipeline_schedule = project.pipeline_schedules.find(params[:id]) + end + + def pipeline_schedule_params + params.require(:pipeline_schedule). + permit(:description, :cron, :cron_timezone, :ref). + reverse_merge(active: true, cron_timezone: 'UTC') + end +end diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb index e9b7cbbad6a..179a2a3648f 100644 --- a/app/helpers/gitlab_routing_helper.rb +++ b/app/helpers/gitlab_routing_helper.rb @@ -46,6 +46,10 @@ module GitlabRoutingHelper namespace_project_environments_path(project.namespace, project, *args) end + def project_pipeline_schedules_path(project, *args) + namespace_project_pipeline_schedules_path(project.namespace, project, *args) + end + def project_cycle_analytics_path(project, *args) namespace_project_cycle_analytics_path(project.namespace, project, *args) end diff --git a/app/models/ci/trigger_schedule.rb b/app/models/ci/trigger_schedule.rb index 012a18eb439..454c73ca9be 100644 --- a/app/models/ci/trigger_schedule.rb +++ b/app/models/ci/trigger_schedule.rb @@ -12,19 +12,31 @@ module Ci validates :cron, unless: :importing_or_inactive?, cron: true, presence: { unless: :importing_or_inactive? } validates :cron_timezone, cron_timezone: true, presence: { unless: :importing_or_inactive? } validates :ref, presence: { unless: :importing_or_inactive? } + validates :description, presence: true before_save :set_next_run_at scope :active, -> { where(active: true) } + scope :inactive, -> { where(active: false) } def importing_or_inactive? importing? || !active? end + def inactive? + !active? + end + def set_next_run_at self.next_run_at = Gitlab::Ci::CronParser.new(cron, cron_timezone).next_time_from(Time.now) end + def schedule_first_run! + if next_run_at < real_next_run + #TODO create a schedule service to be used here and in the worker + end + end + def schedule_next_run! save! # with set_next_run_at rescue ActiveRecord::RecordInvalid diff --git a/app/models/project.rb b/app/models/project.rb index a160efba912..707544f43a4 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -172,6 +172,7 @@ class Project < ActiveRecord::Base has_many :triggers, dependent: :destroy, class_name: 'Ci::Trigger' has_many :environments, dependent: :destroy has_many :deployments, dependent: :destroy + has_many :pipeline_schedules, class_name: 'Ci::TriggerSchedule' has_many :active_runners, -> { active }, through: :runner_projects, source: :runner, class_name: 'Ci::Runner' diff --git a/app/services/ci/create_pipeline_schedule_service.rb b/app/services/ci/create_pipeline_schedule_service.rb new file mode 100644 index 00000000000..53918cf6fd5 --- /dev/null +++ b/app/services/ci/create_pipeline_schedule_service.rb @@ -0,0 +1,18 @@ +module Ci + class CreatePipelineScheduleService < BaseService + def execute + trigger = project.triggers.create + schedule = project.pipeline_schedules.create(pipeline_schedule_params(trigger)) + + return schedule if schedule.errors.any? + + schedule.tap(&:schedule_first_run!) + end + + private + + def pipeline_schedule_params(trigger) + { trigger: trigger }.merge(params) + end + end +end diff --git a/app/services/ci/create_trigger_request_service.rb b/app/services/ci/create_trigger_request_service.rb index dca5aa9f5d7..8362f01ddb8 100644 --- a/app/services/ci/create_trigger_request_service.rb +++ b/app/services/ci/create_trigger_request_service.rb @@ -5,9 +5,8 @@ module Ci pipeline = Ci::CreatePipelineService.new(project, trigger.owner, ref: ref). execute(ignore_skip_ci: true, trigger_request: trigger_request) - if pipeline.persisted? - trigger_request - end + + trigger_request if pipeline.persisted? end end end diff --git a/app/views/projects/pipeline_schedules/_form.html.haml b/app/views/projects/pipeline_schedules/_form.html.haml new file mode 100644 index 00000000000..aded26fc7a1 --- /dev/null +++ b/app/views/projects/pipeline_schedules/_form.html.haml @@ -0,0 +1,21 @@ += form_for @pipeline_schedule, as: :pipeline_schedule, url: namespace_project_pipeline_schedules_path(@project.namespace, @project), html: { id: "new-pipeline-schedule-form", class: "form-horizontal js-pipeline-schedule-form js-requires-input" } do |f| + = form_errors(@pipeline_schedule) + .form-group + = f.label :description, 'Description', class: 'control-label' + .col-sm-10 + = f.text_field :description, class: 'form-control', required: true, autofocus: true + .form-group + = f.label :cron, 'Cron Pattern', class: 'control-label' + .col-sm-10 + = f.text_field :cron, class: 'form-control', required: false, autofocus: true, value: "0 0 * * *" + .form-group + = f.label :cron_timezone, 'Cron Timezone', class: 'control-label' + .col-sm-10 + = f.text_field :cron_timezone, class: 'form-control', required: false, autofocus: true, value: 'UTC' + .form-group + = f.label :ref, 'Branch', class: 'control-label' + .col-sm-10 + = f.text_field :ref, class: 'form-control', required: true, autofocus: true, value: @project.default_branch + .form-actions + = f.submit 'Create pipeline schedule', class: 'btn btn-create', tabindex: 3 + = link_to 'Cancel', project_pipeline_schedules_path(@project), class: 'btn btn-cancel' diff --git a/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml new file mode 100644 index 00000000000..6e6c21b4dd6 --- /dev/null +++ b/app/views/projects/pipeline_schedules/_pipeline_schedule.html.haml @@ -0,0 +1,2 @@ +%li + = pipeline_schedule.id diff --git a/app/views/projects/pipeline_schedules/_tabs.html.haml b/app/views/projects/pipeline_schedules/_tabs.html.haml new file mode 100644 index 00000000000..2a1fb16876a --- /dev/null +++ b/app/views/projects/pipeline_schedules/_tabs.html.haml @@ -0,0 +1,18 @@ +%ul.nav-links + %li{ class: active_when(scope.nil?) }> + = link_to schedule_path_proc.call(nil) do + All + %span.badge.js-totalbuilds-count + = number_with_delimiter(all_schedules.count(:id)) + + %li{ class: active_when(scope == 'active') }> + = link_to schedule_path_proc.call('active') do + Active + %span.badge + = number_with_delimiter(all_schedules.active.count(:id)) + + %li{ class: active_when(scope == 'inactive') }> + = link_to schedule_path_proc.call('inactive') do + Inactive + %span.badge + = number_with_delimiter(all_schedules.inactive.count(:id)) diff --git a/app/views/projects/pipeline_schedules/destroy.html.haml b/app/views/projects/pipeline_schedules/destroy.html.haml new file mode 100644 index 00000000000..72e70c002d7 --- /dev/null +++ b/app/views/projects/pipeline_schedules/destroy.html.haml @@ -0,0 +1,2 @@ +<h1>ScheduledPipelines#destroy</h1> +<p>Find me in app/views/scheduled_pipelines/destroy.html.erb</p> diff --git a/app/views/projects/pipeline_schedules/edit.html.haml b/app/views/projects/pipeline_schedules/edit.html.haml new file mode 100644 index 00000000000..e2eeb05365d --- /dev/null +++ b/app/views/projects/pipeline_schedules/edit.html.haml @@ -0,0 +1,7 @@ +- page_title "Edit", @pipeline_schedule.description, "Pipeline Schedule" + +%h3.page-title + Edit Pipeline Schedule #{@pipeline_schedule.id} +%hr + += render "form" diff --git a/app/views/projects/pipeline_schedules/index.html.haml b/app/views/projects/pipeline_schedules/index.html.haml new file mode 100644 index 00000000000..4d73f12fa04 --- /dev/null +++ b/app/views/projects/pipeline_schedules/index.html.haml @@ -0,0 +1,20 @@ +- @no_container = true +- page_title "Pipeline Schedules" += render "projects/pipelines/head" + +%div{ class: container_class } + .top-area + - schedule_path_proc = ->(scope) { project_pipeline_schedules_path(@project, scope: scope) } + = render "tabs", schedule_path_proc: schedule_path_proc, all_schedules: @all_schedules, scope: @scope + + .nav-controls + = link_to new_namespace_project_pipeline_schedule_path(@project.namespace, @project), class: 'btn btn-create' do + %span New Schedule + + - if @schedules.present? + %ul.content-list + = render partial: "pipeline_schedule", collection: @schedules + - else + .light-well + .nothing-here-block No schedules + diff --git a/app/views/projects/pipeline_schedules/new.html.haml b/app/views/projects/pipeline_schedules/new.html.haml new file mode 100644 index 00000000000..b89e170ad3c --- /dev/null +++ b/app/views/projects/pipeline_schedules/new.html.haml @@ -0,0 +1,7 @@ +- page_title "New Pipeline Schedule" + +%h3.page-title + Schedule a new pipeline +%hr + += render "form" diff --git a/app/views/projects/pipeline_schedules/show.html.haml b/app/views/projects/pipeline_schedules/show.html.haml new file mode 100644 index 00000000000..e1a32320f76 --- /dev/null +++ b/app/views/projects/pipeline_schedules/show.html.haml @@ -0,0 +1,2 @@ +<h1>ScheduledPipelines#show</h1> +<p>Find me in app/views/scheduled_pipelines/show.html.erb</p> diff --git a/app/views/projects/pipelines/_head.html.haml b/app/views/projects/pipelines/_head.html.haml index bc57f7f1c46..d1c72103c03 100644 --- a/app/views/projects/pipelines/_head.html.haml +++ b/app/views/projects/pipelines/_head.html.haml @@ -15,6 +15,12 @@ %span Jobs + - if project_nav_tab? :pipelines + = nav_link(controller: :pipeline_schedules) do + = link_to project_pipeline_schedules_path(@project), title: 'Schedules', class: 'shortcuts-builds' do + %span + Schedules + - if project_nav_tab? :environments = nav_link(controller: :environments) do = link_to project_environments_path(@project), title: 'Environments', class: 'shortcuts-environments' do diff --git a/config/routes/project.rb b/config/routes/project.rb index fa92202c1ea..b1edc78b289 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -127,6 +127,10 @@ constraints(ProjectUrlConstrainer.new) do end end + resources :pipeline_schedules, except: [:show], contrains: { id: /\d+/ } do + post :take_ownership + end + resources :environments, except: [:destroy] do member do post :stop |