Commit 7d0fe1f0 authored by Kamil Trzcinski's avatar Kamil Trzcinski

Add implementation of manual actions

parent 4e898b9b
......@@ -57,6 +57,15 @@ class Projects::BuildsController < Projects::ApplicationController
redirect_to build_path(build)
end
def play
unless @build.playable?
return render_404
end
build = @build.play(current_user)
redirect_to build_path(build)
end
def cancel
@build.cancel
redirect_to build_path(@build)
......
......@@ -15,6 +15,7 @@ module Ci
scope :with_artifacts, ->() { where.not(artifacts_file: nil) }
scope :with_expired_artifacts, ->() { with_artifacts.where('artifacts_expire_at < ?', Time.now) }
scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) }
scope :manual_actions, ->() { where(when: :manual).without_created }
mount_uploader :artifacts_file, ArtifactUploader
mount_uploader :artifacts_metadata, ArtifactUploader
......@@ -91,6 +92,29 @@ module Ci
end
end
def manual?
self.when == 'manual'
end
def playable_actions
pipeline.playable_actions
end
def playable?
project.builds_enabled? && commands.present? && manual?
end
def play(current_user = nil)
if skipped?
# We can run skipped build
new_build.user = current_user
new_build.queue
else
# Otherwise we need to create a duplicate
Ci::Build.retry(self, current_user)
end
end
def retryable?
project.builds_enabled? && commands.present? && complete?
end
......
......@@ -65,6 +65,10 @@ module Ci
!tag?
end
def playable_actions
builds.manual_actions.latest
end
def retryable?
builds.latest.any? do |build|
build.failed? && build.retryable?
......
......@@ -32,4 +32,8 @@ class Deployment < ActiveRecord::Base
def keep_around_commit
project.repository.keep_around(self.sha)
end
def playable_actions
deployable.try(:playable_actions)
end
end
......@@ -39,6 +39,8 @@
%span.label.label-danger allowed to fail
- if defined?(retried) && retried
%span.label.label-warning retried
- if build.manual?
%span.label.label-info manual
- if defined?(runner) && runner
......@@ -79,6 +81,11 @@
- if build.active?
= link_to cancel_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Cancel', class: 'btn btn-build' do
= icon('remove', class: 'cred')
- elsif defined?(allow_retry) && allow_retry && build.retryable?
- elsif defined?(allow_retry) && allow_retry
- if build.retryable?
= link_to retry_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Retry', class: 'btn btn-build' do
= icon('repeat')
- elsif build.playable?
= link_to play_namespace_project_build_path(build.project.namespace, build.project, build, return_to: request.original_url), method: :post, title: 'Retry', class: 'btn btn-build' do
= icon('play')
......@@ -57,8 +57,20 @@
%td.pipeline-actions
.controls.hidden-xs.pull-right
- artifacts = pipeline.builds.latest.select { |b| b.artifacts? }
- playable = pipeline.playable_actions
- if artifacts.present? || playable.any?
.btn-group.inline
- if playable.any?
.btn-group
%a.dropdown-toggle.btn.btn-default{type: 'button', 'data-toggle' => 'dropdown'}
= icon("play")
%b.caret
%ul.dropdown-menu.dropdown-menu-align-right
%li
= link_to play_namespace_project_build_path(@project.namespace, @project, build), rel: 'nofollow' do
= icon("play")
%span= playable.name.titleize
- if artifacts.present?
.inline
.btn-group
%a.dropdown-toggle.btn.btn-default.build-artifacts{type: 'button', 'data-toggle' => 'dropdown'}
= icon("download")
......
......@@ -21,3 +21,5 @@
Retry
- else
Rollback
= render 'playable', deployment: deployment
- playable = deployment.playable_actions
- if playable.any?
.btn-group.inline
.btn-group
%a.dropdown-toggle.btn.btn-default{type: 'button', 'data-toggle' => 'dropdown'}
= icon("play")
%b.caret
%ul.dropdown-menu.dropdown-menu-align-right
%li
= link_to play_namespace_project_build_path(@project.namespace, @project, build), rel: 'nofollow' do
= icon("play")
%span= playable.name.titleize
......@@ -15,3 +15,7 @@
%td
- if last_deployment
#{time_ago_with_tooltip(last_deployment.created_at)}
%td
- if can?(current_user, :create_deployment, last_deployment) && last_deployment.deployable
= render 'projects/deployments/playable', deployment: last_deployment
......@@ -750,6 +750,7 @@ Rails.application.routes.draw do
get :status
post :cancel
post :retry
post :play
post :erase
get :trace
get :raw
......
......@@ -194,8 +194,8 @@ module Ci
raise ValidationError, "#{name} job: allow_failure parameter should be an boolean"
end
if job[:when] && !job[:when].in?(%w[on_success on_failure always])
raise ValidationError, "#{name} job: when parameter should be on_success, on_failure or always"
if job[:when] && !job[:when].in?(%w[on_success on_failure always manual])
raise ValidationError, "#{name} job: when parameter should be on_success, on_failure, always or manual"
end
if job[:environment] && !validate_environment(job[:environment])
......
......@@ -1141,7 +1141,7 @@ EOT
config = YAML.dump({ rspec: { script: "test", when: 1 } })
expect do
GitlabCiYamlProcessor.new(config, path)
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: when parameter should be on_success, on_failure or always")
end.to raise_error(GitlabCiYamlProcessor::ValidationError, "rspec job: when parameter should be on_success, on_failure, always or manual")
end
it "returns errors if job artifacts:name is not an a string" do
......
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