diff options
author | Kamil Trzcinski <ayufan@ayufan.eu> | 2016-06-10 23:36:54 +0200 |
---|---|---|
committer | Kamil Trzcinski <ayufan@ayufan.eu> | 2016-06-10 23:36:54 +0200 |
commit | 907c0e6796b69f9577c147dd489cf55748c749ac (patch) | |
tree | c4db6a3d3785fa845be98447eb4303b548ab7809 /app | |
parent | cf7da039bedcad5163ce9deedccc94206d4c485a (diff) | |
download | gitlab-ce-907c0e6796b69f9577c147dd489cf55748c749ac.tar.gz |
Added initial version of deployments
Diffstat (limited to 'app')
-rw-r--r-- | app/controllers/projects/builds_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/projects/commit_controller.rb | 2 | ||||
-rw-r--r-- | app/controllers/projects/environments_controller.rb | 14 | ||||
-rw-r--r-- | app/helpers/projects_helper.rb | 4 | ||||
-rw-r--r-- | app/models/ability.rb | 12 | ||||
-rw-r--r-- | app/models/ci/build.rb | 13 | ||||
-rw-r--r-- | app/models/deployment.rb | 25 | ||||
-rw-r--r-- | app/models/environment.rb | 11 | ||||
-rw-r--r-- | app/models/project.rb | 2 | ||||
-rw-r--r-- | app/services/ci/create_builds_service.rb | 3 | ||||
-rw-r--r-- | app/services/create_deployment_service.rb | 45 | ||||
-rw-r--r-- | app/views/projects/deployments/_deployment.html.haml | 32 | ||||
-rw-r--r-- | app/views/projects/environments/_environment.html.haml | 68 | ||||
-rw-r--r-- | app/views/projects/environments/index.html.haml | 38 | ||||
-rw-r--r-- | app/views/projects/environments/show.html.haml | 46 | ||||
-rw-r--r-- | app/views/projects/pipelines/_head.html.haml | 6 |
16 files changed, 217 insertions, 106 deletions
diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb index 14c82826342..ef3051d7519 100644 --- a/app/controllers/projects/builds_controller.rb +++ b/app/controllers/projects/builds_controller.rb @@ -51,7 +51,7 @@ class Projects::BuildsController < Projects::ApplicationController return render_404 end - build = Ci::Build.retry(@build) + build = Ci::Build.retry(@build, current_user) redirect_to build_path(build) end diff --git a/app/controllers/projects/commit_controller.rb b/app/controllers/projects/commit_controller.rb index 20637fa46fe..6751737d15e 100644 --- a/app/controllers/projects/commit_controller.rb +++ b/app/controllers/projects/commit_controller.rb @@ -46,7 +46,7 @@ class Projects::CommitController < Projects::ApplicationController def retry_builds ci_builds.latest.failed.each do |build| if build.retryable? - Ci::Build.retry(build) + Ci::Build.retry(build, current_user) end end diff --git a/app/controllers/projects/environments_controller.rb b/app/controllers/projects/environments_controller.rb index f5af24ed217..722954a6b78 100644 --- a/app/controllers/projects/environments_controller.rb +++ b/app/controllers/projects/environments_controller.rb @@ -1,17 +1,19 @@ class Projects::EnvironmentsController < Projects::ApplicationController layout 'project' + before_action :authorize_read_environment! + before_action :environment, only: [:show] def index - @environments = project.builds.where.not(environment: nil).pluck(:environment).uniq - @environments = @environments.map { |env| build_for_env(env) }.compact + @environments = project.environments end def show - @environment = params[:id].to_s - @builds = project.builds.where.not(status: ["manual"]).where(environment: params[:id].to_s).order(id: :desc).page(params[:page]).per(30) end - def build_for_env(environment) - project.builds.success.order(id: :desc).find_by(environment: environment) + private + + def environment + @environment ||= project.environments.find(params[:id].to_s) + @environment || render_404 end end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index 5e5d170a9f3..2ad7520b63a 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -156,6 +156,10 @@ module ProjectsHelper nav_tabs << :container_registry end + if can?(current_user, :read_environment, project) + nav_tabs << :environments + end + if can?(current_user, :admin_project, project) nav_tabs << :settings end diff --git a/app/models/ability.rb b/app/models/ability.rb index 44515550d9e..747f250ff4f 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -228,6 +228,8 @@ class Ability :read_build, :read_container_image, :read_pipeline, + :read_environment, + :read_deployment ] end @@ -246,6 +248,10 @@ class Ability :push_code, :create_container_image, :update_container_image, + :create_environment, + :update_environment, + :create_deployment, + :update_deployment, ] end @@ -273,7 +279,9 @@ class Ability :admin_commit_status, :admin_build, :admin_container_image, - :admin_pipeline + :admin_pipeline, + :admin_environment, + :admin_deployment ] end @@ -317,6 +325,8 @@ class Ability unless project.builds_enabled rules += named_abilities('build') rules += named_abilities('pipeline') + rules += named_abilities('environment') + rules += named_abilities('deployment') end unless project.container_registry_enabled diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 6a64ca451f7..60202525727 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -38,7 +38,7 @@ module Ci new_build.save end - def retry(build) + def retry(build, user = nil) new_build = Ci::Build.new(status: 'pending') new_build.ref = build.ref new_build.tag = build.tag @@ -52,6 +52,7 @@ module Ci new_build.stage = build.stage new_build.stage_idx = build.stage_idx new_build.trigger_request = build.trigger_request + new_build.user = user new_build.save MergeRequests::AddTodoWhenBuildFailsService.new(build.project, nil).close(new_build) new_build @@ -73,6 +74,12 @@ module Ci build.update_coverage build.execute_hooks end + + after_transition any: :success do |build| + if build.environment.present? + CreateDeploymentService.new(build.project, build.user, environment: build.environment).execute(build) + end + end end def retryable? @@ -83,10 +90,6 @@ module Ci !self.pipeline.statuses.latest.include?(self) end - def retry - Ci::Build.retry(self) - end - def depends_on_builds # Get builds of the same type latest_builds = self.pipeline.builds.latest diff --git a/app/models/deployment.rb b/app/models/deployment.rb new file mode 100644 index 00000000000..7cdfc740441 --- /dev/null +++ b/app/models/deployment.rb @@ -0,0 +1,25 @@ +class Deployment < ActiveRecord::Base + include InternalId + + belongs_to :project + belongs_to :environment + belongs_to :user + belongs_to :deployable, polymorphic: true + + validates_presence_of :sha + validates_presence_of :ref + + delegate :name, to: :environment, prefix: true + + def commit + project.commit(sha) + end + + def commit_title + commit.try(:title) + end + + def short_sha + Commit::truncate_sha(sha) + end +end diff --git a/app/models/environment.rb b/app/models/environment.rb new file mode 100644 index 00000000000..623404ba634 --- /dev/null +++ b/app/models/environment.rb @@ -0,0 +1,11 @@ +class Environment < ActiveRecord::Base + belongs_to :project + + has_many :deployments + + validates_presence_of :name + + def last_deployment + deployments.last + end +end diff --git a/app/models/project.rb b/app/models/project.rb index e2f7ffe493c..be714ea41fd 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -125,6 +125,8 @@ class Project < ActiveRecord::Base has_many :runners, through: :runner_projects, source: :runner, class_name: 'Ci::Runner' has_many :variables, dependent: :destroy, class_name: 'Ci::Variable', foreign_key: :gl_project_id has_many :triggers, dependent: :destroy, class_name: 'Ci::Trigger', foreign_key: :gl_project_id + has_many :environments, dependent: :destroy + has_many :deployments, dependent: :destroy accepts_nested_attributes_for :variables, allow_destroy: true diff --git a/app/services/ci/create_builds_service.rb b/app/services/ci/create_builds_service.rb index 64bcdac5c65..3a74ae094e8 100644 --- a/app/services/ci/create_builds_service.rb +++ b/app/services/ci/create_builds_service.rb @@ -29,7 +29,8 @@ module Ci :options, :allow_failure, :stage, - :stage_idx) + :stage_idx, + :environment) build_attrs.merge!(ref: @pipeline.ref, tag: @pipeline.tag, diff --git a/app/services/create_deployment_service.rb b/app/services/create_deployment_service.rb new file mode 100644 index 00000000000..f745471913f --- /dev/null +++ b/app/services/create_deployment_service.rb @@ -0,0 +1,45 @@ +require_relative 'base_service' + +class CreateDeploymentService < BaseService + def execute(deployable) + environment = find_or_create_environment(params[:environment]) + + deployment = create_deployment(environment, deployable) + if deployment.persisted? + success(deployment) + else + error(deployment.errors) + end + end + + private + + def find_or_create_environment(environment) + find_environment(environment) || create_environment(environment) + end + + def create_environment(environment) + project.environments.create(name: environment) + end + + def find_environment(environment) + project.environments.find_by(name: environment) + end + + def create_deployment(environment, deployable) + environment.deployments.create( + project: project, + ref: build.ref, + tag: build.tag, + sha: build.sha, + user: current_user, + deployable: deployable, + ) + end + + def success(deployment) + out = super() + out[:deployment] = deployment + out + end +end diff --git a/app/views/projects/deployments/_deployment.html.haml b/app/views/projects/deployments/_deployment.html.haml new file mode 100644 index 00000000000..363c394d6d3 --- /dev/null +++ b/app/views/projects/deployments/_deployment.html.haml @@ -0,0 +1,32 @@ +%tr.deployment + %td + %strong= "##{environment.id}" + + %td + %div.branch-commit + - if deployment.ref + = link_to last.ref, namespace_project_commits_path(@project.namespace, @project, deployment.ref), class: "monospace" + · + = link_to deployment.short_sha, namespace_project_commit_path(@project.namespace, @project, deployment.sha), class: "commit-id monospace" + + %p + %span + - if commit_title = deployment.commit_title + = link_to_gfm commit_title, namespace_project_commit_path(@project.namespace, @project, deployment.sha), class: "commit-row-message" + - else + Cant find HEAD commit for this branch + + %td + - if deployment.deployable + = link_to [@project.namespace.becomes(Namespace), @project, deployment.deployable], class: "monospace" do + = "#{deployment.deployable.name} (##{deployment.deployable.id})" + + %td + %p + %i.fa.fa-calendar + + #{time_ago_with_tooltip(deployment.created_at)} + + %td + - if can?(current_user, :update_deployment, @project) && deployment.deployable + = link_to [@project.namespace.becomes(Namespace), @project, deployment.deployable, :retry], method: :post, title: 'Retry', class: 'btn btn-build' diff --git a/app/views/projects/environments/_environment.html.haml b/app/views/projects/environments/_environment.html.haml index e3216aea6cd..a4c88fface2 100644 --- a/app/views/projects/environments/_environment.html.haml +++ b/app/views/projects/environments/_environment.html.haml @@ -1,58 +1,32 @@ -%tr.commit - - commit = build.commit - - status = build.status +- last_deployment = environment.last_deployment +%tr.environment %td %strong - = link_to build.environment, namespace_project_environment_path(@project.namespace, @project, build.environment), class: "monospace" - - %td.commit-link - = link_to namespace_project_pipeline_path(@project.namespace, @project, commit.id), class: "ci-status ci-#{commit.status}" do - = ci_icon_for_status(commit.status) - %strong ##{commit.id} - - %td.commit-link - = link_to namespace_project_build_path(@project.namespace, @project, build.id), class: "ci-status ci-#{build.status}" do - = ci_icon_for_status(build.status) - %strong ##{build.id} + = link_to environment.name, namespace_project_environment_path(@project.namespace, @project, environment), class: "monospace" %td - %div.branch-commit - - if commit.ref - = link_to commit.ref, namespace_project_commits_path(@project.namespace, @project, commit.ref), class: "monospace" - · - = link_to commit.short_sha, namespace_project_commit_path(@project.namespace, @project, commit.sha), class: "commit-id monospace" + - if last_deployment + %div.branch-commit + - if last_deployment.ref + = link_to last.ref, namespace_project_commits_path(@project.namespace, @project, last_deployment.ref), class: "monospace" + · + = link_to last_deployment.short_sha, namespace_project_commit_path(@project.namespace, @project, last_deployment.sha), class: "commit-id monospace" + %p + %span + - if commit_title = last_deployment.commit_title + = link_to_gfm commit_title, namespace_project_commit_path(@project.namespace, @project, last_deployment.sha), class: "commit-row-message" + - else + Cant find HEAD commit for this branch + - else %p - %span - - if commit_data = commit.commit_data - = link_to_gfm commit_data.title, namespace_project_commit_path(@project.namespace, @project, commit_data.id), class: "commit-row-message" - - else - Cant find HEAD commit for this branch + No deployments yet %td - - if build.started_at && build.finished_at - %p - %i.fa.fa-clock-o - - #{duration_in_words(build.finished_at, build.started_at)} - - if build.finished_at - %p - %i.fa.fa-calendar - - #{time_ago_with_tooltip(build.finished_at)} + %p + %i.fa.fa-calendar + + #{time_ago_with_tooltip(last_deployment.created_at)} %td - .controls.hidden-xs.pull-right - - manual = commit.builds.latest.manual_actions.to_a - - if manual.any? - .dropdown.inline - %button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'} - = icon('play') - %b.caret - %ul.dropdown-menu.dropdown-menu-align-right - - manual.each do |manual_build| - %li - = link_to '#', rel: 'nofollow' do - %i.fa.fa-play - %span #{manual_build.name} diff --git a/app/views/projects/environments/index.html.haml b/app/views/projects/environments/index.html.haml index e94bc97be9d..40d35ef3881 100644 --- a/app/views/projects/environments/index.html.haml +++ b/app/views/projects/environments/index.html.haml @@ -1,22 +1,22 @@ +- @no_container = true - page_title "Environments" -= render "header_title" += render "projects/pipelines/head" -.gray-content-block - Environments for this project +%div{ class: (container_class) } + .gray-content-block + Environments for this project -%ul.content-list - - if @environments.blank? - %li - .nothing-here-block No environments to show - - else - .table-holder - %table.table.builds - %tbody - %th Environment - %th Pipeline ID - %th Build ID - %th Changes - %th - %th - - @environments.each do |build| - = render "environment", build: build + %ul.content-list + - if @environments.blank? + %li + .nothing-here-block No environments to show + - else + .table-holder + %table.table.builds + %tbody + %th Environment + %th Last deployment + %th Date + %th + - @environments.each do |environment| + = render 'environment', environment: environment diff --git a/app/views/projects/environments/show.html.haml b/app/views/projects/environments/show.html.haml index ce2d9cf7d71..de5e686044f 100644 --- a/app/views/projects/environments/show.html.haml +++ b/app/views/projects/environments/show.html.haml @@ -1,30 +1,26 @@ +- @no_container = true - page_title "Environments" += render "projects/pipelines/head" -= render "header_title" +%div{ class: (container_class) } + .gray-content-block + Latest deployments for + %strong= @environment.name -.gray-content-block - Latest deployments for - %strong - = @environment + %ul.content-list + - if @deployments.blank? + %li + .nothing-here-block No deployment for specific environment + - else + .table-holder + %table.table.builds + %thead + %tr + %th Commit + %th Context + %th Date + %th -%ul.content-list - - if @builds.blank? - %li - .nothing-here-block No builds to show for specific environment - - else - .table-holder - %table.table.builds - %thead - %tr - %th Status - %th Build ID - %th Commit - %th Ref - %th Name - %th Duration - %th Finished at - %th + = render @deployments - = render @builds, commit_sha: true, ref: true, allow_retry: true - - = paginate @builds, theme: 'gitlab' + = paginate @deployments, theme: 'gitlab' diff --git a/app/views/projects/pipelines/_head.html.haml b/app/views/projects/pipelines/_head.html.haml index f278d4e0538..3562d91dfbd 100644 --- a/app/views/projects/pipelines/_head.html.haml +++ b/app/views/projects/pipelines/_head.html.haml @@ -13,3 +13,9 @@ %span Builds %span.badge.count.builds_counter= number_with_delimiter(@project.running_or_pending_build_count) + + - if project_nav_tab? :environments + = nav_link(controller: %w(environments)) do + = link_to project_environments_path(@project), title: 'Environments', class: 'shortcuts-environments' do + %span + Environments |