From 71777a4a184945d6b58170af55d9fd9fef821ac9 Mon Sep 17 00:00:00 2001 From: Lin Jen-Shin Date: Tue, 16 May 2017 19:41:15 +0800 Subject: Rename BuildsController to JobsController Rename other URL generators admin_builds_path -> admin_jobs_path Fix tests and more renaming Fix more tests Also change build_id to job_id in the controller --- app/controllers/admin/builds_controller.rb | 25 -- app/controllers/admin/jobs_controller.rb | 25 ++ app/controllers/projects/artifacts_controller.rb | 4 +- app/controllers/projects/builds_controller.rb | 131 ------ app/controllers/projects/jobs_controller.rb | 131 ++++++ app/helpers/blob_helper.rb | 2 +- app/helpers/builds_helper.rb | 8 +- app/helpers/gitlab_routing_helper.rb | 16 +- app/models/ci/build.rb | 6 + app/serializers/analytics_build_entity.rb | 2 +- app/serializers/build_action_entity.rb | 2 +- app/serializers/build_artifact_entity.rb | 2 +- app/serializers/build_entity.rb | 6 +- app/validators/dynamic_path_validator.rb | 1 + app/views/admin/builds/index.html.haml | 18 - app/views/admin/dashboard/_head.html.haml | 2 +- app/views/admin/jobs/index.html.haml | 18 + app/views/admin/runners/show.html.haml | 2 +- app/views/layouts/nav/_project.html.haml | 2 +- app/views/notify/links/ci/builds/_build.html.haml | 2 +- app/views/notify/links/ci/builds/_build.text.erb | 2 +- .../projects/artifacts/_tree_directory.html.haml | 2 +- app/views/projects/artifacts/_tree_file.html.haml | 2 +- app/views/projects/artifacts/browse.html.haml | 8 +- app/views/projects/artifacts/file.html.haml | 8 +- app/views/projects/builds/_header.html.haml | 31 -- app/views/projects/builds/_sidebar.html.haml | 142 ------- app/views/projects/builds/_table.html.haml | 25 -- app/views/projects/builds/_user.html.haml | 7 - app/views/projects/builds/index.html.haml | 23 -- app/views/projects/builds/show.html.haml | 86 ---- app/views/projects/ci/builds/_build.html.haml | 10 +- app/views/projects/jobs/_header.html.haml | 31 ++ app/views/projects/jobs/_sidebar.html.haml | 142 +++++++ app/views/projects/jobs/_table.html.haml | 25 ++ app/views/projects/jobs/_user.html.haml | 7 + app/views/projects/jobs/index.html.haml | 23 ++ app/views/projects/jobs/show.html.haml | 86 ++++ app/views/projects/pipelines/_head.html.haml | 2 +- app/views/projects/pipelines/_with_tabs.html.haml | 2 +- .../initializers/relative_naming_ci_namespace.rb | 2 +- config/routes/admin.rb | 2 +- config/routes/project.rb | 2 +- features/steps/shared/builds.rb | 6 +- lib/gitlab/ci/status/build/cancelable.rb | 2 +- lib/gitlab/ci/status/build/common.rb | 2 +- lib/gitlab/ci/status/build/play.rb | 2 +- lib/gitlab/ci/status/build/retryable.rb | 2 +- lib/gitlab/ci/status/build/stop.rb | 2 +- .../projects/artifacts_controller_spec.rb | 48 +-- .../controllers/projects/builds_controller_spec.rb | 446 --------------------- .../projects/environments_controller_spec.rb | 2 +- spec/controllers/projects/jobs_controller_spec.rb | 446 +++++++++++++++++++++ spec/features/admin/admin_builds_spec.rb | 16 +- .../merge_requests/mini_pipeline_graph_spec.rb | 2 +- spec/features/projects/artifacts/file_spec.rb | 2 +- spec/features/projects/builds_spec.rb | 71 ++-- .../security/project/internal_access_spec.rb | 6 +- .../security/project/private_access_spec.rb | 6 +- .../security/project/public_access_spec.rb | 6 +- spec/javascripts/build_spec.js | 2 +- spec/javascripts/fixtures/builds.rb | 33 -- spec/javascripts/fixtures/jobs.rb | 33 ++ spec/javascripts/lib/utils/common_utils_spec.js | 2 +- spec/lib/gitlab/ci/status/build/common_spec.rb | 2 +- spec/serializers/build_action_entity_spec.rb | 12 +- spec/serializers/build_artifact_entity_spec.rb | 10 +- spec/views/ci/status/_badge.html.haml_spec.rb | 2 +- .../views/projects/builds/_build.html.haml_spec.rb | 28 -- .../_generic_commit_status.html.haml_spec.rb | 28 -- spec/views/projects/builds/show.html.haml_spec.rb | 293 -------------- spec/views/projects/jobs/_build.html.haml_spec.rb | 28 ++ .../jobs/_generic_commit_status.html.haml_spec.rb | 28 ++ spec/views/projects/jobs/show.html.haml_spec.rb | 293 ++++++++++++++ 74 files changed, 1472 insertions(+), 1464 deletions(-) delete mode 100644 app/controllers/admin/builds_controller.rb create mode 100644 app/controllers/admin/jobs_controller.rb delete mode 100644 app/controllers/projects/builds_controller.rb create mode 100644 app/controllers/projects/jobs_controller.rb delete mode 100644 app/views/admin/builds/index.html.haml create mode 100644 app/views/admin/jobs/index.html.haml delete mode 100644 app/views/projects/builds/_header.html.haml delete mode 100644 app/views/projects/builds/_sidebar.html.haml delete mode 100644 app/views/projects/builds/_table.html.haml delete mode 100644 app/views/projects/builds/_user.html.haml delete mode 100644 app/views/projects/builds/index.html.haml delete mode 100644 app/views/projects/builds/show.html.haml create mode 100644 app/views/projects/jobs/_header.html.haml create mode 100644 app/views/projects/jobs/_sidebar.html.haml create mode 100644 app/views/projects/jobs/_table.html.haml create mode 100644 app/views/projects/jobs/_user.html.haml create mode 100644 app/views/projects/jobs/index.html.haml create mode 100644 app/views/projects/jobs/show.html.haml delete mode 100644 spec/controllers/projects/builds_controller_spec.rb create mode 100644 spec/controllers/projects/jobs_controller_spec.rb delete mode 100644 spec/javascripts/fixtures/builds.rb create mode 100644 spec/javascripts/fixtures/jobs.rb delete mode 100644 spec/views/projects/builds/_build.html.haml_spec.rb delete mode 100644 spec/views/projects/builds/_generic_commit_status.html.haml_spec.rb delete mode 100644 spec/views/projects/builds/show.html.haml_spec.rb create mode 100644 spec/views/projects/jobs/_build.html.haml_spec.rb create mode 100644 spec/views/projects/jobs/_generic_commit_status.html.haml_spec.rb create mode 100644 spec/views/projects/jobs/show.html.haml_spec.rb diff --git a/app/controllers/admin/builds_controller.rb b/app/controllers/admin/builds_controller.rb deleted file mode 100644 index 88f3c0e2fd4..00000000000 --- a/app/controllers/admin/builds_controller.rb +++ /dev/null @@ -1,25 +0,0 @@ -class Admin::BuildsController < Admin::ApplicationController - def index - @scope = params[:scope] - @all_builds = Ci::Build - @builds = @all_builds.order('created_at DESC') - @builds = - case @scope - when 'pending' - @builds.pending.reverse_order - when 'running' - @builds.running.reverse_order - when 'finished' - @builds.finished - else - @builds - end - @builds = @builds.page(params[:page]).per(30) - end - - def cancel_all - Ci::Build.running_or_pending.each(&:cancel) - - redirect_to admin_builds_path - end -end diff --git a/app/controllers/admin/jobs_controller.rb b/app/controllers/admin/jobs_controller.rb new file mode 100644 index 00000000000..5162273ef8a --- /dev/null +++ b/app/controllers/admin/jobs_controller.rb @@ -0,0 +1,25 @@ +class Admin::JobsController < Admin::ApplicationController + def index + @scope = params[:scope] + @all_builds = Ci::Build + @builds = @all_builds.order('created_at DESC') + @builds = + case @scope + when 'pending' + @builds.pending.reverse_order + when 'running' + @builds.running.reverse_order + when 'finished' + @builds.finished + else + @builds + end + @builds = @builds.page(params[:page]).per(30) + end + + def cancel_all + Ci::Build.running_or_pending.each(&:cancel) + + redirect_to admin_jobs_path + end +end diff --git a/app/controllers/projects/artifacts_controller.rb b/app/controllers/projects/artifacts_controller.rb index 1224e9503c9..b46a33604ff 100644 --- a/app/controllers/projects/artifacts_controller.rb +++ b/app/controllers/projects/artifacts_controller.rb @@ -46,7 +46,7 @@ class Projects::ArtifactsController < Projects::ApplicationController def keep build.keep_artifacts! - redirect_to namespace_project_build_path(project.namespace, project, build) + redirect_to namespace_project_job_path(project.namespace, project, build) end def latest_succeeded @@ -79,7 +79,7 @@ class Projects::ArtifactsController < Projects::ApplicationController end def build_from_id - project.builds.find_by(id: params[:build_id]) if params[:build_id] + project.builds.find_by(id: params[:job_id]) if params[:job_id] end def build_from_ref diff --git a/app/controllers/projects/builds_controller.rb b/app/controllers/projects/builds_controller.rb deleted file mode 100644 index dfaaea71b9c..00000000000 --- a/app/controllers/projects/builds_controller.rb +++ /dev/null @@ -1,131 +0,0 @@ -class Projects::BuildsController < Projects::ApplicationController - before_action :build, except: [:index, :cancel_all] - - before_action :authorize_read_build!, - only: [:index, :show, :status, :raw, :trace] - before_action :authorize_update_build!, - except: [:index, :show, :status, :raw, :trace, :cancel_all] - - layout 'project' - - def index - @scope = params[:scope] - @all_builds = project.builds.relevant - @builds = @all_builds.order('created_at DESC') - @builds = - case @scope - when 'pending' - @builds.pending.reverse_order - when 'running' - @builds.running.reverse_order - when 'finished' - @builds.finished - else - @builds - end - @builds = @builds.includes([ - { pipeline: :project }, - :project, - :tags - ]) - @builds = @builds.page(params[:page]).per(30) - end - - def cancel_all - return access_denied! unless can?(current_user, :update_build, project) - - @project.builds.running_or_pending.each do |build| - build.cancel if can?(current_user, :update_build, build) - end - - redirect_to namespace_project_builds_path(project.namespace, project) - end - - def show - @builds = @project.pipelines.find_by_sha(@build.sha).builds.order('id DESC') - @builds = @builds.where("id not in (?)", @build.id) - @pipeline = @build.pipeline - end - - def trace - build.trace.read do |stream| - respond_to do |format| - format.json do - result = { - id: @build.id, status: @build.status, complete: @build.complete? - } - - if stream.valid? - stream.limit - state = params[:state].presence - trace = stream.html_with_state(state) - result.merge!(trace.to_h) - end - - render json: result - end - end - end - end - - def retry - return respond_422 unless @build.retryable? - - build = Ci::Build.retry(@build, current_user) - redirect_to build_path(build) - end - - def play - return respond_422 unless @build.playable? - - build = @build.play(current_user) - redirect_to build_path(build) - end - - def cancel - return respond_422 unless @build.cancelable? - - @build.cancel - redirect_to build_path(@build) - end - - def status - render json: BuildSerializer - .new(project: @project, current_user: @current_user) - .represent_status(@build) - end - - def erase - if @build.erase(erased_by: current_user) - redirect_to namespace_project_build_path(project.namespace, project, @build), - notice: "Build has been successfully erased!" - else - respond_422 - end - end - - def raw - build.trace.read do |stream| - if stream.file? - send_file stream.path, type: 'text/plain; charset=utf-8', disposition: 'inline' - else - render_404 - end - end - end - - private - - def authorize_update_build! - return access_denied! unless can?(current_user, :update_build, build) - end - - def build - @build ||= project.builds.find(params[:id]) - .present(current_user: current_user) - end - - def build_path(build) - namespace_project_build_path(build.project.namespace, build.project, build) - end -end diff --git a/app/controllers/projects/jobs_controller.rb b/app/controllers/projects/jobs_controller.rb new file mode 100644 index 00000000000..d2cd1cfdab8 --- /dev/null +++ b/app/controllers/projects/jobs_controller.rb @@ -0,0 +1,131 @@ +class Projects::JobsController < Projects::ApplicationController + before_action :build, except: [:index, :cancel_all] + + before_action :authorize_read_build!, + only: [:index, :show, :status, :raw, :trace] + before_action :authorize_update_build!, + except: [:index, :show, :status, :raw, :trace, :cancel_all] + + layout 'project' + + def index + @scope = params[:scope] + @all_builds = project.builds.relevant + @builds = @all_builds.order('created_at DESC') + @builds = + case @scope + when 'pending' + @builds.pending.reverse_order + when 'running' + @builds.running.reverse_order + when 'finished' + @builds.finished + else + @builds + end + @builds = @builds.includes([ + { pipeline: :project }, + :project, + :tags + ]) + @builds = @builds.page(params[:page]).per(30) + end + + def cancel_all + return access_denied! unless can?(current_user, :update_build, project) + + @project.builds.running_or_pending.each do |build| + build.cancel if can?(current_user, :update_build, build) + end + + redirect_to namespace_project_jobs_path(project.namespace, project) + end + + def show + @builds = @project.pipelines.find_by_sha(@build.sha).builds.order('id DESC') + @builds = @builds.where("id not in (?)", @build.id) + @pipeline = @build.pipeline + end + + def trace + build.trace.read do |stream| + respond_to do |format| + format.json do + result = { + id: @build.id, status: @build.status, complete: @build.complete? + } + + if stream.valid? + stream.limit + state = params[:state].presence + trace = stream.html_with_state(state) + result.merge!(trace.to_h) + end + + render json: result + end + end + end + end + + def retry + return respond_422 unless @build.retryable? + + build = Ci::Build.retry(@build, current_user) + redirect_to build_path(build) + end + + def play + return respond_422 unless @build.playable? + + build = @build.play(current_user) + redirect_to build_path(build) + end + + def cancel + return respond_422 unless @build.cancelable? + + @build.cancel + redirect_to build_path(@build) + end + + def status + render json: BuildSerializer + .new(project: @project, current_user: @current_user) + .represent_status(@build) + end + + def erase + if @build.erase(erased_by: current_user) + redirect_to namespace_project_job_path(project.namespace, project, @build), + notice: "Build has been successfully erased!" + else + respond_422 + end + end + + def raw + build.trace.read do |stream| + if stream.file? + send_file stream.path, type: 'text/plain; charset=utf-8', disposition: 'inline' + else + render_404 + end + end + end + + private + + def authorize_update_build! + return access_denied! unless can?(current_user, :update_build, build) + end + + def build + @build ||= project.builds.find(params[:id]) + .present(current_user: current_user) + end + + def build_path(build) + namespace_project_job_path(build.project.namespace, build.project, build) + end +end diff --git a/app/helpers/blob_helper.rb b/app/helpers/blob_helper.rb index 7eb3512378c..6a72b0059ea 100644 --- a/app/helpers/blob_helper.rb +++ b/app/helpers/blob_helper.rb @@ -120,7 +120,7 @@ module BlobHelper def blob_raw_url if @build && @entry - raw_namespace_project_build_artifacts_path(@project.namespace, @project, @build, path: @entry.path) + raw_namespace_project_job_artifacts_path(@project.namespace, @project, @build, path: @entry.path) elsif @snippet if @snippet.project_id raw_namespace_project_snippet_path(@project.namespace, @project, @snippet) diff --git a/app/helpers/builds_helper.rb b/app/helpers/builds_helper.rb index 2eb2c6c7389..f0a0d245dc0 100644 --- a/app/helpers/builds_helper.rb +++ b/app/helpers/builds_helper.rb @@ -2,7 +2,7 @@ module BuildsHelper def build_summary(build, skip: false) if build.has_trace? if skip - link_to "View job trace", pipeline_build_url(build.pipeline, build) + link_to "View job trace", pipeline_job_url(build.pipeline, build) else build.trace.html(last_lines: 10).html_safe end @@ -20,8 +20,8 @@ module BuildsHelper def javascript_build_options { - page_url: namespace_project_build_url(@project.namespace, @project, @build), - build_url: namespace_project_build_url(@project.namespace, @project, @build, :json), + page_url: namespace_project_job_url(@project.namespace, @project, @build), + build_url: namespace_project_job_url(@project.namespace, @project, @build, :json), build_status: @build.status, build_stage: @build.stage, log_state: '' @@ -31,7 +31,7 @@ module BuildsHelper def build_failed_issue_options { title: "Build Failed ##{@build.id}", - description: namespace_project_build_url(@project.namespace, @project, @build) + description: namespace_project_job_url(@project.namespace, @project, @build) } end end diff --git a/app/helpers/gitlab_routing_helper.rb b/app/helpers/gitlab_routing_helper.rb index fc308b3960e..40864bed0ff 100644 --- a/app/helpers/gitlab_routing_helper.rb +++ b/app/helpers/gitlab_routing_helper.rb @@ -50,8 +50,8 @@ module GitlabRoutingHelper namespace_project_cycle_analytics_path(project.namespace, project, *args) end - def project_builds_path(project, *args) - namespace_project_builds_path(project.namespace, project, *args) + def project_jobs_path(project, *args) + namespace_project_jobs_path(project.namespace, project, *args) end def project_ref_path(project, ref_name, *args) @@ -110,8 +110,8 @@ module GitlabRoutingHelper namespace_project_pipeline_url(pipeline.project.namespace, pipeline.project, pipeline.id, *args) end - def pipeline_build_url(pipeline, build, *args) - namespace_project_build_url(pipeline.project.namespace, pipeline.project, build.id, *args) + def pipeline_job_url(pipeline, build, *args) + namespace_project_job_url(pipeline.project.namespace, pipeline.project, build.id, *args) end def commits_url(entity, *args) @@ -215,13 +215,13 @@ module GitlabRoutingHelper case action when 'download' - download_namespace_project_build_artifacts_path(*args) + download_namespace_project_job_artifacts_path(*args) when 'browse' - browse_namespace_project_build_artifacts_path(*args) + browse_namespace_project_job_artifacts_path(*args) when 'file' - file_namespace_project_build_artifacts_path(*args) + file_namespace_project_job_artifacts_path(*args) when 'raw' - raw_namespace_project_build_artifacts_path(*args) + raw_namespace_project_job_artifacts_path(*args) end end diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 760ec8e5919..60b71ff0d93 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -51,6 +51,12 @@ module Ci after_destroy :update_project_statistics class << self + # This is needed for url_for to work, + # as the controller is JobsController + def model_name + ActiveModel::Name.new(self, nil, 'job') + end + def first_pending pending.unstarted.order('created_at ASC').first end diff --git a/app/serializers/analytics_build_entity.rb b/app/serializers/analytics_build_entity.rb index a0db5b8f0f4..ad7ad020b03 100644 --- a/app/serializers/analytics_build_entity.rb +++ b/app/serializers/analytics_build_entity.rb @@ -25,7 +25,7 @@ class AnalyticsBuildEntity < Grape::Entity end expose :url do |build| - url_to(:namespace_project_build, build) + url_to(:namespace_project_job, build) end expose :commit_url do |build| diff --git a/app/serializers/build_action_entity.rb b/app/serializers/build_action_entity.rb index 5e99204c658..301b718d060 100644 --- a/app/serializers/build_action_entity.rb +++ b/app/serializers/build_action_entity.rb @@ -6,7 +6,7 @@ class BuildActionEntity < Grape::Entity end expose :path do |build| - play_namespace_project_build_path( + play_namespace_project_job_path( build.project.namespace, build.project, build) diff --git a/app/serializers/build_artifact_entity.rb b/app/serializers/build_artifact_entity.rb index 8b643d8e783..dde17aa68b8 100644 --- a/app/serializers/build_artifact_entity.rb +++ b/app/serializers/build_artifact_entity.rb @@ -6,7 +6,7 @@ class BuildArtifactEntity < Grape::Entity end expose :path do |build| - download_namespace_project_build_artifacts_path( + download_namespace_project_job_artifacts_path( build.project.namespace, build.project, build) diff --git a/app/serializers/build_entity.rb b/app/serializers/build_entity.rb index e2276808b90..05dd8270e92 100644 --- a/app/serializers/build_entity.rb +++ b/app/serializers/build_entity.rb @@ -5,15 +5,15 @@ class BuildEntity < Grape::Entity expose :name expose :build_path do |build| - path_to(:namespace_project_build, build) + path_to(:namespace_project_job, build) end expose :retry_path do |build| - path_to(:retry_namespace_project_build, build) + path_to(:retry_namespace_project_job, build) end expose :play_path, if: -> (*) { playable? } do |build| - path_to(:play_namespace_project_build, build) + path_to(:play_namespace_project_job, build) end expose :playable?, as: :playable diff --git a/app/validators/dynamic_path_validator.rb b/app/validators/dynamic_path_validator.rb index d992b0c3725..5814eb10720 100644 --- a/app/validators/dynamic_path_validator.rb +++ b/app/validators/dynamic_path_validator.rb @@ -97,6 +97,7 @@ class DynamicPathValidator < ActiveModel::EachValidator find_file gitlab-lfs/objects info/lfs/objects + jobs new preview raw diff --git a/app/views/admin/builds/index.html.haml b/app/views/admin/builds/index.html.haml deleted file mode 100644 index 66d633119c2..00000000000 --- a/app/views/admin/builds/index.html.haml +++ /dev/null @@ -1,18 +0,0 @@ -- @no_container = true -= render "admin/dashboard/head" - -%div{ class: container_class } - - .top-area - - build_path_proc = ->(scope) { admin_builds_path(scope: scope) } - = render "shared/builds/tabs", build_path_proc: build_path_proc, all_builds: @all_builds, scope: @scope - - .nav-controls - - if @all_builds.running_or_pending.any? - = link_to 'Cancel all', cancel_all_admin_builds_path, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post - - .row-content-block.second-block - #{(@scope || 'all').capitalize} jobs - - %ul.content-list.builds-content-list.admin-builds-table - = render "projects/builds/table", builds: @builds, admin: true diff --git a/app/views/admin/dashboard/_head.html.haml b/app/views/admin/dashboard/_head.html.haml index 163bd5662b0..dff549f502c 100644 --- a/app/views/admin/dashboard/_head.html.haml +++ b/app/views/admin/dashboard/_head.html.haml @@ -20,7 +20,7 @@ %span Groups = nav_link path: 'builds#index' do - = link_to admin_builds_path, title: 'Jobs' do + = link_to admin_jobs_path, title: 'Jobs' do %span Jobs = nav_link path: ['runners#index', 'runners#show'] do diff --git a/app/views/admin/jobs/index.html.haml b/app/views/admin/jobs/index.html.haml new file mode 100644 index 00000000000..09be17f07be --- /dev/null +++ b/app/views/admin/jobs/index.html.haml @@ -0,0 +1,18 @@ +- @no_container = true += render "admin/dashboard/head" + +%div{ class: container_class } + + .top-area + - build_path_proc = ->(scope) { admin_jobs_path(scope: scope) } + = render "shared/builds/tabs", build_path_proc: build_path_proc, all_builds: @all_builds, scope: @scope + + .nav-controls + - if @all_builds.running_or_pending.any? + = link_to 'Cancel all', cancel_all_admin_jobs_path, data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post + + .row-content-block.second-block + #{(@scope || 'all').capitalize} jobs + + %ul.content-list.builds-content-list.admin-builds-table + = render "projects/jobs/table", builds: @builds, admin: true diff --git a/app/views/admin/runners/show.html.haml b/app/views/admin/runners/show.html.haml index dc4116e1ce0..801430e525e 100644 --- a/app/views/admin/runners/show.html.haml +++ b/app/views/admin/runners/show.html.haml @@ -85,7 +85,7 @@ %tr.build %td.id - if project - = link_to namespace_project_build_path(project.namespace, project, build) do + = link_to namespace_project_job_path(project.namespace, project, build) do %strong ##{build.id} - else %strong ##{build.id} diff --git a/app/views/layouts/nav/_project.html.haml b/app/views/layouts/nav/_project.html.haml index e4dfe0c8c08..29658da7792 100644 --- a/app/views/layouts/nav/_project.html.haml +++ b/app/views/layouts/nav/_project.html.haml @@ -92,7 +92,7 @@ -# Shortcut to Pipelines > Jobs - if project_nav_tab? :builds %li.hidden - = link_to project_builds_path(@project), title: 'Jobs', class: 'shortcuts-builds' do + = link_to project_jobs_path(@project), title: 'Jobs', class: 'shortcuts-builds' do Jobs -# Shortcut to commits page diff --git a/app/views/notify/links/ci/builds/_build.html.haml b/app/views/notify/links/ci/builds/_build.html.haml index d35b3839171..644cf506eff 100644 --- a/app/views/notify/links/ci/builds/_build.html.haml +++ b/app/views/notify/links/ci/builds/_build.html.haml @@ -1,2 +1,2 @@ -%a{ href: pipeline_build_url(pipeline, build), style: "color:#3777b0;text-decoration:none;" } +%a{ href: pipeline_job_url(pipeline, build), style: "color:#3777b0;text-decoration:none;" } = build.name diff --git a/app/views/notify/links/ci/builds/_build.text.erb b/app/views/notify/links/ci/builds/_build.text.erb index 741c7f344c8..773ae8174e9 100644 --- a/app/views/notify/links/ci/builds/_build.text.erb +++ b/app/views/notify/links/ci/builds/_build.text.erb @@ -1 +1 @@ -Job #<%= build.id %> ( <%= pipeline_build_url(pipeline, build) %> ) +Job #<%= build.id %> ( <%= pipeline_job_url(pipeline, build) %> ) diff --git a/app/views/projects/artifacts/_tree_directory.html.haml b/app/views/projects/artifacts/_tree_directory.html.haml index 34d5c3b7285..e2966ec33c2 100644 --- a/app/views/projects/artifacts/_tree_directory.html.haml +++ b/app/views/projects/artifacts/_tree_directory.html.haml @@ -1,4 +1,4 @@ -- path_to_directory = browse_namespace_project_build_artifacts_path(@project.namespace, @project, @build, path: directory.path) +- path_to_directory = browse_namespace_project_job_artifacts_path(@project.namespace, @project, @build, path: directory.path) %tr.tree-item{ 'data-link' => path_to_directory } %td.tree-item-file-name diff --git a/app/views/projects/artifacts/_tree_file.html.haml b/app/views/projects/artifacts/_tree_file.html.haml index ce7e25d774b..ea0b43b85cf 100644 --- a/app/views/projects/artifacts/_tree_file.html.haml +++ b/app/views/projects/artifacts/_tree_file.html.haml @@ -1,4 +1,4 @@ -- path_to_file = file_namespace_project_build_artifacts_path(@project.namespace, @project, @build, path: file.path) +- path_to_file = file_namespace_project_job_artifacts_path(@project.namespace, @project, @build, path: file.path) %tr.tree-item{ 'data-link' => path_to_file } - blob = file.blob diff --git a/app/views/projects/artifacts/browse.html.haml b/app/views/projects/artifacts/browse.html.haml index 9fbb30f7c7c..961c805dc7c 100644 --- a/app/views/projects/artifacts/browse.html.haml +++ b/app/views/projects/artifacts/browse.html.haml @@ -1,22 +1,22 @@ - page_title @path.presence, 'Artifacts', "#{@build.name} (##{@build.id})", 'Jobs' = render "projects/pipelines/head" -= render "projects/builds/header", show_controls: false += render "projects/jobs/header", show_controls: false .tree-holder .nav-block .tree-controls - = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, @build), + = link_to download_namespace_project_job_artifacts_path(@project.namespace, @project, @build), rel: 'nofollow', download: '', class: 'btn btn-default download' do = icon('download') Download artifacts archive %ul.breadcrumb.repo-breadcrumb %li - = link_to 'Artifacts', browse_namespace_project_build_artifacts_path(@project.namespace, @project, @build) + = link_to 'Artifacts', browse_namespace_project_job_artifacts_path(@project.namespace, @project, @build) - path_breadcrumbs do |title, path| %li - = link_to truncate(title, length: 40), browse_namespace_project_build_artifacts_path(@project.namespace, @project, @build, path) + = link_to truncate(title, length: 40), browse_namespace_project_job_artifacts_path(@project.namespace, @project, @build, path) .tree-content-holder %table.table.tree-table diff --git a/app/views/projects/artifacts/file.html.haml b/app/views/projects/artifacts/file.html.haml index d8da83b9a80..b25c7c95196 100644 --- a/app/views/projects/artifacts/file.html.haml +++ b/app/views/projects/artifacts/file.html.haml @@ -1,21 +1,21 @@ - page_title @path, 'Artifacts', "#{@build.name} (##{@build.id})", 'Jobs' = render "projects/pipelines/head" -= render "projects/builds/header", show_controls: false += render "projects/jobs/header", show_controls: false #tree-holder.tree-holder .nav-block %ul.breadcrumb.repo-breadcrumb %li - = link_to 'Artifacts', browse_namespace_project_build_artifacts_path(@project.namespace, @project, @build) + = link_to 'Artifacts', browse_namespace_project_job_artifacts_path(@project.namespace, @project, @build) - path_breadcrumbs do |title, path| - title = truncate(title, length: 40) %li - if path == @path - = link_to file_namespace_project_build_artifacts_path(@project.namespace, @project, @build, path) do + = link_to file_namespace_project_job_artifacts_path(@project.namespace, @project, @build, path) do %strong= title - else - = link_to title, browse_namespace_project_build_artifacts_path(@project.namespace, @project, @build, path) + = link_to title, browse_namespace_project_job_artifacts_path(@project.namespace, @project, @build, path) %article.file-holder diff --git a/app/views/projects/builds/_header.html.haml b/app/views/projects/builds/_header.html.haml deleted file mode 100644 index d4cdb709b97..00000000000 --- a/app/views/projects/builds/_header.html.haml +++ /dev/null @@ -1,31 +0,0 @@ -- show_controls = local_assigns.fetch(:show_controls, true) -- pipeline = @build.pipeline - -.content-block.build-header.top-area - .header-content - = render 'ci/status/badge', status: @build.detailed_status(current_user), link: false, title: @build.status_title - %strong - Job - = link_to "##{@build.id}", namespace_project_build_path(@project.namespace, @project, @build), class: 'js-build-id' - in pipeline - %strong - = link_to "##{pipeline.id}", pipeline_path(pipeline) - for - %strong - = link_to pipeline.short_sha, namespace_project_commit_path(@project.namespace, @project, pipeline.sha), class: 'commit-sha' - from - %strong - = link_to @build.ref, project_ref_path(@project, @build.ref), class: 'ref-name' - - = render "projects/builds/user" if @build.user - - = time_ago_with_tooltip(@build.created_at) - - - if show_controls - .nav-controls - - if can?(current_user, :create_issue, @project) && @build.failed? - = link_to "New issue", new_namespace_project_issue_path(@project.namespace, @project, issue: build_failed_issue_options), class: 'btn btn-new btn-inverted' - - if can?(current_user, :update_build, @build) && @build.retryable? - = link_to "Retry job", retry_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-inverted-secondary', method: :post - %button.btn.btn-default.pull-right.visible-xs-block.visible-sm-block.build-gutter-toggle.js-sidebar-build-toggle{ role: "button", type: "button" } - = icon('angle-double-left') diff --git a/app/views/projects/builds/_sidebar.html.haml b/app/views/projects/builds/_sidebar.html.haml deleted file mode 100644 index 8032d81cd91..00000000000 --- a/app/views/projects/builds/_sidebar.html.haml +++ /dev/null @@ -1,142 +0,0 @@ -- builds = @build.pipeline.builds.to_a - -%aside.right-sidebar.right-sidebar-expanded.build-sidebar.js-build-sidebar.js-right-sidebar{ data: { "offset-top" => "101", "spy" => "affix" } } - .block.build-sidebar-header.visible-xs-block.visible-sm-block.append-bottom-default - Job - %strong ##{@build.id} - %a.gutter-toggle.pull-right.js-sidebar-build-toggle{ href: "#" } - = icon('angle-double-right') - - if @build.coverage - .block.coverage - .title - Test coverage - %p.build-detail-row - #{@build.coverage}% - - .blocks-container - - if can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?) - .block{ class: ("block-first" if !@build.coverage) } - .title - Job artifacts - - if @build.artifacts_expired? - %p.build-detail-row - The artifacts were removed - #{time_ago_with_tooltip(@build.artifacts_expire_at)} - - elsif @build.has_expiring_artifacts? - %p.build-detail-row - The artifacts will be removed in - %span.js-artifacts-remove= @build.artifacts_expire_at - - - if @build.artifacts? - .btn-group.btn-group-justified{ role: :group } - - if @build.has_expiring_artifacts? && can?(current_user, :update_build, @build) - = link_to keep_namespace_project_build_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default', method: :post do - Keep - - = link_to download_namespace_project_build_artifacts_path(@project.namespace, @project, @build), rel: 'nofollow', download: '', class: 'btn btn-sm btn-default' do - Download - - - if @build.artifacts_metadata? - = link_to browse_namespace_project_build_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default' do - Browse - - .block{ class: ("block-first" if !@build.coverage && !(can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?))) } - .title - Job details - - if can?(current_user, :update_build, @build) && @build.retryable? - = link_to "Retry job", retry_namespace_project_build_path(@project.namespace, @project, @build), class: 'pull-right retry-link', method: :post - - if @build.merge_request - %p.build-detail-row - %span.build-light-text Merge Request: - = link_to "#{@build.merge_request.to_reference}", merge_request_path(@build.merge_request), class: 'bold' - - if @build.duration - %p.build-detail-row - %span.build-light-text Duration: - = time_interval_in_words(@build.duration) - - if @build.finished_at - %p.build-detail-row - %span.build-light-text Finished: - #{time_ago_with_tooltip(@build.finished_at)} - - if @build.erased_at - %p.build-detail-row - %span.build-light-text Erased: - #{time_ago_with_tooltip(@build.erased_at)} - %p.build-detail-row - %span.build-light-text Runner: - - if @build.runner && current_user && current_user.admin - = link_to "##{@build.runner.id}", admin_runner_path(@build.runner.id) - - elsif @build.runner - \##{@build.runner.id} - .btn-group.btn-group-justified{ role: :group } - - if @build.has_trace? - = link_to 'Raw', raw_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default' - - if @build.active? - = link_to "Cancel", cancel_namespace_project_build_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default', method: :post - - if can?(current_user, :update_build, @project) && @build.erasable? - = link_to erase_namespace_project_build_path(@project.namespace, @project, @build), - class: "btn btn-sm btn-default", method: :post, - data: { confirm: "Are you sure you want to erase this build?" } do - Erase - - - if @build.trigger_request - .build-widget - %h4.title - Trigger - - %p - %span.build-light-text Token: - #{@build.trigger_request.trigger.short_token} - - - if @build.trigger_request.variables - %p - %button.btn.group.btn-group-justified.reveal-variables Reveal Variables - - - - @build.trigger_request.variables.each do |key, value| - .hide.js-build - .js-build-variable= key - .js-build-value= value - - .block - .title - Commit title - %p.build-light-text.append-bottom-0 - #{@build.pipeline.git_commit_title} - - - if @build.tags.any? - .block - .title - Tags - - @build.tag_list.each do |tag| - %span.label.label-primary - = tag - - - if @build.pipeline.stages_count > 1 - .dropdown.build-dropdown - .title Stage - %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' } - %span.stage-selection More - = icon('chevron-down') - %ul.dropdown-menu - - @build.pipeline.stages.each do |stage| - %li - %a.stage-item= stage.name - - .builds-container - - HasStatus::ORDERED_STATUSES.each do |build_status| - - builds.select{|build| build.status == build_status}.each do |build| - .build-job{ class: sidebar_build_class(build, @build), data: { stage: build.stage } } - = link_to namespace_project_build_path(@project.namespace, @project, build) do - = icon('arrow-right') - %span{ class: "ci-status-icon-#{build.status}" } - = ci_icon_for_status(build.status) - %span - - if build.name - = build.name - - else - = build.id - - if build.retried? - %i.fa.fa-refresh.has-tooltip{ data: { container: 'body', placement: 'bottom' }, title: 'Job was retried' } - -:javascript - new Sidebar(); diff --git a/app/views/projects/builds/_table.html.haml b/app/views/projects/builds/_table.html.haml deleted file mode 100644 index 82806f022ee..00000000000 --- a/app/views/projects/builds/_table.html.haml +++ /dev/null @@ -1,25 +0,0 @@ -- admin = local_assigns.fetch(:admin, false) - -- if builds.blank? - %div - .nothing-here-block No jobs to show -- else - .table-holder - %table.table.ci-table.builds-page - %thead - %tr - %th Status - %th Job - %th Pipeline - - if admin - %th Project - %th Runner - %th Stage - %th Name - %th - %th Coverage - %th - - = render partial: "projects/ci/builds/build", collection: builds, as: :build, locals: { commit_sha: true, ref: true, pipeline_link: true, stage: true, allow_retry: true, admin: admin } - - = paginate builds, theme: 'gitlab' diff --git a/app/views/projects/builds/_user.html.haml b/app/views/projects/builds/_user.html.haml deleted file mode 100644 index 83f299da651..00000000000 --- a/app/views/projects/builds/_user.html.haml +++ /dev/null @@ -1,7 +0,0 @@ -by -%a{ href: user_path(@build.user) } - %span.hidden-xs - = image_tag avatar_icon(@build.user, 24), class: "avatar s24" - %strong{ data: { toggle: 'tooltip', placement: 'top', title: @build.user.to_reference } } - = @build.user.name - %strong.visible-xs-inline= @build.user.to_reference diff --git a/app/views/projects/builds/index.html.haml b/app/views/projects/builds/index.html.haml deleted file mode 100644 index 65162aacda1..00000000000 --- a/app/views/projects/builds/index.html.haml +++ /dev/null @@ -1,23 +0,0 @@ -- @no_container = true -- page_title "Jobs" -= render "projects/pipelines/head" - -%div{ class: container_class } - .top-area - - build_path_proc = ->(scope) { project_builds_path(@project, scope: scope) } - = render "shared/builds/tabs", build_path_proc: build_path_proc, all_builds: @all_builds, scope: @scope - - .nav-controls - - if can?(current_user, :update_build, @project) - - if @all_builds.running_or_pending.any? - = link_to 'Cancel running', cancel_all_namespace_project_builds_path(@project.namespace, @project), - data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post - - - unless @repository.gitlab_ci_yml - = link_to 'Get started with CI/CD Pipelines', help_page_path('ci/quick_start/README'), class: 'btn btn-info' - - = link_to ci_lint_path, class: 'btn btn-default' do - %span CI lint - - .content-list.builds-content-list - = render "table", builds: @builds, project: @project diff --git a/app/views/projects/builds/show.html.haml b/app/views/projects/builds/show.html.haml deleted file mode 100644 index 7cb2ec83cc7..00000000000 --- a/app/views/projects/builds/show.html.haml +++ /dev/null @@ -1,86 +0,0 @@ -- @no_container = true -- page_title "#{@build.name} (##{@build.id})", "Jobs" -= render "projects/pipelines/head" - -%div{ class: container_class } - .build-page - = render "header" - - - if @build.stuck? - - unless @build.any_runners_online? - .bs-callout.bs-callout-warning - %p - - if no_runners_for_project?(@build.project) - This job is stuck, because the project doesn't have any runners online assigned to it. - - elsif @build.tags.any? - This job is stuck, because you don't have any active runners online with any of these tags assigned to them: - - @build.tags.each do |tag| - %span.label.label-primary - = tag - - else - This job is stuck, because you don't have any active runners that can run this job. - - %br - Go to - = link_to namespace_project_runners_path(@build.project.namespace, @build.project) do - Runners page - - - if @build.starts_environment? - .prepend-top-default - .environment-information - - if @build.outdated_deployment? - = ci_icon_for_status('success_with_warnings') - - else - = ci_icon_for_status(@build.status) - - - environment = environment_for_build(@build.project, @build) - - if @build.success? && @build.last_deployment.present? - - if @build.last_deployment.last? - This job is the most recent deployment to #{environment_link_for_build(@build.project, @build)}. - - else - This job is an out-of-date deployment to #{environment_link_for_build(@build.project, @build)}. - View the most recent deployment #{deployment_link(environment.last_deployment)}. - - elsif @build.complete? && !@build.success? - The deployment of this job to #{environment_link_for_build(@build.project, @build)} did not succeed. - - else - This job is creating a deployment to #{environment_link_for_build(@build.project, @build)} - - if environment.try(:last_deployment) - and will overwrite the #{deployment_link(environment.last_deployment, text: 'latest deployment')} - - .prepend-top-default - - if @build.erased? - .erased.alert.alert-warning - - if @build.erased_by_user? - Job has been erased by #{link_to(@build.erased_by_name, user_path(@build.erased_by))} #{time_ago_with_tooltip(@build.erased_at)} - - else - Job has been erased #{time_ago_with_tooltip(@build.erased_at)} - - else - #js-build-scroll.scroll-controls - .scroll-step - %a.scroll-link.scroll-top{ href: '#up-build-trace', id: 'scroll-top', title: 'Scroll to top' } - = custom_icon('scroll_up') - = custom_icon('scroll_up_hover_active') - %a.scroll-link.scroll-bottom{ href: '#down-build-trace', id: 'scroll-bottom', title: 'Scroll to bottom' } - = custom_icon('scroll_down') - = custom_icon('scroll_down_hover_active') - - if @build.active? - .autoscroll-container - %span.status-message#autoscroll-status{ data: { state: 'disabled' } } - %span.status-text Autoscroll active - %i.status-icon - = custom_icon('scroll_down_hover_active') - #up-build-trace - %pre.build-trace#build-trace - .js-truncated-info.truncated-info.hidden< - Showing last - %span.js-truncated-info-size.truncated-info-size>< - KiB of log - - %a.js-raw-link.raw-link{ :href => raw_namespace_project_build_path(@project.namespace, @project, @build) }>< Complete Raw - %code.bash.js-build-output - .build-loader-animation.js-build-refresh - - #down-build-trace - - = render "sidebar" - -.js-build-options{ data: javascript_build_options } diff --git a/app/views/projects/ci/builds/_build.html.haml b/app/views/projects/ci/builds/_build.html.haml index e796920ac82..bec72bb1f7a 100644 --- a/app/views/projects/ci/builds/_build.html.haml +++ b/app/views/projects/ci/builds/_build.html.haml @@ -14,7 +14,7 @@ %td.branch-commit - if can?(current_user, :read_build, job) - = link_to namespace_project_build_url(job.project.namespace, job.project, job) do + = link_to namespace_project_job_url(job.project.namespace, job.project, job) do %span.build-link ##{job.id} - else %span.build-link ##{job.id} @@ -95,16 +95,16 @@ %td .pull-right - if can?(current_user, :read_build, job) && job.artifacts? - = link_to download_namespace_project_build_artifacts_path(job.project.namespace, job.project, job), rel: 'nofollow', download: '', title: 'Download artifacts', class: 'btn btn-build' do + = link_to download_namespace_project_job_artifacts_path(job.project.namespace, job.project, job), rel: 'nofollow', download: '', title: 'Download artifacts', class: 'btn btn-build' do = icon('download') - if can?(current_user, :update_build, job) - if job.active? - = link_to cancel_namespace_project_build_path(job.project.namespace, job.project, job, return_to: request.original_url), method: :post, title: 'Cancel', class: 'btn btn-build' do + = link_to cancel_namespace_project_job_path(job.project.namespace, job.project, job, return_to: request.original_url), method: :post, title: 'Cancel', class: 'btn btn-build' do = icon('remove', class: 'cred') - elsif allow_retry - if job.playable? && !admin && can?(current_user, :update_build, job) - = link_to play_namespace_project_build_path(job.project.namespace, job.project, job, return_to: request.original_url), method: :post, title: 'Play', class: 'btn btn-build' do + = link_to play_namespace_project_job_path(job.project.namespace, job.project, job, return_to: request.original_url), method: :post, title: 'Play', class: 'btn btn-build' do = custom_icon('icon_play') - elsif job.retryable? - = link_to retry_namespace_project_build_path(job.project.namespace, job.project, job, return_to: request.original_url), method: :post, title: 'Retry', class: 'btn btn-build' do + = link_to retry_namespace_project_job_path(job.project.namespace, job.project, job, return_to: request.original_url), method: :post, title: 'Retry', class: 'btn btn-build' do = icon('repeat') diff --git a/app/views/projects/jobs/_header.html.haml b/app/views/projects/jobs/_header.html.haml new file mode 100644 index 00000000000..ad72ab5b199 --- /dev/null +++ b/app/views/projects/jobs/_header.html.haml @@ -0,0 +1,31 @@ +- show_controls = local_assigns.fetch(:show_controls, true) +- pipeline = @build.pipeline + +.content-block.build-header.top-area + .header-content + = render 'ci/status/badge', status: @build.detailed_status(current_user), link: false, title: @build.status_title + %strong + Job + = link_to "##{@build.id}", namespace_project_job_path(@project.namespace, @project, @build), class: 'js-build-id' + in pipeline + %strong + = link_to "##{pipeline.id}", pipeline_path(pipeline) + for + %strong + = link_to pipeline.short_sha, namespace_project_commit_path(@project.namespace, @project, pipeline.sha), class: 'commit-sha' + from + %strong + = link_to @build.ref, project_ref_path(@project, @build.ref), class: 'ref-name' + + = render "projects/jobs/user" if @build.user + + = time_ago_with_tooltip(@build.created_at) + + - if show_controls + .nav-controls + - if can?(current_user, :create_issue, @project) && @build.failed? + = link_to "New issue", new_namespace_project_issue_path(@project.namespace, @project, issue: build_failed_issue_options), class: 'btn btn-new btn-inverted' + - if can?(current_user, :update_build, @build) && @build.retryable? + = link_to "Retry job", retry_namespace_project_job_path(@project.namespace, @project, @build), class: 'btn btn-inverted-secondary', method: :post + %button.btn.btn-default.pull-right.visible-xs-block.visible-sm-block.build-gutter-toggle.js-sidebar-build-toggle{ role: "button", type: "button" } + = icon('angle-double-left') diff --git a/app/views/projects/jobs/_sidebar.html.haml b/app/views/projects/jobs/_sidebar.html.haml new file mode 100644 index 00000000000..8cd4144952b --- /dev/null +++ b/app/views/projects/jobs/_sidebar.html.haml @@ -0,0 +1,142 @@ +- builds = @build.pipeline.builds.to_a + +%aside.right-sidebar.right-sidebar-expanded.build-sidebar.js-build-sidebar.js-right-sidebar{ data: { "offset-top" => "101", "spy" => "affix" } } + .block.build-sidebar-header.visible-xs-block.visible-sm-block.append-bottom-default + Job + %strong ##{@build.id} + %a.gutter-toggle.pull-right.js-sidebar-build-toggle{ href: "#" } + = icon('angle-double-right') + - if @build.coverage + .block.coverage + .title + Test coverage + %p.build-detail-row + #{@build.coverage}% + + .blocks-container + - if can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?) + .block{ class: ("block-first" if !@build.coverage) } + .title + Job artifacts + - if @build.artifacts_expired? + %p.build-detail-row + The artifacts were removed + #{time_ago_with_tooltip(@build.artifacts_expire_at)} + - elsif @build.has_expiring_artifacts? + %p.build-detail-row + The artifacts will be removed in + %span.js-artifacts-remove= @build.artifacts_expire_at + + - if @build.artifacts? + .btn-group.btn-group-justified{ role: :group } + - if @build.has_expiring_artifacts? && can?(current_user, :update_build, @build) + = link_to keep_namespace_project_job_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default', method: :post do + Keep + + = link_to download_namespace_project_job_artifacts_path(@project.namespace, @project, @build), rel: 'nofollow', download: '', class: 'btn btn-sm btn-default' do + Download + + - if @build.artifacts_metadata? + = link_to browse_namespace_project_job_artifacts_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default' do + Browse + + .block{ class: ("block-first" if !@build.coverage && !(can?(current_user, :read_build, @project) && (@build.artifacts? || @build.artifacts_expired?))) } + .title + Job details + - if can?(current_user, :update_build, @build) && @build.retryable? + = link_to "Retry job", retry_namespace_project_job_path(@project.namespace, @project, @build), class: 'pull-right retry-link', method: :post + - if @build.merge_request + %p.build-detail-row + %span.build-light-text Merge Request: + = link_to "#{@build.merge_request.to_reference}", merge_request_path(@build.merge_request), class: 'bold' + - if @build.duration + %p.build-detail-row + %span.build-light-text Duration: + = time_interval_in_words(@build.duration) + - if @build.finished_at + %p.build-detail-row + %span.build-light-text Finished: + #{time_ago_with_tooltip(@build.finished_at)} + - if @build.erased_at + %p.build-detail-row + %span.build-light-text Erased: + #{time_ago_with_tooltip(@build.erased_at)} + %p.build-detail-row + %span.build-light-text Runner: + - if @build.runner && current_user && current_user.admin + = link_to "##{@build.runner.id}", admin_runner_path(@build.runner.id) + - elsif @build.runner + \##{@build.runner.id} + .btn-group.btn-group-justified{ role: :group } + - if @build.has_trace? + = link_to 'Raw', raw_namespace_project_job_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default' + - if @build.active? + = link_to "Cancel", cancel_namespace_project_job_path(@project.namespace, @project, @build), class: 'btn btn-sm btn-default', method: :post + - if can?(current_user, :update_build, @project) && @build.erasable? + = link_to erase_namespace_project_job_path(@project.namespace, @project, @build), + class: "btn btn-sm btn-default", method: :post, + data: { confirm: "Are you sure you want to erase this build?" } do + Erase + + - if @build.trigger_request + .build-widget + %h4.title + Trigger + + %p + %span.build-light-text Token: + #{@build.trigger_request.trigger.short_token} + + - if @build.trigger_request.variables + %p + %button.btn.group.btn-group-justified.reveal-variables Reveal Variables + + + - @build.trigger_request.variables.each do |key, value| + .hide.js-build + .js-build-variable= key + .js-build-value= value + + .block + .title + Commit title + %p.build-light-text.append-bottom-0 + #{@build.pipeline.git_commit_title} + + - if @build.tags.any? + .block + .title + Tags + - @build.tag_list.each do |tag| + %span.label.label-primary + = tag + + - if @build.pipeline.stages_count > 1 + .dropdown.build-dropdown + .title Stage + %button.dropdown-menu-toggle{ type: 'button', 'data-toggle' => 'dropdown' } + %span.stage-selection More + = icon('chevron-down') + %ul.dropdown-menu + - @build.pipeline.stages.each do |stage| + %li + %a.stage-item= stage.name + + .builds-container + - HasStatus::ORDERED_STATUSES.each do |build_status| + - builds.select{|build| build.status == build_status}.each do |build| + .build-job{ class: sidebar_build_class(build, @build), data: { stage: build.stage } } + = link_to namespace_project_job_path(@project.namespace, @project, build) do + = icon('arrow-right') + %span{ class: "ci-status-icon-#{build.status}" } + = ci_icon_for_status(build.status) + %span + - if build.name + = build.name + - else + = build.id + - if build.retried? + %i.fa.fa-refresh.has-tooltip{ data: { container: 'body', placement: 'bottom' }, title: 'Job was retried' } + +:javascript + new Sidebar(); diff --git a/app/views/projects/jobs/_table.html.haml b/app/views/projects/jobs/_table.html.haml new file mode 100644 index 00000000000..82806f022ee --- /dev/null +++ b/app/views/projects/jobs/_table.html.haml @@ -0,0 +1,25 @@ +- admin = local_assigns.fetch(:admin, false) + +- if builds.blank? + %div + .nothing-here-block No jobs to show +- else + .table-holder + %table.table.ci-table.builds-page + %thead + %tr + %th Status + %th Job + %th Pipeline + - if admin + %th Project + %th Runner + %th Stage + %th Name + %th + %th Coverage + %th + + = render partial: "projects/ci/builds/build", collection: builds, as: :build, locals: { commit_sha: true, ref: true, pipeline_link: true, stage: true, allow_retry: true, admin: admin } + + = paginate builds, theme: 'gitlab' diff --git a/app/views/projects/jobs/_user.html.haml b/app/views/projects/jobs/_user.html.haml new file mode 100644 index 00000000000..83f299da651 --- /dev/null +++ b/app/views/projects/jobs/_user.html.haml @@ -0,0 +1,7 @@ +by +%a{ href: user_path(@build.user) } + %span.hidden-xs + = image_tag avatar_icon(@build.user, 24), class: "avatar s24" + %strong{ data: { toggle: 'tooltip', placement: 'top', title: @build.user.to_reference } } + = @build.user.name + %strong.visible-xs-inline= @build.user.to_reference diff --git a/app/views/projects/jobs/index.html.haml b/app/views/projects/jobs/index.html.haml new file mode 100644 index 00000000000..70b53e4ca77 --- /dev/null +++ b/app/views/projects/jobs/index.html.haml @@ -0,0 +1,23 @@ +- @no_container = true +- page_title "Jobs" += render "projects/pipelines/head" + +%div{ class: container_class } + .top-area + - build_path_proc = ->(scope) { project_jobs_path(@project, scope: scope) } + = render "shared/builds/tabs", build_path_proc: build_path_proc, all_builds: @all_builds, scope: @scope + + .nav-controls + - if can?(current_user, :update_build, @project) + - if @all_builds.running_or_pending.any? + = link_to 'Cancel running', cancel_all_namespace_project_jobs_path(@project.namespace, @project), + data: { confirm: 'Are you sure?' }, class: 'btn btn-danger', method: :post + + - unless @repository.gitlab_ci_yml + = link_to 'Get started with CI/CD Pipelines', help_page_path('ci/quick_start/README'), class: 'btn btn-info' + + = link_to ci_lint_path, class: 'btn btn-default' do + %span CI lint + + .content-list.builds-content-list + = render "table", builds: @builds, project: @project diff --git a/app/views/projects/jobs/show.html.haml b/app/views/projects/jobs/show.html.haml new file mode 100644 index 00000000000..113da4d7a0c --- /dev/null +++ b/app/views/projects/jobs/show.html.haml @@ -0,0 +1,86 @@ +- @no_container = true +- page_title "#{@build.name} (##{@build.id})", "Jobs" += render "projects/pipelines/head" + +%div{ class: container_class } + .build-page + = render "header" + + - if @build.stuck? + - unless @build.any_runners_online? + .bs-callout.bs-callout-warning + %p + - if no_runners_for_project?(@build.project) + This job is stuck, because the project doesn't have any runners online assigned to it. + - elsif @build.tags.any? + This job is stuck, because you don't have any active runners online with any of these tags assigned to them: + - @build.tags.each do |tag| + %span.label.label-primary + = tag + - else + This job is stuck, because you don't have any active runners that can run this job. + + %br + Go to + = link_to namespace_project_runners_path(@build.project.namespace, @build.project) do + Runners page + + - if @build.starts_environment? + .prepend-top-default + .environment-information + - if @build.outdated_deployment? + = ci_icon_for_status('success_with_warnings') + - else + = ci_icon_for_status(@build.status) + + - environment = environment_for_build(@build.project, @build) + - if @build.success? && @build.last_deployment.present? + - if @build.last_deployment.last? + This job is the most recent deployment to #{environment_link_for_build(@build.project, @build)}. + - else + This job is an out-of-date deployment to #{environment_link_for_build(@build.project, @build)}. + View the most recent deployment #{deployment_link(environment.last_deployment)}. + - elsif @build.complete? && !@build.success? + The deployment of this job to #{environment_link_for_build(@build.project, @build)} did not succeed. + - else + This job is creating a deployment to #{environment_link_for_build(@build.project, @build)} + - if environment.try(:last_deployment) + and will overwrite the #{deployment_link(environment.last_deployment, text: 'latest deployment')} + + .prepend-top-default + - if @build.erased? + .erased.alert.alert-warning + - if @build.erased_by_user? + Job has been erased by #{link_to(@build.erased_by_name, user_path(@build.erased_by))} #{time_ago_with_tooltip(@build.erased_at)} + - else + Job has been erased #{time_ago_with_tooltip(@build.erased_at)} + - else + #js-build-scroll.scroll-controls + .scroll-step + %a.scroll-link.scroll-top{ href: '#up-build-trace', id: 'scroll-top', title: 'Scroll to top' } + = custom_icon('scroll_up') + = custom_icon('scroll_up_hover_active') + %a.scroll-link.scroll-bottom{ href: '#down-build-trace', id: 'scroll-bottom', title: 'Scroll to bottom' } + = custom_icon('scroll_down') + = custom_icon('scroll_down_hover_active') + - if @build.active? + .autoscroll-container + %span.status-message#autoscroll-status{ data: { state: 'disabled' } } + %span.status-text Autoscroll active + %i.status-icon + = custom_icon('scroll_down_hover_active') + #up-build-trace + %pre.build-trace#build-trace + .js-truncated-info.truncated-info.hidden< + Showing last + %span.js-truncated-info-size.truncated-info-size>< + KiB of log - + %a.js-raw-link.raw-link{ :href => raw_namespace_project_job_path(@project.namespace, @project, @build) }>< Complete Raw + %code.bash.js-build-output + .build-loader-animation.js-build-refresh + + #down-build-trace + + = render "sidebar" + +.js-build-options{ data: javascript_build_options } diff --git a/app/views/projects/pipelines/_head.html.haml b/app/views/projects/pipelines/_head.html.haml index db9d77dba16..a33da149c62 100644 --- a/app/views/projects/pipelines/_head.html.haml +++ b/app/views/projects/pipelines/_head.html.haml @@ -11,7 +11,7 @@ - if project_nav_tab? :builds = nav_link(controller: [:builds, :artifacts]) do - = link_to project_builds_path(@project), title: 'Jobs', class: 'shortcuts-builds' do + = link_to project_jobs_path(@project), title: 'Jobs', class: 'shortcuts-builds' do %span Jobs diff --git a/app/views/projects/pipelines/_with_tabs.html.haml b/app/views/projects/pipelines/_with_tabs.html.haml index 075ddc0025c..fd2f2c4c72c 100644 --- a/app/views/projects/pipelines/_with_tabs.html.haml +++ b/app/views/projects/pipelines/_with_tabs.html.haml @@ -55,5 +55,5 @@ %span.stage = build.stage.titleize %span.build-name - = link_to build.name, pipeline_build_url(pipeline, build) + = link_to build.name, pipeline_job_url(pipeline, build) %pre.build-log= build_summary(build, skip: index >= 10) diff --git a/config/initializers/relative_naming_ci_namespace.rb b/config/initializers/relative_naming_ci_namespace.rb index 59abe1b9b91..03ac55be0b6 100644 --- a/config/initializers/relative_naming_ci_namespace.rb +++ b/config/initializers/relative_naming_ci_namespace.rb @@ -4,7 +4,7 @@ # - [project.namespace, project, build] # # instead of: -# - namespace_project_build_path(project.namespace, project, build) +# - namespace_project_job_path(project.namespace, project, build) # # Without that, Ci:: namespace is used for resolving routes: # - namespace_project_ci_build_path(project.namespace, project, build) diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 48993420ed9..11e6f844de8 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -110,7 +110,7 @@ namespace :admin do resources :cohorts, only: :index - resources :builds, only: :index do + resources :jobs, only: :index do collection do post :cancel_all end diff --git a/config/routes/project.rb b/config/routes/project.rb index c786cbdee1e..0c8052558c1 100644 --- a/config/routes/project.rb +++ b/config/routes/project.rb @@ -166,7 +166,7 @@ constraints(ProjectUrlConstrainer.new) do end end - resources :builds, only: [:index, :show], constraints: { id: /\d+/ } do + resources :jobs, only: [:index, :show], constraints: { id: /\d+/ } do collection do post :cancel_all diff --git a/features/steps/shared/builds.rb b/features/steps/shared/builds.rb index 5549fc25525..624f1a7858b 100644 --- a/features/steps/shared/builds.rb +++ b/features/steps/shared/builds.rb @@ -27,11 +27,11 @@ module SharedBuilds end step 'I visit recent build details page' do - visit namespace_project_build_path(@project.namespace, @project, @build) + visit namespace_project_job_path(@project.namespace, @project, @build) end step 'I visit project builds page' do - visit namespace_project_builds_path(@project.namespace, @project) + visit namespace_project_jobs_path(@project.namespace, @project) end step 'recent build has artifacts available' do @@ -56,7 +56,7 @@ module SharedBuilds end step 'I access artifacts download page' do - visit download_namespace_project_build_artifacts_path(@project.namespace, @project, @build) + visit download_namespace_project_job_artifacts_path(@project.namespace, @project, @build) end step 'I see details of a build' do diff --git a/lib/gitlab/ci/status/build/cancelable.rb b/lib/gitlab/ci/status/build/cancelable.rb index 57b533bad99..439ef0ce015 100644 --- a/lib/gitlab/ci/status/build/cancelable.rb +++ b/lib/gitlab/ci/status/build/cancelable.rb @@ -12,7 +12,7 @@ module Gitlab end def action_path - cancel_namespace_project_build_path(subject.project.namespace, + cancel_namespace_project_job_path(subject.project.namespace, subject.project, subject) end diff --git a/lib/gitlab/ci/status/build/common.rb b/lib/gitlab/ci/status/build/common.rb index 3fec2c5d4db..b173c23fba4 100644 --- a/lib/gitlab/ci/status/build/common.rb +++ b/lib/gitlab/ci/status/build/common.rb @@ -8,7 +8,7 @@ module Gitlab end def details_path - namespace_project_build_path(subject.project.namespace, + namespace_project_job_path(subject.project.namespace, subject.project, subject) end diff --git a/lib/gitlab/ci/status/build/play.rb b/lib/gitlab/ci/status/build/play.rb index c6139f1b716..e80f3263794 100644 --- a/lib/gitlab/ci/status/build/play.rb +++ b/lib/gitlab/ci/status/build/play.rb @@ -20,7 +20,7 @@ module Gitlab end def action_path - play_namespace_project_build_path(subject.project.namespace, + play_namespace_project_job_path(subject.project.namespace, subject.project, subject) end diff --git a/lib/gitlab/ci/status/build/retryable.rb b/lib/gitlab/ci/status/build/retryable.rb index 505f80848b2..56303e4cb17 100644 --- a/lib/gitlab/ci/status/build/retryable.rb +++ b/lib/gitlab/ci/status/build/retryable.rb @@ -16,7 +16,7 @@ module Gitlab end def action_path - retry_namespace_project_build_path(subject.project.namespace, + retry_namespace_project_job_path(subject.project.namespace, subject.project, subject) end diff --git a/lib/gitlab/ci/status/build/stop.rb b/lib/gitlab/ci/status/build/stop.rb index 0b5199e5483..2778d6f3b52 100644 --- a/lib/gitlab/ci/status/build/stop.rb +++ b/lib/gitlab/ci/status/build/stop.rb @@ -20,7 +20,7 @@ module Gitlab end def action_path - play_namespace_project_build_path(subject.project.namespace, + play_namespace_project_job_path(subject.project.namespace, subject.project, subject) end diff --git a/spec/controllers/projects/artifacts_controller_spec.rb b/spec/controllers/projects/artifacts_controller_spec.rb index eff9fab8da2..428bc45b842 100644 --- a/spec/controllers/projects/artifacts_controller_spec.rb +++ b/spec/controllers/projects/artifacts_controller_spec.rb @@ -12,7 +12,7 @@ describe Projects::ArtifactsController do status: 'success') end - let(:build) { create(:ci_build, :success, :artifacts, pipeline: pipeline) } + let(:job) { create(:ci_build, :success, :artifacts, pipeline: pipeline) } before do project.team << [user, :developer] @@ -22,16 +22,16 @@ describe Projects::ArtifactsController do describe 'GET download' do it 'sends the artifacts file' do - expect(controller).to receive(:send_file).with(build.artifacts_file.path, disposition: 'attachment').and_call_original + expect(controller).to receive(:send_file).with(job.artifacts_file.path, disposition: 'attachment').and_call_original - get :download, namespace_id: project.namespace, project_id: project, build_id: build + get :download, namespace_id: project.namespace, project_id: project, job_id: job end end describe 'GET browse' do context 'when the directory exists' do it 'renders the browse view' do - get :browse, namespace_id: project.namespace, project_id: project, build_id: build, path: 'other_artifacts_0.1.2' + get :browse, namespace_id: project.namespace, project_id: project, job_id: job, path: 'other_artifacts_0.1.2' expect(response).to render_template('projects/artifacts/browse') end @@ -39,7 +39,7 @@ describe Projects::ArtifactsController do context 'when the directory does not exist' do it 'responds Not Found' do - get :browse, namespace_id: project.namespace, project_id: project, build_id: build, path: 'unknown' + get :browse, namespace_id: project.namespace, project_id: project, job_id: job, path: 'unknown' expect(response).to be_not_found end @@ -49,7 +49,7 @@ describe Projects::ArtifactsController do describe 'GET file' do context 'when the file exists' do it 'renders the file view' do - get :file, namespace_id: project.namespace, project_id: project, build_id: build, path: 'ci_artifacts.txt' + get :file, namespace_id: project.namespace, project_id: project, job_id: job, path: 'ci_artifacts.txt' expect(response).to render_template('projects/artifacts/file') end @@ -57,7 +57,7 @@ describe Projects::ArtifactsController do context 'when the file does not exist' do it 'responds Not Found' do - get :file, namespace_id: project.namespace, project_id: project, build_id: build, path: 'unknown' + get :file, namespace_id: project.namespace, project_id: project, job_id: job, path: 'unknown' expect(response).to be_not_found end @@ -67,7 +67,7 @@ describe Projects::ArtifactsController do describe 'GET raw' do context 'when the file exists' do it 'serves the file using workhorse' do - get :raw, namespace_id: project.namespace, project_id: project, build_id: build, path: 'ci_artifacts.txt' + get :raw, namespace_id: project.namespace, project_id: project, job_id: job, path: 'ci_artifacts.txt' send_data = response.headers[Gitlab::Workhorse::SEND_DATA_HEADER] @@ -84,7 +84,7 @@ describe Projects::ArtifactsController do context 'when the file does not exist' do it 'responds Not Found' do - get :raw, namespace_id: project.namespace, project_id: project, build_id: build, path: 'unknown' + get :raw, namespace_id: project.namespace, project_id: project, job_id: job, path: 'unknown' expect(response).to be_not_found end @@ -92,29 +92,29 @@ describe Projects::ArtifactsController do end describe 'GET latest_succeeded' do - def params_from_ref(ref = pipeline.ref, job = build.name, path = 'browse') + def params_from_ref(ref = pipeline.ref, job_name = job.name, path = 'browse') { namespace_id: project.namespace, project_id: project, ref_name_and_path: File.join(ref, path), - job: job + job: job_name } end - context 'cannot find the build' do + context 'cannot find the job' do shared_examples 'not found' do it { expect(response).to have_http_status(:not_found) } end context 'has no such ref' do before do - get :latest_succeeded, params_from_ref('TAIL', build.name) + get :latest_succeeded, params_from_ref('TAIL', job.name) end it_behaves_like 'not found' end - context 'has no such build' do + context 'has no such job' do before do get :latest_succeeded, params_from_ref(pipeline.ref, 'NOBUILD') end @@ -124,20 +124,20 @@ describe Projects::ArtifactsController do context 'has no path' do before do - get :latest_succeeded, params_from_ref(pipeline.sha, build.name, '') + get :latest_succeeded, params_from_ref(pipeline.sha, job.name, '') end it_behaves_like 'not found' end end - context 'found the build and redirect' do - shared_examples 'redirect to the build' do + context 'found the job and redirect' do + shared_examples 'redirect to the job' do it 'redirects' do - path = browse_namespace_project_build_artifacts_path( + path = browse_namespace_project_job_artifacts_path( project.namespace, project, - build) + job) expect(response).to redirect_to(path) end @@ -151,7 +151,7 @@ describe Projects::ArtifactsController do get :latest_succeeded, params_from_ref('master') end - it_behaves_like 'redirect to the build' + it_behaves_like 'redirect to the job' end context 'with branch name containing slash' do @@ -162,7 +162,7 @@ describe Projects::ArtifactsController do get :latest_succeeded, params_from_ref('improve/awesome') end - it_behaves_like 'redirect to the build' + it_behaves_like 'redirect to the job' end context 'with branch name and path containing slashes' do @@ -170,14 +170,14 @@ describe Projects::ArtifactsController do pipeline.update(ref: 'improve/awesome', sha: project.commit('improve/awesome').sha) - get :latest_succeeded, params_from_ref('improve/awesome', build.name, 'file/README.md') + get :latest_succeeded, params_from_ref('improve/awesome', job.name, 'file/README.md') end it 'redirects' do - path = file_namespace_project_build_artifacts_path( + path = file_namespace_project_job_artifacts_path( project.namespace, project, - build, + job, 'README.md') expect(response).to redirect_to(path) diff --git a/spec/controllers/projects/builds_controller_spec.rb b/spec/controllers/projects/builds_controller_spec.rb deleted file mode 100644 index 3ce23c17cdc..00000000000 --- a/spec/controllers/projects/builds_controller_spec.rb +++ /dev/null @@ -1,446 +0,0 @@ -require 'spec_helper' - -describe Projects::BuildsController do - include ApiHelpers - - let(:project) { create(:empty_project, :public) } - let(:pipeline) { create(:ci_pipeline, project: project) } - let(:user) { create(:user) } - - describe 'GET index' do - context 'when scope is pending' do - before do - create(:ci_build, :pending, pipeline: pipeline) - - get_index(scope: 'pending') - end - - it 'has only pending builds' do - expect(response).to have_http_status(:ok) - expect(assigns(:builds).first.status).to eq('pending') - end - end - - context 'when scope is running' do - before do - create(:ci_build, :running, pipeline: pipeline) - - get_index(scope: 'running') - end - - it 'has only running builds' do - expect(response).to have_http_status(:ok) - expect(assigns(:builds).first.status).to eq('running') - end - end - - context 'when scope is finished' do - before do - create(:ci_build, :success, pipeline: pipeline) - - get_index(scope: 'finished') - end - - it 'has only finished builds' do - expect(response).to have_http_status(:ok) - expect(assigns(:builds).first.status).to eq('success') - end - end - - context 'when page is specified' do - let(:last_page) { project.builds.page.total_pages } - - context 'when page number is eligible' do - before do - create_list(:ci_build, 2, pipeline: pipeline) - - get_index(page: last_page.to_param) - end - - it 'redirects to the page' do - expect(response).to have_http_status(:ok) - expect(assigns(:builds).current_page).to eq(last_page) - end - end - end - - context 'number of queries' do - before do - Ci::Build::AVAILABLE_STATUSES.each do |status| - create_build(status, status) - end - - RequestStore.begin! - end - - after do - RequestStore.end! - RequestStore.clear! - end - - it "verifies number of queries" do - recorded = ActiveRecord::QueryRecorder.new { get_index } - expect(recorded.count).to be_within(5).of(8) - end - - def create_build(name, status) - pipeline = create(:ci_pipeline, project: project) - create(:ci_build, :tags, :triggered, :artifacts, - pipeline: pipeline, name: name, status: status) - end - end - - def get_index(**extra_params) - params = { - namespace_id: project.namespace.to_param, - project_id: project - } - - get :index, params.merge(extra_params) - end - end - - describe 'GET show' do - context 'when build exists' do - let!(:build) { create(:ci_build, pipeline: pipeline) } - - before do - get_show(id: build.id) - end - - it 'has a build' do - expect(response).to have_http_status(:ok) - expect(assigns(:build).id).to eq(build.id) - end - end - - context 'when build does not exist' do - before do - get_show(id: 1234) - end - - it 'renders not_found' do - expect(response).to have_http_status(:not_found) - end - end - - def get_show(**extra_params) - params = { - namespace_id: project.namespace.to_param, - project_id: project - } - - get :show, params.merge(extra_params) - end - end - - describe 'GET trace.json' do - before do - get_trace - end - - context 'when build has a trace' do - let(:build) { create(:ci_build, :trace, pipeline: pipeline) } - - it 'returns a trace' do - expect(response).to have_http_status(:ok) - expect(json_response['html']).to eq('BUILD TRACE') - end - end - - context 'when build has no traces' do - let(:build) { create(:ci_build, pipeline: pipeline) } - - it 'returns no traces' do - expect(response).to have_http_status(:ok) - expect(json_response['html']).to be_nil - end - end - - def get_trace - get :trace, namespace_id: project.namespace, - project_id: project, - id: build.id, - format: :json - end - end - - describe 'GET status.json' do - let(:build) { create(:ci_build, pipeline: pipeline) } - let(:status) { build.detailed_status(double('user')) } - - before do - get :status, namespace_id: project.namespace, - project_id: project, - id: build.id, - format: :json - end - - it 'return a detailed build status in json' do - expect(response).to have_http_status(:ok) - expect(json_response['text']).to eq status.text - expect(json_response['label']).to eq status.label - expect(json_response['icon']).to eq status.icon - expect(json_response['favicon']).to eq "/assets/ci_favicons/#{status.favicon}.ico" - end - end - - describe 'GET trace.json' do - let(:pipeline) { create(:ci_pipeline, project: project) } - let(:build) { create(:ci_build, pipeline: pipeline) } - let(:user) { create(:user) } - - context 'when user is logged in as developer' do - before do - project.add_developer(user) - sign_in(user) - - get_trace - end - - it 'traces build log' do - expect(response).to have_http_status(:ok) - expect(json_response['id']).to eq build.id - expect(json_response['status']).to eq build.status - end - end - - context 'when user is logged in as non member' do - before do - sign_in(user) - - get_trace - end - - it 'traces build log' do - expect(response).to have_http_status(:ok) - expect(json_response['id']).to eq build.id - expect(json_response['status']).to eq build.status - end - end - - def get_trace - get :trace, namespace_id: project.namespace, - project_id: project, - id: build.id, - format: :json - end - end - - describe 'POST retry' do - before do - project.add_developer(user) - sign_in(user) - - post_retry - end - - context 'when build is retryable' do - let(:build) { create(:ci_build, :retryable, pipeline: pipeline) } - - it 'redirects to the retried build page' do - expect(response).to have_http_status(:found) - expect(response).to redirect_to(namespace_project_build_path(id: Ci::Build.last.id)) - end - end - - context 'when build is not retryable' do - let(:build) { create(:ci_build, pipeline: pipeline) } - - it 'renders unprocessable_entity' do - expect(response).to have_http_status(:unprocessable_entity) - end - end - - def post_retry - post :retry, namespace_id: project.namespace, - project_id: project, - id: build.id - end - end - - describe 'POST play' do - before do - project.add_master(user) - sign_in(user) - - post_play - end - - context 'when build is playable' do - let(:build) { create(:ci_build, :playable, pipeline: pipeline) } - - it 'redirects to the played build page' do - expect(response).to have_http_status(:found) - expect(response).to redirect_to(namespace_project_build_path(id: build.id)) - end - - it 'transits to pending' do - expect(build.reload).to be_pending - end - end - - context 'when build is not playable' do - let(:build) { create(:ci_build, pipeline: pipeline) } - - it 'renders unprocessable_entity' do - expect(response).to have_http_status(:unprocessable_entity) - end - end - - def post_play - post :play, namespace_id: project.namespace, - project_id: project, - id: build.id - end - end - - describe 'POST cancel' do - before do - project.add_developer(user) - sign_in(user) - - post_cancel - end - - context 'when build is cancelable' do - let(:build) { create(:ci_build, :cancelable, pipeline: pipeline) } - - it 'redirects to the canceled build page' do - expect(response).to have_http_status(:found) - expect(response).to redirect_to(namespace_project_build_path(id: build.id)) - end - - it 'transits to canceled' do - expect(build.reload).to be_canceled - end - end - - context 'when build is not cancelable' do - let(:build) { create(:ci_build, :canceled, pipeline: pipeline) } - - it 'returns unprocessable_entity' do - expect(response).to have_http_status(:unprocessable_entity) - end - end - - def post_cancel - post :cancel, namespace_id: project.namespace, - project_id: project, - id: build.id - end - end - - describe 'POST cancel_all' do - before do - project.add_developer(user) - sign_in(user) - end - - context 'when builds are cancelable' do - before do - create_list(:ci_build, 2, :cancelable, pipeline: pipeline) - - post_cancel_all - end - - it 'redirects to a index page' do - expect(response).to have_http_status(:found) - expect(response).to redirect_to(namespace_project_builds_path) - end - - it 'transits to canceled' do - expect(Ci::Build.all).to all(be_canceled) - end - end - - context 'when builds are not cancelable' do - before do - create_list(:ci_build, 2, :canceled, pipeline: pipeline) - - post_cancel_all - end - - it 'redirects to a index page' do - expect(response).to have_http_status(:found) - expect(response).to redirect_to(namespace_project_builds_path) - end - end - - def post_cancel_all - post :cancel_all, namespace_id: project.namespace, - project_id: project - end - end - - describe 'POST erase' do - before do - project.add_developer(user) - sign_in(user) - - post_erase - end - - context 'when build is erasable' do - let(:build) { create(:ci_build, :erasable, :trace, pipeline: pipeline) } - - it 'redirects to the erased build page' do - expect(response).to have_http_status(:found) - expect(response).to redirect_to(namespace_project_build_path(id: build.id)) - end - - it 'erases artifacts' do - expect(build.artifacts_file.exists?).to be_falsey - expect(build.artifacts_metadata.exists?).to be_falsey - end - - it 'erases trace' do - expect(build.trace.exist?).to be_falsey - end - end - - context 'when build is not erasable' do - let(:build) { create(:ci_build, :erased, pipeline: pipeline) } - - it 'returns unprocessable_entity' do - expect(response).to have_http_status(:unprocessable_entity) - end - end - - def post_erase - post :erase, namespace_id: project.namespace, - project_id: project, - id: build.id - end - end - - describe 'GET raw' do - before do - get_raw - end - - context 'when build has a trace file' do - let(:build) { create(:ci_build, :trace, pipeline: pipeline) } - - it 'send a trace file' do - expect(response).to have_http_status(:ok) - expect(response.content_type).to eq 'text/plain; charset=utf-8' - expect(response.body).to eq 'BUILD TRACE' - end - end - - context 'when build does not have a trace file' do - let(:build) { create(:ci_build, pipeline: pipeline) } - - it 'returns not_found' do - expect(response).to have_http_status(:not_found) - end - end - - def get_raw - post :raw, namespace_id: project.namespace, - project_id: project, - id: build.id - end - end -end diff --git a/spec/controllers/projects/environments_controller_spec.rb b/spec/controllers/projects/environments_controller_spec.rb index c0f8c36a018..ac81f65ba0a 100644 --- a/spec/controllers/projects/environments_controller_spec.rb +++ b/spec/controllers/projects/environments_controller_spec.rb @@ -172,7 +172,7 @@ describe Projects::EnvironmentsController do expect(response).to have_http_status(200) expect(json_response).to eq( { 'redirect_url' => - "http://test.host/#{project.path_with_namespace}/builds/#{action.id}" }) + "http://test.host/#{project.path_with_namespace}/jobs/#{action.id}" }) end end diff --git a/spec/controllers/projects/jobs_controller_spec.rb b/spec/controllers/projects/jobs_controller_spec.rb new file mode 100644 index 00000000000..3a36f4c6198 --- /dev/null +++ b/spec/controllers/projects/jobs_controller_spec.rb @@ -0,0 +1,446 @@ +require 'spec_helper' + +describe Projects::JobsController do + include ApiHelpers + + let(:project) { create(:empty_project, :public) } + let(:pipeline) { create(:ci_pipeline, project: project) } + let(:user) { create(:user) } + + describe 'GET index' do + context 'when scope is pending' do + before do + create(:ci_build, :pending, pipeline: pipeline) + + get_index(scope: 'pending') + end + + it 'has only pending builds' do + expect(response).to have_http_status(:ok) + expect(assigns(:builds).first.status).to eq('pending') + end + end + + context 'when scope is running' do + before do + create(:ci_build, :running, pipeline: pipeline) + + get_index(scope: 'running') + end + + it 'has only running builds' do + expect(response).to have_http_status(:ok) + expect(assigns(:builds).first.status).to eq('running') + end + end + + context 'when scope is finished' do + before do + create(:ci_build, :success, pipeline: pipeline) + + get_index(scope: 'finished') + end + + it 'has only finished builds' do + expect(response).to have_http_status(:ok) + expect(assigns(:builds).first.status).to eq('success') + end + end + + context 'when page is specified' do + let(:last_page) { project.builds.page.total_pages } + + context 'when page number is eligible' do + before do + create_list(:ci_build, 2, pipeline: pipeline) + + get_index(page: last_page.to_param) + end + + it 'redirects to the page' do + expect(response).to have_http_status(:ok) + expect(assigns(:builds).current_page).to eq(last_page) + end + end + end + + context 'number of queries' do + before do + Ci::Build::AVAILABLE_STATUSES.each do |status| + create_build(status, status) + end + + RequestStore.begin! + end + + after do + RequestStore.end! + RequestStore.clear! + end + + it "verifies number of queries" do + recorded = ActiveRecord::QueryRecorder.new { get_index } + expect(recorded.count).to be_within(5).of(8) + end + + def create_build(name, status) + pipeline = create(:ci_pipeline, project: project) + create(:ci_build, :tags, :triggered, :artifacts, + pipeline: pipeline, name: name, status: status) + end + end + + def get_index(**extra_params) + params = { + namespace_id: project.namespace.to_param, + project_id: project + } + + get :index, params.merge(extra_params) + end + end + + describe 'GET show' do + context 'when build exists' do + let!(:build) { create(:ci_build, pipeline: pipeline) } + + before do + get_show(id: build.id) + end + + it 'has a build' do + expect(response).to have_http_status(:ok) + expect(assigns(:build).id).to eq(build.id) + end + end + + context 'when build does not exist' do + before do + get_show(id: 1234) + end + + it 'renders not_found' do + expect(response).to have_http_status(:not_found) + end + end + + def get_show(**extra_params) + params = { + namespace_id: project.namespace.to_param, + project_id: project + } + + get :show, params.merge(extra_params) + end + end + + describe 'GET trace.json' do + before do + get_trace + end + + context 'when build has a trace' do + let(:build) { create(:ci_build, :trace, pipeline: pipeline) } + + it 'returns a trace' do + expect(response).to have_http_status(:ok) + expect(json_response['html']).to eq('BUILD TRACE') + end + end + + context 'when build has no traces' do + let(:build) { create(:ci_build, pipeline: pipeline) } + + it 'returns no traces' do + expect(response).to have_http_status(:ok) + expect(json_response['html']).to be_nil + end + end + + def get_trace + get :trace, namespace_id: project.namespace, + project_id: project, + id: build.id, + format: :json + end + end + + describe 'GET status.json' do + let(:build) { create(:ci_build, pipeline: pipeline) } + let(:status) { build.detailed_status(double('user')) } + + before do + get :status, namespace_id: project.namespace, + project_id: project, + id: build.id, + format: :json + end + + it 'return a detailed build status in json' do + expect(response).to have_http_status(:ok) + expect(json_response['text']).to eq status.text + expect(json_response['label']).to eq status.label + expect(json_response['icon']).to eq status.icon + expect(json_response['favicon']).to eq "/assets/ci_favicons/#{status.favicon}.ico" + end + end + + describe 'GET trace.json' do + let(:pipeline) { create(:ci_pipeline, project: project) } + let(:build) { create(:ci_build, pipeline: pipeline) } + let(:user) { create(:user) } + + context 'when user is logged in as developer' do + before do + project.add_developer(user) + sign_in(user) + + get_trace + end + + it 'traces build log' do + expect(response).to have_http_status(:ok) + expect(json_response['id']).to eq build.id + expect(json_response['status']).to eq build.status + end + end + + context 'when user is logged in as non member' do + before do + sign_in(user) + + get_trace + end + + it 'traces build log' do + expect(response).to have_http_status(:ok) + expect(json_response['id']).to eq build.id + expect(json_response['status']).to eq build.status + end + end + + def get_trace + get :trace, namespace_id: project.namespace, + project_id: project, + id: build.id, + format: :json + end + end + + describe 'POST retry' do + before do + project.add_developer(user) + sign_in(user) + + post_retry + end + + context 'when build is retryable' do + let(:build) { create(:ci_build, :retryable, pipeline: pipeline) } + + it 'redirects to the retried build page' do + expect(response).to have_http_status(:found) + expect(response).to redirect_to(namespace_project_job_path(id: Ci::Build.last.id)) + end + end + + context 'when build is not retryable' do + let(:build) { create(:ci_build, pipeline: pipeline) } + + it 'renders unprocessable_entity' do + expect(response).to have_http_status(:unprocessable_entity) + end + end + + def post_retry + post :retry, namespace_id: project.namespace, + project_id: project, + id: build.id + end + end + + describe 'POST play' do + before do + project.add_master(user) + sign_in(user) + + post_play + end + + context 'when build is playable' do + let(:build) { create(:ci_build, :playable, pipeline: pipeline) } + + it 'redirects to the played build page' do + expect(response).to have_http_status(:found) + expect(response).to redirect_to(namespace_project_job_path(id: build.id)) + end + + it 'transits to pending' do + expect(build.reload).to be_pending + end + end + + context 'when build is not playable' do + let(:build) { create(:ci_build, pipeline: pipeline) } + + it 'renders unprocessable_entity' do + expect(response).to have_http_status(:unprocessable_entity) + end + end + + def post_play + post :play, namespace_id: project.namespace, + project_id: project, + id: build.id + end + end + + describe 'POST cancel' do + before do + project.add_developer(user) + sign_in(user) + + post_cancel + end + + context 'when build is cancelable' do + let(:build) { create(:ci_build, :cancelable, pipeline: pipeline) } + + it 'redirects to the canceled build page' do + expect(response).to have_http_status(:found) + expect(response).to redirect_to(namespace_project_job_path(id: build.id)) + end + + it 'transits to canceled' do + expect(build.reload).to be_canceled + end + end + + context 'when build is not cancelable' do + let(:build) { create(:ci_build, :canceled, pipeline: pipeline) } + + it 'returns unprocessable_entity' do + expect(response).to have_http_status(:unprocessable_entity) + end + end + + def post_cancel + post :cancel, namespace_id: project.namespace, + project_id: project, + id: build.id + end + end + + describe 'POST cancel_all' do + before do + project.add_developer(user) + sign_in(user) + end + + context 'when builds are cancelable' do + before do + create_list(:ci_build, 2, :cancelable, pipeline: pipeline) + + post_cancel_all + end + + it 'redirects to a index page' do + expect(response).to have_http_status(:found) + expect(response).to redirect_to(namespace_project_jobs_path) + end + + it 'transits to canceled' do + expect(Ci::Build.all).to all(be_canceled) + end + end + + context 'when builds are not cancelable' do + before do + create_list(:ci_build, 2, :canceled, pipeline: pipeline) + + post_cancel_all + end + + it 'redirects to a index page' do + expect(response).to have_http_status(:found) + expect(response).to redirect_to(namespace_project_jobs_path) + end + end + + def post_cancel_all + post :cancel_all, namespace_id: project.namespace, + project_id: project + end + end + + describe 'POST erase' do + before do + project.add_developer(user) + sign_in(user) + + post_erase + end + + context 'when build is erasable' do + let(:build) { create(:ci_build, :erasable, :trace, pipeline: pipeline) } + + it 'redirects to the erased build page' do + expect(response).to have_http_status(:found) + expect(response).to redirect_to(namespace_project_job_path(id: build.id)) + end + + it 'erases artifacts' do + expect(build.artifacts_file.exists?).to be_falsey + expect(build.artifacts_metadata.exists?).to be_falsey + end + + it 'erases trace' do + expect(build.trace.exist?).to be_falsey + end + end + + context 'when build is not erasable' do + let(:build) { create(:ci_build, :erased, pipeline: pipeline) } + + it 'returns unprocessable_entity' do + expect(response).to have_http_status(:unprocessable_entity) + end + end + + def post_erase + post :erase, namespace_id: project.namespace, + project_id: project, + id: build.id + end + end + + describe 'GET raw' do + before do + get_raw + end + + context 'when build has a trace file' do + let(:build) { create(:ci_build, :trace, pipeline: pipeline) } + + it 'send a trace file' do + expect(response).to have_http_status(:ok) + expect(response.content_type).to eq 'text/plain; charset=utf-8' + expect(response.body).to eq 'BUILD TRACE' + end + end + + context 'when build does not have a trace file' do + let(:build) { create(:ci_build, pipeline: pipeline) } + + it 'returns not_found' do + expect(response).to have_http_status(:not_found) + end + end + + def get_raw + post :raw, namespace_id: project.namespace, + project_id: project, + id: build.id + end + end +end diff --git a/spec/features/admin/admin_builds_spec.rb b/spec/features/admin/admin_builds_spec.rb index 9d5ce876c29..999ce3611b5 100644 --- a/spec/features/admin/admin_builds_spec.rb +++ b/spec/features/admin/admin_builds_spec.rb @@ -16,7 +16,7 @@ describe 'Admin Builds' do create(:ci_build, pipeline: pipeline, status: :success) create(:ci_build, pipeline: pipeline, status: :failed) - visit admin_builds_path + visit admin_jobs_path expect(page).to have_selector('.nav-links li.active', text: 'All') expect(page).to have_selector('.row-content-block', text: 'All jobs') @@ -27,7 +27,7 @@ describe 'Admin Builds' do context 'when have no jobs' do it 'shows a message' do - visit admin_builds_path + visit admin_jobs_path expect(page).to have_selector('.nav-links li.active', text: 'All') expect(page).to have_content 'No jobs to show' @@ -44,7 +44,7 @@ describe 'Admin Builds' do build3 = create(:ci_build, pipeline: pipeline, status: :success) build4 = create(:ci_build, pipeline: pipeline, status: :failed) - visit admin_builds_path(scope: :pending) + visit admin_jobs_path(scope: :pending) expect(page).to have_selector('.nav-links li.active', text: 'Pending') expect(page.find('.build-link')).to have_content(build1.id) @@ -59,7 +59,7 @@ describe 'Admin Builds' do it 'shows a message' do create(:ci_build, pipeline: pipeline, status: :success) - visit admin_builds_path(scope: :pending) + visit admin_jobs_path(scope: :pending) expect(page).to have_selector('.nav-links li.active', text: 'Pending') expect(page).to have_content 'No jobs to show' @@ -76,7 +76,7 @@ describe 'Admin Builds' do build3 = create(:ci_build, pipeline: pipeline, status: :failed) build4 = create(:ci_build, pipeline: pipeline, status: :pending) - visit admin_builds_path(scope: :running) + visit admin_jobs_path(scope: :running) expect(page).to have_selector('.nav-links li.active', text: 'Running') expect(page.find('.build-link')).to have_content(build1.id) @@ -91,7 +91,7 @@ describe 'Admin Builds' do it 'shows a message' do create(:ci_build, pipeline: pipeline, status: :success) - visit admin_builds_path(scope: :running) + visit admin_jobs_path(scope: :running) expect(page).to have_selector('.nav-links li.active', text: 'Running') expect(page).to have_content 'No jobs to show' @@ -107,7 +107,7 @@ describe 'Admin Builds' do build2 = create(:ci_build, pipeline: pipeline, status: :running) build3 = create(:ci_build, pipeline: pipeline, status: :success) - visit admin_builds_path(scope: :finished) + visit admin_jobs_path(scope: :finished) expect(page).to have_selector('.nav-links li.active', text: 'Finished') expect(page.find('.build-link')).not_to have_content(build1.id) @@ -121,7 +121,7 @@ describe 'Admin Builds' do it 'shows a message' do create(:ci_build, pipeline: pipeline, status: :running) - visit admin_builds_path(scope: :finished) + visit admin_jobs_path(scope: :finished) expect(page).to have_selector('.nav-links li.active', text: 'Finished') expect(page).to have_content 'No jobs to show' diff --git a/spec/features/merge_requests/mini_pipeline_graph_spec.rb b/spec/features/merge_requests/mini_pipeline_graph_spec.rb index 5b2798af32f..68edac30f36 100644 --- a/spec/features/merge_requests/mini_pipeline_graph_spec.rb +++ b/spec/features/merge_requests/mini_pipeline_graph_spec.rb @@ -85,7 +85,7 @@ feature 'Mini Pipeline Graph', :js, :feature do build_item.click find('.build-page') - expect(current_path).to eql(namespace_project_build_path(project.namespace, project, build)) + expect(current_path).to eql(namespace_project_job_path(project.namespace, project, build)) end it 'should show tooltip when hovered' do diff --git a/spec/features/projects/artifacts/file_spec.rb b/spec/features/projects/artifacts/file_spec.rb index 74308a7e8dd..adc44fe5602 100644 --- a/spec/features/projects/artifacts/file_spec.rb +++ b/spec/features/projects/artifacts/file_spec.rb @@ -6,7 +6,7 @@ feature 'Artifact file', :js, feature: true do let(:build) { create(:ci_build, :artifacts, pipeline: pipeline) } def visit_file(path) - visit file_namespace_project_build_artifacts_path(project.namespace, project, build, path) + visit file_namespace_project_job_artifacts_path(project.namespace, project, build, path) end context 'Text file' do diff --git a/spec/features/projects/builds_spec.rb b/spec/features/projects/builds_spec.rb index ab10434e10c..a3dd8a4edd2 100644 --- a/spec/features/projects/builds_spec.rb +++ b/spec/features/projects/builds_spec.rb @@ -1,7 +1,7 @@ require 'spec_helper' require 'tempfile' -feature 'Builds', :feature do +feature 'Jobs', :feature do let(:user) { create(:user) } let(:user_access_level) { :developer } let(:project) { create(:project) } @@ -19,12 +19,12 @@ feature 'Builds', :feature do login_as(user) end - describe "GET /:project/builds" do + describe "GET /:project/jobs" do let!(:build) { create(:ci_build, pipeline: pipeline) } context "Pending scope" do before do - visit namespace_project_builds_path(project.namespace, project, scope: :pending) + visit namespace_project_jobs_path(project.namespace, project, scope: :pending) end it "shows Pending tab jobs" do @@ -39,7 +39,7 @@ feature 'Builds', :feature do context "Running scope" do before do build.run! - visit namespace_project_builds_path(project.namespace, project, scope: :running) + visit namespace_project_jobs_path(project.namespace, project, scope: :running) end it "shows Running tab jobs" do @@ -54,7 +54,7 @@ feature 'Builds', :feature do context "Finished scope" do before do build.run! - visit namespace_project_builds_path(project.namespace, project, scope: :finished) + visit namespace_project_jobs_path(project.namespace, project, scope: :finished) end it "shows Finished tab jobs" do @@ -67,7 +67,7 @@ feature 'Builds', :feature do context "All jobs" do before do project.builds.running_or_pending.each(&:success) - visit namespace_project_builds_path(project.namespace, project) + visit namespace_project_jobs_path(project.namespace, project) end it "shows All tab jobs" do @@ -80,10 +80,10 @@ feature 'Builds', :feature do end end - describe "POST /:project/builds/:id/cancel_all" do + describe "POST /:project/jobs/:id/cancel_all" do before do build.run! - visit namespace_project_builds_path(project.namespace, project) + visit namespace_project_jobs_path(project.namespace, project) click_link "Cancel running" end @@ -97,10 +97,10 @@ feature 'Builds', :feature do end end - describe "GET /:project/builds/:id" do + describe "GET /:project/jobs/:id" do context "Job from project" do before do - visit namespace_project_build_path(project.namespace, project, build) + visit namespace_project_job_path(project.namespace, project, build) end it 'shows commit`s data' do @@ -117,7 +117,7 @@ feature 'Builds', :feature do context "Job from other project" do before do - visit namespace_project_build_path(project.namespace, project, build2) + visit namespace_project_job_path(project.namespace, project, build2) end it { expect(page.status_code).to eq(404) } @@ -126,7 +126,7 @@ feature 'Builds', :feature do context "Download artifacts" do before do build.update_attributes(artifacts_file: artifacts_file) - visit namespace_project_build_path(project.namespace, project, build) + visit namespace_project_job_path(project.namespace, project, build) end it 'has button to download artifacts' do @@ -139,7 +139,7 @@ feature 'Builds', :feature do build.update_attributes(artifacts_file: artifacts_file, artifacts_expire_at: expire_at) - visit namespace_project_build_path(project.namespace, project, build) + visit namespace_project_job_path(project.namespace, project, build) end context 'no expire date defined' do @@ -186,7 +186,8 @@ feature 'Builds', :feature do feature 'Raw trace' do before do build.run! - visit namespace_project_build_path(project.namespace, project, build) + + visit namespace_project_job_path(project.namespace, project, build) end it do @@ -198,7 +199,7 @@ feature 'Builds', :feature do before do build.run! - visit namespace_project_build_path(project.namespace, project, build) + visit namespace_project_job_path(project.namespace, project, build) end context 'when job has an initial trace' do @@ -222,7 +223,7 @@ feature 'Builds', :feature do end before do - visit namespace_project_build_path(project.namespace, project, build) + visit namespace_project_job_path(project.namespace, project, build) end it 'shows variable key and value after click', js: true do @@ -247,7 +248,7 @@ feature 'Builds', :feature do let(:build) { create(:ci_build, :success, environment: environment.name, deployments: [deployment], pipeline: pipeline) } it 'shows a link for the job' do - visit namespace_project_build_path(project.namespace, project, build) + visit namespace_project_job_path(project.namespace, project, build) expect(page).to have_link environment.name end @@ -257,7 +258,7 @@ feature 'Builds', :feature do let(:build) { create(:ci_build, :failed, environment: environment.name, pipeline: pipeline) } it 'shows a link for the job' do - visit namespace_project_build_path(project.namespace, project, build) + visit namespace_project_job_path(project.namespace, project, build) expect(page).to have_link environment.name end @@ -268,7 +269,7 @@ feature 'Builds', :feature do let(:build) { create(:ci_build, :success, environment: environment.name, pipeline: pipeline) } it 'shows a link to latest deployment' do - visit namespace_project_build_path(project.namespace, project, build) + visit namespace_project_job_path(project.namespace, project, build) expect(page).to have_link('latest deployment') end @@ -280,7 +281,7 @@ feature 'Builds', :feature do context "Job from project" do before do build.run! - visit namespace_project_build_path(project.namespace, project, build) + visit namespace_project_job_path(project.namespace, project, build) click_link "Cancel" end @@ -294,8 +295,8 @@ feature 'Builds', :feature do context "Job from other project" do before do build.run! - visit namespace_project_build_path(project.namespace, project, build) - page.driver.post(cancel_namespace_project_build_path(project.namespace, project, build2)) + visit namespace_project_job_path(project.namespace, project, build) + page.driver.post(cancel_namespace_project_job_path(project.namespace, project, build2)) end it { expect(page.status_code).to eq(404) } @@ -306,7 +307,7 @@ feature 'Builds', :feature do context "Job from project" do before do build.run! - visit namespace_project_build_path(project.namespace, project, build) + visit namespace_project_job_path(project.namespace, project, build) click_link 'Cancel' page.within('.build-header') do click_link 'Retry job' @@ -325,9 +326,9 @@ feature 'Builds', :feature do context "Build from other project" do before do build.run! - visit namespace_project_build_path(project.namespace, project, build) + visit namespace_project_job_path(project.namespace, project, build) click_link 'Cancel' - page.driver.post(retry_namespace_project_build_path(project.namespace, project, build2)) + page.driver.post(retry_namespace_project_job_path(project.namespace, project, build2)) end it { expect(page).to have_http_status(404) } @@ -341,7 +342,7 @@ feature 'Builds', :feature do logout_direct login_with(create(:user)) - visit namespace_project_build_path(project.namespace, project, build) + visit namespace_project_job_path(project.namespace, project, build) end it 'does not show the Retry button' do @@ -355,14 +356,14 @@ feature 'Builds', :feature do describe "GET /:project/builds/:id/download" do before do build.update_attributes(artifacts_file: artifacts_file) - visit namespace_project_build_path(project.namespace, project, build) + visit namespace_project_job_path(project.namespace, project, build) click_link 'Download' end context "Build from other project" do before do build2.update_attributes(artifacts_file: artifacts_file) - visit download_namespace_project_build_artifacts_path(project.namespace, project, build2) + visit download_namespace_project_job_artifacts_path(project.namespace, project, build2) end it { expect(page.status_code).to eq(404) } @@ -375,7 +376,7 @@ feature 'Builds', :feature do before do Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile') build.run! - visit namespace_project_build_path(project.namespace, project, build) + visit namespace_project_job_path(project.namespace, project, build) page.within('.js-build-sidebar') { click_link 'Raw' } end @@ -390,7 +391,7 @@ feature 'Builds', :feature do before do Capybara.current_session.driver.header('X-Sendfile-Type', 'X-Sendfile') build2.run! - visit raw_namespace_project_build_path(project.namespace, project, build2) + visit raw_namespace_project_job_path(project.namespace, project, build2) end it 'sends the right headers' do @@ -410,7 +411,7 @@ feature 'Builds', :feature do allow_any_instance_of(Gitlab::Ci::Trace).to receive(:paths) .and_return(paths) - visit namespace_project_build_path(project.namespace, project, build) + visit namespace_project_job_path(project.namespace, project, build) end context 'when build has trace in file' do @@ -442,7 +443,7 @@ feature 'Builds', :feature do describe "GET /:project/builds/:id/trace.json" do context "Build from project" do before do - visit trace_namespace_project_build_path(project.namespace, project, build, format: :json) + visit trace_namespace_project_job_path(project.namespace, project, build, format: :json) end it { expect(page.status_code).to eq(200) } @@ -450,7 +451,7 @@ feature 'Builds', :feature do context "Build from other project" do before do - visit trace_namespace_project_build_path(project.namespace, project, build2, format: :json) + visit trace_namespace_project_job_path(project.namespace, project, build2, format: :json) end it { expect(page.status_code).to eq(404) } @@ -460,7 +461,7 @@ feature 'Builds', :feature do describe "GET /:project/builds/:id/status" do context "Build from project" do before do - visit status_namespace_project_build_path(project.namespace, project, build) + visit status_namespace_project_job_path(project.namespace, project, build) end it { expect(page.status_code).to eq(200) } @@ -468,7 +469,7 @@ feature 'Builds', :feature do context "Build from other project" do before do - visit status_namespace_project_build_path(project.namespace, project, build2) + visit status_namespace_project_job_path(project.namespace, project, build2) end it { expect(page.status_code).to eq(404) } diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb index 78a76d9c112..2a2655bbdb5 100644 --- a/spec/features/security/project/internal_access_spec.rb +++ b/spec/features/security/project/internal_access_spec.rb @@ -334,7 +334,7 @@ describe "Internal Project Access", feature: true do end describe "GET /:project_path/builds" do - subject { namespace_project_builds_path(project.namespace, project) } + subject { namespace_project_jobs_path(project.namespace, project) } context "when allowed for public and internal" do before { project.update(public_builds: true) } @@ -368,7 +368,7 @@ describe "Internal Project Access", feature: true do describe "GET /:project_path/builds/:id" do let(:pipeline) { create(:ci_pipeline, project: project) } let(:build) { create(:ci_build, pipeline: pipeline) } - subject { namespace_project_build_path(project.namespace, project, build.id) } + subject { namespace_project_job_path(project.namespace, project, build.id) } context "when allowed for public and internal" do before { project.update(public_builds: true) } @@ -402,7 +402,7 @@ describe "Internal Project Access", feature: true do describe 'GET /:project_path/builds/:id/trace' do let(:pipeline) { create(:ci_pipeline, project: project) } let(:build) { create(:ci_build, pipeline: pipeline) } - subject { trace_namespace_project_build_path(project.namespace, project, build.id) } + subject { trace_namespace_project_job_path(project.namespace, project, build.id) } context 'when allowed for public and internal' do before do diff --git a/spec/features/security/project/private_access_spec.rb b/spec/features/security/project/private_access_spec.rb index a66f6e09055..b676c236758 100644 --- a/spec/features/security/project/private_access_spec.rb +++ b/spec/features/security/project/private_access_spec.rb @@ -330,7 +330,7 @@ describe "Private Project Access", feature: true do end describe "GET /:project_path/builds" do - subject { namespace_project_builds_path(project.namespace, project) } + subject { namespace_project_jobs_path(project.namespace, project) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -358,7 +358,7 @@ describe "Private Project Access", feature: true do describe "GET /:project_path/builds/:id" do let(:pipeline) { create(:ci_pipeline, project: project) } let(:build) { create(:ci_build, pipeline: pipeline) } - subject { namespace_project_build_path(project.namespace, project, build.id) } + subject { namespace_project_job_path(project.namespace, project, build.id) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } @@ -391,7 +391,7 @@ describe "Private Project Access", feature: true do describe 'GET /:project_path/builds/:id/trace' do let(:pipeline) { create(:ci_pipeline, project: project) } let(:build) { create(:ci_build, pipeline: pipeline) } - subject { trace_namespace_project_build_path(project.namespace, project, build.id) } + subject { trace_namespace_project_job_path(project.namespace, project, build.id) } it { is_expected.to be_allowed_for(:admin) } it { is_expected.to be_allowed_for(:owner).of(project) } diff --git a/spec/features/security/project/public_access_spec.rb b/spec/features/security/project/public_access_spec.rb index 5cd575500c3..35d5163941e 100644 --- a/spec/features/security/project/public_access_spec.rb +++ b/spec/features/security/project/public_access_spec.rb @@ -154,7 +154,7 @@ describe "Public Project Access", feature: true do end describe "GET /:project_path/builds" do - subject { namespace_project_builds_path(project.namespace, project) } + subject { namespace_project_jobs_path(project.namespace, project) } context "when allowed for public" do before { project.update(public_builds: true) } @@ -188,7 +188,7 @@ describe "Public Project Access", feature: true do describe "GET /:project_path/builds/:id" do let(:pipeline) { create(:ci_pipeline, project: project) } let(:build) { create(:ci_build, pipeline: pipeline) } - subject { namespace_project_build_path(project.namespace, project, build.id) } + subject { namespace_project_job_path(project.namespace, project, build.id) } context "when allowed for public" do before { project.update(public_builds: true) } @@ -222,7 +222,7 @@ describe "Public Project Access", feature: true do describe 'GET /:project_path/builds/:id/trace' do let(:pipeline) { create(:ci_pipeline, project: project) } let(:build) { create(:ci_build, pipeline: pipeline) } - subject { trace_namespace_project_build_path(project.namespace, project, build.id) } + subject { trace_namespace_project_job_path(project.namespace, project, build.id) } context 'when allowed for public' do before do diff --git a/spec/javascripts/build_spec.js b/spec/javascripts/build_spec.js index 8ec96bdb583..93e96676468 100644 --- a/spec/javascripts/build_spec.js +++ b/spec/javascripts/build_spec.js @@ -8,7 +8,7 @@ import '~/breakpoints'; import 'vendor/jquery.nicescroll'; describe('Build', () => { - const BUILD_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/builds/1`; + const BUILD_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/jobs/1`; preloadFixtures('builds/build-with-artifacts.html.raw'); diff --git a/spec/javascripts/fixtures/builds.rb b/spec/javascripts/fixtures/builds.rb deleted file mode 100644 index 320de791b08..00000000000 --- a/spec/javascripts/fixtures/builds.rb +++ /dev/null @@ -1,33 +0,0 @@ -require 'spec_helper' - -describe Projects::BuildsController, '(JavaScript fixtures)', type: :controller do - include JavaScriptFixturesHelpers - - let(:admin) { create(:admin) } - let(:namespace) { create(:namespace, name: 'frontend-fixtures' )} - let(:project) { create(:project_empty_repo, namespace: namespace, path: 'builds-project') } - let(:pipeline) { create(:ci_empty_pipeline, project: project) } - let!(:build_with_artifacts) { create(:ci_build, :success, :artifacts, :trace, pipeline: pipeline, stage: 'test', artifacts_expire_at: Time.now + 18.months) } - let!(:failed_build) { create(:ci_build, :failed, pipeline: pipeline, stage: 'build') } - let!(:pending_build) { create(:ci_build, :pending, pipeline: pipeline, stage: 'deploy') } - - render_views - - before(:all) do - clean_frontend_fixtures('builds/') - end - - before(:each) do - sign_in(admin) - end - - it 'builds/build-with-artifacts.html.raw' do |example| - get :show, - namespace_id: project.namespace.to_param, - project_id: project, - id: build_with_artifacts.to_param - - expect(response).to be_success - store_frontend_fixture(response, example.description) - end -end diff --git a/spec/javascripts/fixtures/jobs.rb b/spec/javascripts/fixtures/jobs.rb new file mode 100644 index 00000000000..dc7dde1138c --- /dev/null +++ b/spec/javascripts/fixtures/jobs.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +describe Projects::JobsController, '(JavaScript fixtures)', type: :controller do + include JavaScriptFixturesHelpers + + let(:admin) { create(:admin) } + let(:namespace) { create(:namespace, name: 'frontend-fixtures' )} + let(:project) { create(:project_empty_repo, namespace: namespace, path: 'builds-project') } + let(:pipeline) { create(:ci_empty_pipeline, project: project) } + let!(:build_with_artifacts) { create(:ci_build, :success, :artifacts, :trace, pipeline: pipeline, stage: 'test', artifacts_expire_at: Time.now + 18.months) } + let!(:failed_build) { create(:ci_build, :failed, pipeline: pipeline, stage: 'build') } + let!(:pending_build) { create(:ci_build, :pending, pipeline: pipeline, stage: 'deploy') } + + render_views + + before(:all) do + clean_frontend_fixtures('builds/') + end + + before(:each) do + sign_in(admin) + end + + it 'builds/build-with-artifacts.html.raw' do |example| + get :show, + namespace_id: project.namespace.to_param, + project_id: project, + id: build_with_artifacts.to_param + + expect(response).to be_success + store_frontend_fixture(response, example.description) + end +end diff --git a/spec/javascripts/lib/utils/common_utils_spec.js b/spec/javascripts/lib/utils/common_utils_spec.js index 42a9067ade5..afa8c791038 100644 --- a/spec/javascripts/lib/utils/common_utils_spec.js +++ b/spec/javascripts/lib/utils/common_utils_spec.js @@ -356,7 +356,7 @@ require('~/lib/utils/common_utils'); describe('gl.utils.setCiStatusFavicon', () => { it('should set page favicon to CI status favicon based on provided status', () => { - const BUILD_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/builds/1/status.json`; + const BUILD_URL = `${gl.TEST_HOST}/frontend-fixtures/builds-project/jobs/1/status.json`; const FAVICON_PATH = '//icon_status_success'; const spySetFavicon = spyOn(gl.utils, 'setFavicon').and.stub(); const spyResetFavicon = spyOn(gl.utils, 'resetFavicon').and.stub(); diff --git a/spec/lib/gitlab/ci/status/build/common_spec.rb b/spec/lib/gitlab/ci/status/build/common_spec.rb index 40b96b1807b..72bd7c4eb93 100644 --- a/spec/lib/gitlab/ci/status/build/common_spec.rb +++ b/spec/lib/gitlab/ci/status/build/common_spec.rb @@ -31,7 +31,7 @@ describe Gitlab::Ci::Status::Build::Common do describe '#details_path' do it 'links to the build details page' do - expect(subject.details_path).to include "builds/#{build.id}" + expect(subject.details_path).to include "jobs/#{build.id}" end end end diff --git a/spec/serializers/build_action_entity_spec.rb b/spec/serializers/build_action_entity_spec.rb index 059deba5416..15720d86583 100644 --- a/spec/serializers/build_action_entity_spec.rb +++ b/spec/serializers/build_action_entity_spec.rb @@ -1,26 +1,26 @@ require 'spec_helper' describe BuildActionEntity do - let(:build) { create(:ci_build, name: 'test_build') } + let(:job) { create(:ci_build, name: 'test_job') } let(:request) { double('request') } let(:entity) do - described_class.new(build, request: spy('request')) + described_class.new(job, request: spy('request')) end describe '#as_json' do subject { entity.as_json } - it 'contains original build name' do - expect(subject[:name]).to eq 'test_build' + it 'contains original job name' do + expect(subject[:name]).to eq 'test_job' end it 'contains path to the action play' do - expect(subject[:path]).to include "builds/#{build.id}/play" + expect(subject[:path]).to include "jobs/#{job.id}/play" end it 'contains whether it is playable' do - expect(subject[:playable]).to eq build.playable? + expect(subject[:playable]).to eq job.playable? end end end diff --git a/spec/serializers/build_artifact_entity_spec.rb b/spec/serializers/build_artifact_entity_spec.rb index 2fc60aa9de6..b4eef20d6a6 100644 --- a/spec/serializers/build_artifact_entity_spec.rb +++ b/spec/serializers/build_artifact_entity_spec.rb @@ -1,22 +1,22 @@ require 'spec_helper' describe BuildArtifactEntity do - let(:build) { create(:ci_build, name: 'test:build') } + let(:job) { create(:ci_build, name: 'test:job') } let(:entity) do - described_class.new(build, request: double) + described_class.new(job, request: double) end describe '#as_json' do subject { entity.as_json } - it 'contains build name' do - expect(subject[:name]).to eq 'test:build' + it 'contains job name' do + expect(subject[:name]).to eq 'test:job' end it 'contains path to the artifacts' do expect(subject[:path]) - .to include "builds/#{build.id}/artifacts/download" + .to include "jobs/#{job.id}/artifacts/download" end end end diff --git a/spec/views/ci/status/_badge.html.haml_spec.rb b/spec/views/ci/status/_badge.html.haml_spec.rb index c62450fb8e2..72323da2838 100644 --- a/spec/views/ci/status/_badge.html.haml_spec.rb +++ b/spec/views/ci/status/_badge.html.haml_spec.rb @@ -16,7 +16,7 @@ describe 'ci/status/_badge', :view do end it 'has link to build details page' do - details_path = namespace_project_build_path( + details_path = namespace_project_job_path( project.namespace, project, build) render_status(build) diff --git a/spec/views/projects/builds/_build.html.haml_spec.rb b/spec/views/projects/builds/_build.html.haml_spec.rb deleted file mode 100644 index 751482cac42..00000000000 --- a/spec/views/projects/builds/_build.html.haml_spec.rb +++ /dev/null @@ -1,28 +0,0 @@ -require 'spec_helper' - -describe 'projects/ci/builds/_build' do - include Devise::Test::ControllerHelpers - - let(:project) { create(:project, :repository) } - let(:pipeline) { create(:ci_empty_pipeline, id: 1337, project: project, sha: project.commit.id) } - let(:build) { create(:ci_build, pipeline: pipeline, stage: 'test', stage_idx: 1, name: 'rspec 0:2', status: :pending) } - - before do - controller.prepend_view_path('app/views/projects') - allow(view).to receive(:can?).and_return(true) - end - - it 'won\'t include a column with a link to its pipeline by default' do - render partial: 'projects/ci/builds/build', locals: { build: build } - - expect(rendered).not_to have_link('#1337') - expect(rendered).not_to have_text('#1337 by API') - end - - it 'can include a column with a link to its pipeline' do - render partial: 'projects/ci/builds/build', locals: { build: build, pipeline_link: true } - - expect(rendered).to have_link('#1337') - expect(rendered).to have_text('#1337 by API') - end -end diff --git a/spec/views/projects/builds/_generic_commit_status.html.haml_spec.rb b/spec/views/projects/builds/_generic_commit_status.html.haml_spec.rb deleted file mode 100644 index dc2ffc9dc47..00000000000 --- a/spec/views/projects/builds/_generic_commit_status.html.haml_spec.rb +++ /dev/null @@ -1,28 +0,0 @@ -require 'spec_helper' - -describe 'projects/generic_commit_statuses/_generic_commit_status.html.haml' do - include Devise::Test::ControllerHelpers - - let(:project) { create(:project, :repository) } - let(:pipeline) { create(:ci_empty_pipeline, id: 1337, project: project, sha: project.commit.id) } - let(:generic_commit_status) { create(:generic_commit_status, pipeline: pipeline, stage: 'external', name: 'jenkins', stage_idx: 3) } - - before do - controller.prepend_view_path('app/views/projects') - allow(view).to receive(:can?).and_return(true) - end - - it 'won\'t include a column with a link to its pipeline by default' do - render partial: 'projects/generic_commit_statuses/generic_commit_status', locals: { generic_commit_status: generic_commit_status } - - expect(rendered).not_to have_link('#1337') - expect(rendered).not_to have_text('#1337 by API') - end - - it 'can include a column with a link to its pipeline' do - render partial: 'projects/generic_commit_statuses/generic_commit_status', locals: { generic_commit_status: generic_commit_status, pipeline_link: true } - - expect(rendered).to have_link('#1337') - expect(rendered).to have_text('#1337 by API') - end -end diff --git a/spec/views/projects/builds/show.html.haml_spec.rb b/spec/views/projects/builds/show.html.haml_spec.rb deleted file mode 100644 index 0f39df0f250..00000000000 --- a/spec/views/projects/builds/show.html.haml_spec.rb +++ /dev/null @@ -1,293 +0,0 @@ -require 'spec_helper' - -describe 'projects/builds/show', :view do - let(:project) { create(:project, :repository) } - let(:build) { create(:ci_build, pipeline: pipeline) } - - let(:pipeline) do - create(:ci_pipeline, project: project, sha: project.commit.id) - end - - before do - assign(:build, build.present) - assign(:project, project) - - allow(view).to receive(:can?).and_return(true) - end - - describe 'job information in header' do - let(:build) do - create(:ci_build, :success, environment: 'staging') - end - - before do - render - end - - it 'shows status name' do - expect(rendered).to have_css('.ci-status.ci-success', text: 'passed') - end - - it 'does not render a link to the job' do - expect(rendered).not_to have_link('passed') - end - - it 'shows job id' do - expect(rendered).to have_css('.js-build-id', text: build.id) - end - - it 'shows a link to the pipeline' do - expect(rendered).to have_link(build.pipeline.id) - end - - it 'shows a link to the commit' do - expect(rendered).to have_link(build.pipeline.short_sha) - end - end - - describe 'environment info in job view' do - context 'job with latest deployment' do - let(:build) do - create(:ci_build, :success, environment: 'staging') - end - - before do - create(:environment, name: 'staging') - create(:deployment, deployable: build) - end - - it 'shows deployment message' do - expected_text = 'This job is the most recent deployment' - render - - expect(rendered).to have_css( - '.environment-information', text: expected_text) - end - end - - context 'job with outdated deployment' do - let(:build) do - create(:ci_build, :success, environment: 'staging', pipeline: pipeline) - end - - let(:second_build) do - create(:ci_build, :success, environment: 'staging', pipeline: pipeline) - end - - let(:environment) do - create(:environment, name: 'staging', project: project) - end - - let!(:first_deployment) do - create(:deployment, environment: environment, deployable: build) - end - - let!(:second_deployment) do - create(:deployment, environment: environment, deployable: second_build) - end - - it 'shows deployment message' do - expected_text = 'This job is an out-of-date deployment ' \ - "to staging.\nView the most recent deployment ##{second_deployment.iid}." - render - - expect(rendered).to have_css('.environment-information', text: expected_text) - end - end - - context 'job failed to deploy' do - let(:build) do - create(:ci_build, :failed, environment: 'staging', pipeline: pipeline) - end - - let!(:environment) do - create(:environment, name: 'staging', project: project) - end - - it 'shows deployment message' do - expected_text = 'The deployment of this job to staging did not succeed.' - render - - expect(rendered).to have_css( - '.environment-information', text: expected_text) - end - end - - context 'job will deploy' do - let(:build) do - create(:ci_build, :running, environment: 'staging', pipeline: pipeline) - end - - context 'when environment exists' do - let!(:environment) do - create(:environment, name: 'staging', project: project) - end - - it 'shows deployment message' do - expected_text = 'This job is creating a deployment to staging' - render - - expect(rendered).to have_css( - '.environment-information', text: expected_text) - end - - context 'when it has deployment' do - let!(:deployment) do - create(:deployment, environment: environment) - end - - it 'shows that deployment will be overwritten' do - expected_text = 'This job is creating a deployment to staging' - render - - expect(rendered).to have_css( - '.environment-information', text: expected_text) - expect(rendered).to have_css( - '.environment-information', text: 'latest deployment') - end - end - end - - context 'when environment does not exist' do - it 'shows deployment message' do - expected_text = 'This job is creating a deployment to staging' - render - - expect(rendered).to have_css( - '.environment-information', text: expected_text) - expect(rendered).not_to have_css( - '.environment-information', text: 'latest deployment') - end - end - end - - context 'job that failed to deploy and environment has not been created' do - let(:build) do - create(:ci_build, :failed, environment: 'staging', pipeline: pipeline) - end - - let!(:environment) do - create(:environment, name: 'staging', project: project) - end - - it 'shows deployment message' do - expected_text = 'The deployment of this job to staging did not succeed' - render - - expect(rendered).to have_css( - '.environment-information', text: expected_text) - end - end - - context 'job that will deploy and environment has not been created' do - let(:build) do - create(:ci_build, :running, environment: 'staging', pipeline: pipeline) - end - - let!(:environment) do - create(:environment, name: 'staging', project: project) - end - - it 'shows deployment message' do - expected_text = 'This job is creating a deployment to staging' - render - - expect(rendered).to have_css( - '.environment-information', text: expected_text) - expect(rendered).not_to have_css( - '.environment-information', text: 'latest deployment') - end - end - end - - context 'when job is running' do - before do - build.run! - render - end - - it 'does not show retry button' do - expect(rendered).not_to have_link('Retry') - end - - it 'does not show New issue button' do - expect(rendered).not_to have_link('New issue') - end - end - - context 'when job is not running' do - before do - build.success! - render - end - - it 'shows retry button' do - expect(rendered).to have_link('Retry') - end - - context 'if build passed' do - it 'does not show New issue button' do - expect(rendered).not_to have_link('New issue') - end - end - - context 'if build failed' do - before do - build.status = 'failed' - render - end - - it 'shows New issue button' do - expect(rendered).to have_link('New issue') - end - end - end - - describe 'commit title in sidebar' do - let(:commit_title) { project.commit.title } - - it 'shows commit title and not show commit message' do - render - - expect(rendered).to have_css('p.build-light-text.append-bottom-0', - text: /\A\n#{Regexp.escape(commit_title)}\n\Z/) - end - end - - describe 'shows trigger variables in sidebar' do - let(:trigger_request) { create(:ci_trigger_request_with_variables, pipeline: pipeline) } - - before do - build.trigger_request = trigger_request - render - end - - it 'shows trigger variables in separate lines' do - expect(rendered).to have_css('.js-build-variable', visible: false, text: 'TRIGGER_KEY_1') - expect(rendered).to have_css('.js-build-variable', visible: false, text: 'TRIGGER_KEY_2') - expect(rendered).to have_css('.js-build-value', visible: false, text: 'TRIGGER_VALUE_1') - expect(rendered).to have_css('.js-build-value', visible: false, text: 'TRIGGER_VALUE_2') - end - end - - describe 'New issue button' do - before do - build.status = 'failed' - render - end - - it 'links to issues/new with the title and description filled in' do - title = "Build Failed ##{build.id}" - build_url = namespace_project_build_url(project.namespace, project, build) - href = new_namespace_project_issue_path( - project.namespace, - project, - issue: { - title: title, - description: build_url - } - ) - expect(rendered).to have_link('New issue', href: href) - end - end -end diff --git a/spec/views/projects/jobs/_build.html.haml_spec.rb b/spec/views/projects/jobs/_build.html.haml_spec.rb new file mode 100644 index 00000000000..1d58891036e --- /dev/null +++ b/spec/views/projects/jobs/_build.html.haml_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe 'projects/ci/jobs/_build' do + include Devise::Test::ControllerHelpers + + let(:project) { create(:project, :repository) } + let(:pipeline) { create(:ci_empty_pipeline, id: 1337, project: project, sha: project.commit.id) } + let(:build) { create(:ci_build, pipeline: pipeline, stage: 'test', stage_idx: 1, name: 'rspec 0:2', status: :pending) } + + before do + controller.prepend_view_path('app/views/projects') + allow(view).to receive(:can?).and_return(true) + end + + it 'won\'t include a column with a link to its pipeline by default' do + render partial: 'projects/ci/builds/build', locals: { build: build } + + expect(rendered).not_to have_link('#1337') + expect(rendered).not_to have_text('#1337 by API') + end + + it 'can include a column with a link to its pipeline' do + render partial: 'projects/ci/builds/build', locals: { build: build, pipeline_link: true } + + expect(rendered).to have_link('#1337') + expect(rendered).to have_text('#1337 by API') + end +end diff --git a/spec/views/projects/jobs/_generic_commit_status.html.haml_spec.rb b/spec/views/projects/jobs/_generic_commit_status.html.haml_spec.rb new file mode 100644 index 00000000000..dc2ffc9dc47 --- /dev/null +++ b/spec/views/projects/jobs/_generic_commit_status.html.haml_spec.rb @@ -0,0 +1,28 @@ +require 'spec_helper' + +describe 'projects/generic_commit_statuses/_generic_commit_status.html.haml' do + include Devise::Test::ControllerHelpers + + let(:project) { create(:project, :repository) } + let(:pipeline) { create(:ci_empty_pipeline, id: 1337, project: project, sha: project.commit.id) } + let(:generic_commit_status) { create(:generic_commit_status, pipeline: pipeline, stage: 'external', name: 'jenkins', stage_idx: 3) } + + before do + controller.prepend_view_path('app/views/projects') + allow(view).to receive(:can?).and_return(true) + end + + it 'won\'t include a column with a link to its pipeline by default' do + render partial: 'projects/generic_commit_statuses/generic_commit_status', locals: { generic_commit_status: generic_commit_status } + + expect(rendered).not_to have_link('#1337') + expect(rendered).not_to have_text('#1337 by API') + end + + it 'can include a column with a link to its pipeline' do + render partial: 'projects/generic_commit_statuses/generic_commit_status', locals: { generic_commit_status: generic_commit_status, pipeline_link: true } + + expect(rendered).to have_link('#1337') + expect(rendered).to have_text('#1337 by API') + end +end diff --git a/spec/views/projects/jobs/show.html.haml_spec.rb b/spec/views/projects/jobs/show.html.haml_spec.rb new file mode 100644 index 00000000000..8f2822f5dc5 --- /dev/null +++ b/spec/views/projects/jobs/show.html.haml_spec.rb @@ -0,0 +1,293 @@ +require 'spec_helper' + +describe 'projects/jobs/show', :view do + let(:project) { create(:project, :repository) } + let(:build) { create(:ci_build, pipeline: pipeline) } + + let(:pipeline) do + create(:ci_pipeline, project: project, sha: project.commit.id) + end + + before do + assign(:build, build.present) + assign(:project, project) + + allow(view).to receive(:can?).and_return(true) + end + + describe 'job information in header' do + let(:build) do + create(:ci_build, :success, environment: 'staging') + end + + before do + render + end + + it 'shows status name' do + expect(rendered).to have_css('.ci-status.ci-success', text: 'passed') + end + + it 'does not render a link to the job' do + expect(rendered).not_to have_link('passed') + end + + it 'shows job id' do + expect(rendered).to have_css('.js-build-id', text: build.id) + end + + it 'shows a link to the pipeline' do + expect(rendered).to have_link(build.pipeline.id) + end + + it 'shows a link to the commit' do + expect(rendered).to have_link(build.pipeline.short_sha) + end + end + + describe 'environment info in job view' do + context 'job with latest deployment' do + let(:build) do + create(:ci_build, :success, environment: 'staging') + end + + before do + create(:environment, name: 'staging') + create(:deployment, deployable: build) + end + + it 'shows deployment message' do + expected_text = 'This job is the most recent deployment' + render + + expect(rendered).to have_css( + '.environment-information', text: expected_text) + end + end + + context 'job with outdated deployment' do + let(:build) do + create(:ci_build, :success, environment: 'staging', pipeline: pipeline) + end + + let(:second_build) do + create(:ci_build, :success, environment: 'staging', pipeline: pipeline) + end + + let(:environment) do + create(:environment, name: 'staging', project: project) + end + + let!(:first_deployment) do + create(:deployment, environment: environment, deployable: build) + end + + let!(:second_deployment) do + create(:deployment, environment: environment, deployable: second_build) + end + + it 'shows deployment message' do + expected_text = 'This job is an out-of-date deployment ' \ + "to staging.\nView the most recent deployment ##{second_deployment.iid}." + render + + expect(rendered).to have_css('.environment-information', text: expected_text) + end + end + + context 'job failed to deploy' do + let(:build) do + create(:ci_build, :failed, environment: 'staging', pipeline: pipeline) + end + + let!(:environment) do + create(:environment, name: 'staging', project: project) + end + + it 'shows deployment message' do + expected_text = 'The deployment of this job to staging did not succeed.' + render + + expect(rendered).to have_css( + '.environment-information', text: expected_text) + end + end + + context 'job will deploy' do + let(:build) do + create(:ci_build, :running, environment: 'staging', pipeline: pipeline) + end + + context 'when environment exists' do + let!(:environment) do + create(:environment, name: 'staging', project: project) + end + + it 'shows deployment message' do + expected_text = 'This job is creating a deployment to staging' + render + + expect(rendered).to have_css( + '.environment-information', text: expected_text) + end + + context 'when it has deployment' do + let!(:deployment) do + create(:deployment, environment: environment) + end + + it 'shows that deployment will be overwritten' do + expected_text = 'This job is creating a deployment to staging' + render + + expect(rendered).to have_css( + '.environment-information', text: expected_text) + expect(rendered).to have_css( + '.environment-information', text: 'latest deployment') + end + end + end + + context 'when environment does not exist' do + it 'shows deployment message' do + expected_text = 'This job is creating a deployment to staging' + render + + expect(rendered).to have_css( + '.environment-information', text: expected_text) + expect(rendered).not_to have_css( + '.environment-information', text: 'latest deployment') + end + end + end + + context 'job that failed to deploy and environment has not been created' do + let(:build) do + create(:ci_build, :failed, environment: 'staging', pipeline: pipeline) + end + + let!(:environment) do + create(:environment, name: 'staging', project: project) + end + + it 'shows deployment message' do + expected_text = 'The deployment of this job to staging did not succeed' + render + + expect(rendered).to have_css( + '.environment-information', text: expected_text) + end + end + + context 'job that will deploy and environment has not been created' do + let(:build) do + create(:ci_build, :running, environment: 'staging', pipeline: pipeline) + end + + let!(:environment) do + create(:environment, name: 'staging', project: project) + end + + it 'shows deployment message' do + expected_text = 'This job is creating a deployment to staging' + render + + expect(rendered).to have_css( + '.environment-information', text: expected_text) + expect(rendered).not_to have_css( + '.environment-information', text: 'latest deployment') + end + end + end + + context 'when job is running' do + before do + build.run! + render + end + + it 'does not show retry button' do + expect(rendered).not_to have_link('Retry') + end + + it 'does not show New issue button' do + expect(rendered).not_to have_link('New issue') + end + end + + context 'when job is not running' do + before do + build.success! + render + end + + it 'shows retry button' do + expect(rendered).to have_link('Retry') + end + + context 'if build passed' do + it 'does not show New issue button' do + expect(rendered).not_to have_link('New issue') + end + end + + context 'if build failed' do + before do + build.status = 'failed' + render + end + + it 'shows New issue button' do + expect(rendered).to have_link('New issue') + end + end + end + + describe 'commit title in sidebar' do + let(:commit_title) { project.commit.title } + + it 'shows commit title and not show commit message' do + render + + expect(rendered).to have_css('p.build-light-text.append-bottom-0', + text: /\A\n#{Regexp.escape(commit_title)}\n\Z/) + end + end + + describe 'shows trigger variables in sidebar' do + let(:trigger_request) { create(:ci_trigger_request_with_variables, pipeline: pipeline) } + + before do + build.trigger_request = trigger_request + render + end + + it 'shows trigger variables in separate lines' do + expect(rendered).to have_css('.js-build-variable', visible: false, text: 'TRIGGER_KEY_1') + expect(rendered).to have_css('.js-build-variable', visible: false, text: 'TRIGGER_KEY_2') + expect(rendered).to have_css('.js-build-value', visible: false, text: 'TRIGGER_VALUE_1') + expect(rendered).to have_css('.js-build-value', visible: false, text: 'TRIGGER_VALUE_2') + end + end + + describe 'New issue button' do + before do + build.status = 'failed' + render + end + + it 'links to issues/new with the title and description filled in' do + title = "Build Failed ##{build.id}" + build_url = namespace_project_job_url(project.namespace, project, build) + href = new_namespace_project_issue_path( + project.namespace, + project, + issue: { + title: title, + description: build_url + } + ) + expect(rendered).to have_link('New issue', href: href) + end + end +end -- cgit v1.2.1