Commit a957eca6 authored by Kamil Trzcinski's avatar Kamil Trzcinski

Added builds view

parent 2d0fcb4d
......@@ -17,6 +17,7 @@ v 8.1.0 (unreleased)
- Fix cases where Markdown did not render links in activity feed (Stan Hu)
- Add first and last to pagination (Zeger-Jan van de Weg)
- Added Commit Status API
- Added Builds View
- Show CI status on commit page
- Show CI status on Your projects page and Starred projects page
- Remove "Continuous Integration" page from dashboard
......
......@@ -7,6 +7,7 @@ class @ShortcutsNavigation extends Shortcuts
Mousetrap.bind('g e', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-project-activity'))
Mousetrap.bind('g f', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-tree'))
Mousetrap.bind('g c', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-commits'))
Mousetrap.bind('g b', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-builds'))
Mousetrap.bind('g n', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-network'))
Mousetrap.bind('g g', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-graphs'))
Mousetrap.bind('g i', -> ShortcutsNavigation.findAndFollowLink('.shortcuts-issues'))
......
class Projects::BuildsController < Projects::ApplicationController
before_action :ci_project
before_action :build
before_action :build, except: [:index, :cancel_all]
before_action :authorize_admin_project!, except: [:show, :status]
before_action :authorize_admin_project!, except: [:index, :show, :status]
layout "project"
def index
@scope = params[:scope]
@all_builds = project.ci_builds.order('created_at DESC').page(params[:page]).per(30)
@builds =
case @scope
when 'pending'
@all_builds.pending
when 'running'
@all_builds.running
else
@all_builds
end
end
def cancel_all
@project.ci_builds.running_or_pending.each(&:cancel)
redirect_to namespace_project_builds_path(project.namespace, project)
end
def show
@builds = @ci_project.commits.find_by_sha(@build.sha).builds.order('id DESC')
@builds = @builds.where("id not in (?)", @build.id).page(params[:page]).per(20)
......
......@@ -25,6 +25,10 @@ def project_commits_path(project, *args)
namespace_project_commits_path(project.namespace, project, @ref || project.repository.root_ref)
end
def project_builds_path(project, *args)
namespace_project_builds_path(project.namespace, project, *args)
end
def activity_project_path(project, *args)
activity_namespace_project_path(project.namespace, project, *args)
end
......
......@@ -113,6 +113,10 @@ def get_project_nav_tabs(project, current_user)
nav_tabs << :merge_requests
end
if can?(current_user, :read_build, project)
nav_tabs << :builds
end
if can?(current_user, :admin_project, project)
nav_tabs << :settings
end
......
......@@ -17,4 +17,17 @@ def runner_status_icon(runner)
class: "fa fa-circle runner-status-#{status}",
title: "Runner is #{status}, last contact was #{time_ago_in_words(runner.contacted_at)} ago"
end
def runner_link(runner)
display_name = truncate(runner.display_name, length: 20)
id = "\##{runner.id}"
if current_user && current_user.admin
link_to ci_admin_runner_path(runner) do
display_name + id
end
else
display_name + id
end
end
end
......@@ -41,6 +41,7 @@ def not_auth_abilities(user, subject)
:read_project_member,
:read_merge_request,
:read_note,
:read_build,
:download_code
]
......@@ -127,6 +128,7 @@ def project_guest_rules
:read_project_member,
:read_merge_request,
:read_note,
:read_build,
:create_project,
:create_issue,
:create_note
......
......@@ -56,7 +56,7 @@ def assign_to(project, current_user = nil)
end
def display_name
return token unless !description.blank?
return short_sha unless !description.blank?
description
end
......@@ -78,7 +78,7 @@ def only_for?(project)
end
def short_sha
token[0...10]
token[0...8]
end
end
end
......@@ -99,6 +99,12 @@
.key c
%td
Go to commits
%tr
%td.shortcut
.key g
.key b
%td
Go to builds
%tr
%td.shortcut
.key g
......
......@@ -32,12 +32,19 @@
Files
- if project_nav_tab? :commits
= nav_link(controller: %w(commit commits compare repositories tags branches builds)) do
= nav_link(controller: %w(commit commits compare repositories tags branches)) do
= link_to project_commits_path(@project), title: 'Commits', class: 'shortcuts-commits', data: {placement: 'right'} do
= icon('history fw')
%span
Commits
- if project_nav_tab? :builds
= nav_link(controller: %w(builds)) do
= link_to project_builds_path(@project), title: 'Builds', class: 'shortcuts-builds', data: {placement: 'right'} do
= icon('link fw')
%span
Builds
- if project_nav_tab? :network
= nav_link(controller: %w(network)) do
= link_to namespace_project_network_path(@project.namespace, @project, current_ref), title: 'Network', class: 'shortcuts-network', data: {placement: 'right'} do
......
......@@ -66,7 +66,7 @@
%span
CI Services
= nav_link path: 'events#index' do
= link_to ci_project_events_path(@project.gitlab_ci_project) do
= link_to ci_project_events_path(@project.ensure_gitlab_ci_project) do
= icon('book fw')
%span
CI Events
%tr.build
%td.status
= ci_status_with_icon(build.status)
%td.commit_status-link
- if build.target_url
= link_to build.target_url do
%strong Build ##{build.id}
- else
%strong Build ##{build.id}
%td
= link_to namespace_project_commit_path(@project.namespace, @project, build.sha) do
= build.short_sha
%td
= link_to namespace_project_commits_path(@project.namespace, @project, build.ref) do
= build.ref
%td
- if build.runner
= runner_link(build.runner)
- else
.light none
%td
= build.name
.pull-right
- if build.tags.any?
- build.tags.each do |tag|
%span.label.label-primary
= tag
- if build.try(:trigger_request)
%span.label.label-info triggered
- if build.try(:allow_failure)
%span.label.label-danger allowed to fail
%td.duration
- if build.duration
#{duration_in_words(build.finished_at, build.started_at)}
%td.timestamp
- if build.finished_at
%span #{time_ago_in_words build.finished_at} ago
%td
.pull-right
- if current_user && can?(current_user, :manage_builds, @project)
- if build.cancel_url
= link_to build.cancel_url, title: 'Cancel' do
%i.fa.fa-remove.cred
- page_title "Builds"
- header_title project_title(@project, "Builds", project_builds_path(@project))
%ul.center-top-menu
%li{class: ('active' if @scope.nil?)}
= link_to project_builds_path(@project) do
All builds
%span.badge.js-totalbuilds-count= @all_builds.size
%li{class: ('active' if @scope == 'pending')}
= link_to project_builds_path(@project, scope: :pending) do
Pending
%span.badge.js-pending-count= @all_builds.pending.size
%li{class: ('active' if @scope == 'running')}
= link_to project_builds_path(@project, scope: :running) do
Running
%span.badge.js-running-count= @all_builds.running.size
.gray-content-block
.oneline
List of all builds from this project
- if @ci_project && current_user && can?(current_user, :manage_builds, @project)
.pull-right
- if @all_builds.running_or_pending.any?
= link_to 'Cancel all', cancel_all_namespace_project_builds_path(@project.namespace, @project), data: { confirm: 'Are you sure?' }, method: :post, class: 'btn btn-danger'
%ul.content-list
- if @builds.blank?
%li
.nothing-here-block No builds to show
- else
%table.table.builds
%thead
%tr
%th Status
%th Build ID
%th Commit
%th Ref
%th Runner
%th Name
%th Duration
%th Finished at
%th
- @builds.each do |build|
= render 'projects/builds/build', build: build
= paginate @builds
......@@ -585,7 +585,11 @@
end
end
resources :builds, only: [:show] do
resources :builds, only: [:index, :show] do
collection do
post :cancel_all
end
member do
get :cancel
get :status
......
......@@ -9,6 +9,55 @@
@gl_project.team << [@user, :master]
end
describe "GET /:project/builds" do
context "All builds" do
before do
@build.success
visit namespace_project_builds_path(@gl_project.namespace, @gl_project)
end
it { expect(page).to have_content 'All builds' }
it { expect(page).to have_content @build.short_sha }
it { expect(page).to have_content @build.ref }
it { expect(page).to have_content @build.name }
it { expect(page).to_not have_content 'Cancel all' }
end
context "Pending scope" do
before do
@build.success
visit namespace_project_builds_path(@gl_project.namespace, @gl_project, scope: :pending)
end
it { expect(page).to have_content 'No builds to show' }
it { expect(page).to_not have_content 'Cancel all' }
end
context "Running scope" do
before do
@build.run!
visit namespace_project_builds_path(@gl_project.namespace, @gl_project, scope: :running)
end
it { expect(page).to have_content 'Running' }
it { expect(page).to have_content 'Cancel all' }
it { expect(page).to have_content @build.short_sha }
it { expect(page).to have_content @build.ref }
it { expect(page).to have_content @build.name }
end
end
describe "POST /:project/builds/:id/cancel_all" do
before do
@build.run!
visit cancel_namespace_project_build_path(@gl_project.namespace, @gl_project, @build)
end
it { expect(page).to have_content 'All builds' }
it { expect(page).to have_content 'canceled' }
it { expect(page).to_not have_content 'Cancel all' }
end
describe "GET /:project/builds/:id" do
before do
visit namespace_project_build_path(@gl_project.namespace, @gl_project, @build)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment