Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/controllers/projects/builds_controller.rb9
-rw-r--r--app/models/ci/build.rb24
-rw-r--r--app/models/ci/pipeline.rb4
-rw-r--r--app/models/deployment.rb4
-rw-r--r--app/views/projects/ci/builds/_build.html.haml13
-rw-r--r--app/views/projects/ci/pipelines/_pipeline.html.haml34
-rw-r--r--app/views/projects/deployments/_deployment.html.haml2
-rw-r--r--app/views/projects/deployments/_playable.html.haml12
-rw-r--r--app/views/projects/environments/_environment.html.haml4
-rw-r--r--config/routes.rb1
-rw-r--r--lib/ci/gitlab_ci_yaml_processor.rb4
-rw-r--r--spec/lib/ci/gitlab_ci_yaml_processor_spec.rb2
12 files changed, 96 insertions, 17 deletions
diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb
index d7513d75f01..597cfa93712 100644
--- a/app/controllers/projects/builds_controller.rb
+++ b/app/controllers/projects/builds_controller.rb
@@ -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)
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index ffac3a22efc..81feca0088f 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -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
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index b468434866b..5aefe1d1694 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -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?
diff --git a/app/models/deployment.rb b/app/models/deployment.rb
index 520026c18dd..44dfb67552e 100644
--- a/app/models/deployment.rb
+++ b/app/models/deployment.rb
@@ -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
diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml
index e1b42b2cfa5..efedafefc38 100644
--- a/app/views/projects/ci/builds/_build.html.haml
+++ b/app/views/projects/ci/builds/_build.html.haml
@@ -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?
- = 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 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')
+
diff --git a/app/views/projects/ci/pipelines/_pipeline.html.haml b/app/views/projects/ci/pipelines/_pipeline.html.haml
index 0557d384e33..1285fce4930 100644
--- a/app/views/projects/ci/pipelines/_pipeline.html.haml
+++ b/app/views/projects/ci/pipelines/_pipeline.html.haml
@@ -57,18 +57,30 @@
%td.pipeline-actions
.controls.hidden-xs.pull-right
- artifacts = pipeline.builds.latest.select { |b| b.artifacts? }
- - if artifacts.present?
- .inline
- .btn-group
- %a.dropdown-toggle.btn.btn-default.build-artifacts{type: 'button', 'data-toggle' => 'dropdown'}
- = icon("download")
- %b.caret
- %ul.dropdown-menu.dropdown-menu-align-right
- - artifacts.each do |build|
+ - 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 download_namespace_project_build_artifacts_path(@project.namespace, @project, build), rel: 'nofollow' do
- = icon("download")
- %span Download '#{build.name}' artifacts
+ = link_to play_namespace_project_build_path(@project.namespace, @project, build), rel: 'nofollow' do
+ = icon("play")
+ %span= playable.name.titleize
+ - if artifacts.present?
+ .btn-group
+ %a.dropdown-toggle.btn.btn-default.build-artifacts{type: 'button', 'data-toggle' => 'dropdown'}
+ = icon("download")
+ %b.caret
+ %ul.dropdown-menu.dropdown-menu-align-right
+ - artifacts.each do |build|
+ %li
+ = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, build), rel: 'nofollow' do
+ = icon("download")
+ %span Download '#{build.name}' artifacts
- if can?(current_user, :update_pipeline, @project)
.cancel-retry-btns.inline
diff --git a/app/views/projects/deployments/_deployment.html.haml b/app/views/projects/deployments/_deployment.html.haml
index d08dd92f1f6..e430d195ea6 100644
--- a/app/views/projects/deployments/_deployment.html.haml
+++ b/app/views/projects/deployments/_deployment.html.haml
@@ -21,3 +21,5 @@
Retry
- else
Rollback
+
+ = render 'playable', deployment: deployment
diff --git a/app/views/projects/deployments/_playable.html.haml b/app/views/projects/deployments/_playable.html.haml
new file mode 100644
index 00000000000..02e4fb7974e
--- /dev/null
+++ b/app/views/projects/deployments/_playable.html.haml
@@ -0,0 +1,12 @@
+- 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
diff --git a/app/views/projects/environments/_environment.html.haml b/app/views/projects/environments/_environment.html.haml
index eafa246d05f..8e517196e27 100644
--- a/app/views/projects/environments/_environment.html.haml
+++ b/app/views/projects/environments/_environment.html.haml
@@ -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
diff --git a/config/routes.rb b/config/routes.rb
index 3160fd767b8..be651d8903f 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -750,6 +750,7 @@ Rails.application.routes.draw do
get :status
post :cancel
post :retry
+ post :play
post :erase
get :trace
get :raw
diff --git a/lib/ci/gitlab_ci_yaml_processor.rb b/lib/ci/gitlab_ci_yaml_processor.rb
index a48dc542b14..41449d720b3 100644
--- a/lib/ci/gitlab_ci_yaml_processor.rb
+++ b/lib/ci/gitlab_ci_yaml_processor.rb
@@ -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])
diff --git a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
index ad6587b4c25..d20fd4ab7dd 100644
--- a/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
+++ b/spec/lib/ci/gitlab_ci_yaml_processor_spec.rb
@@ -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