Commit afda4835 authored by Robert Speicher's avatar Robert Speicher

Merge branch 'master' into 8-4-stable

parents 894cb7df d04eadf8
...@@ -17,8 +17,10 @@ v 8.4.0 (unreleased) ...@@ -17,8 +17,10 @@ v 8.4.0 (unreleased)
- Expire view caches when application settings change (e.g. Gravatar disabled) (Stan Hu) - Expire view caches when application settings change (e.g. Gravatar disabled) (Stan Hu)
- Don't notify users twice if they are both project watchers and subscribers (Stan Hu) - Don't notify users twice if they are both project watchers and subscribers (Stan Hu)
- Remove gray background from layout in UI - Remove gray background from layout in UI
- Fix signup for OAuth providers that don't provide a name
- Implement new UI for group page - Implement new UI for group page
- Implement search inside emoji picker - Implement search inside emoji picker
- Let the CI runner know about builds that this build depends on
- Add API support for looking up a user by username (Stan Hu) - Add API support for looking up a user by username (Stan Hu)
- Add project permissions to all project API endpoints (Stan Hu) - Add project permissions to all project API endpoints (Stan Hu)
- Link to milestone in "Milestone changed" system note - Link to milestone in "Milestone changed" system note
...@@ -54,6 +56,7 @@ v 8.4.0 (unreleased) ...@@ -54,6 +56,7 @@ v 8.4.0 (unreleased)
- Allow broadcast messages to be edited - Allow broadcast messages to be edited
- Autosize Markdown textareas - Autosize Markdown textareas
- Import GitHub wiki into GitLab - Import GitHub wiki into GitLab
- Add reporters ability to download and browse build artifacts (Andrew Johnson)
v 8.3.4 v 8.3.4
- Use gitlab-workhorse 0.5.4 (fixes API routing bug) - Use gitlab-workhorse 0.5.4 (fixes API routing bug)
......
...@@ -2,6 +2,6 @@ ...@@ -2,6 +2,6 @@
# https://gitlab.com/gitlab-org/omnibus-gitlab or the init scripts in # https://gitlab.com/gitlab-org/omnibus-gitlab or the init scripts in
# lib/support/init.d, which call scripts in bin/ . # lib/support/init.d, which call scripts in bin/ .
# #
web: bundle exec unicorn_rails -p ${PORT:="3000"} -E ${RAILS_ENV:="development"} -c ${UNICORN_CONFIG:="config/unicorn.rb"} web: RAILS_ENV=development bin/web start_foreground
worker: bundle exec sidekiq -q post_receive -q mailers -q archive_repo -q system_hook -q project_web_hook -q gitlab_shell -q incoming_email -q runner -q common -q default worker: RAILS_ENV=development bin/background_jobs start_foreground
# mail_room: bundle exec mail_room -q -c config/mail_room.yml # mail_room: bundle exec mail_room -q -c config/mail_room.yml
...@@ -355,7 +355,7 @@ class @Notes ...@@ -355,7 +355,7 @@ class @Notes
$('.note[id="' + note_id + '"]').each -> $('.note[id="' + note_id + '"]').each ->
note = $(this) note = $(this)
notes = note.closest(".notes") notes = note.closest(".notes")
count = notes.closest(".notes_holder").find(".discussion-notes-count") count = notes.closest(".issuable-details").find(".notes-tab .badge")
# check if this is the last note for this line # check if this is the last note for this line
if notes.find(".note").length is 1 if notes.find(".note").length is 1
...@@ -365,9 +365,10 @@ class @Notes ...@@ -365,9 +365,10 @@ class @Notes
# for diff lines # for diff lines
notes.closest("tr").remove() notes.closest("tr").remove()
else
# update notes count # update notes count
count.get(0).lastChild.nodeValue = " #{notes.children().length - 1}" oldNum = parseInt(count.text())
count.text(oldNum - 1)
note.remove() note.remove()
......
...@@ -75,6 +75,8 @@ hr { ...@@ -75,6 +75,8 @@ hr {
@include str-truncated; @include str-truncated;
} }
.item-title { font-weight: 600; }
/** FLASH message **/ /** FLASH message **/
.author_link { .author_link {
color: $gl-link-color; color: $gl-link-color;
......
...@@ -2,10 +2,6 @@ ...@@ -2,10 +2,6 @@
display: block; display: block;
} }
.commit-row-title .commit-title {
font-weight: 600;
}
.commit-author, .commit-committer{ .commit-author, .commit-committer{
display: block; display: block;
color: #999; color: #999;
......
...@@ -11,8 +11,3 @@ ...@@ -11,8 +11,3 @@
height: 42px; height: 42px;
} }
} }
.content-list .group-name {
font-weight: 600;
color: #4c4e54;
}
...@@ -115,7 +115,7 @@ class ApplicationController < ActionController::Base ...@@ -115,7 +115,7 @@ class ApplicationController < ActionController::Base
# localhost/group/project # localhost/group/project
# #
if id =~ /\.git\Z/ if id =~ /\.git\Z/
redirect_to request.original_url.gsub(/\.git\Z/, '') and return redirect_to request.original_url.gsub(/\.git\/?\Z/, '') and return
end end
project_path = "#{namespace}/#{id}" project_path = "#{namespace}/#{id}"
......
...@@ -8,7 +8,7 @@ class Projects::ArtifactsController < Projects::ApplicationController ...@@ -8,7 +8,7 @@ class Projects::ArtifactsController < Projects::ApplicationController
end end
unless artifacts_file.exists? unless artifacts_file.exists?
return not_found! return render_404
end end
send_file artifacts_file.path, disposition: 'attachment' send_file artifacts_file.path, disposition: 'attachment'
......
...@@ -42,7 +42,7 @@ class Projects::BuildsController < Projects::ApplicationController ...@@ -42,7 +42,7 @@ class Projects::BuildsController < Projects::ApplicationController
def retry def retry
unless @build.retryable? unless @build.retryable?
return page_404 return render_404
end end
build = Ci::Build.retry(@build) build = Ci::Build.retry(@build)
...@@ -72,7 +72,7 @@ class Projects::BuildsController < Projects::ApplicationController ...@@ -72,7 +72,7 @@ class Projects::BuildsController < Projects::ApplicationController
def authorize_manage_builds! def authorize_manage_builds!
unless can?(current_user, :manage_builds, project) unless can?(current_user, :manage_builds, project)
return page_404 return render_404
end end
end end
end end
...@@ -79,7 +79,7 @@ class Projects::CommitController < Projects::ApplicationController ...@@ -79,7 +79,7 @@ class Projects::CommitController < Projects::ApplicationController
def authorize_manage_builds! def authorize_manage_builds!
unless can?(current_user, :manage_builds, project) unless can?(current_user, :manage_builds, project)
return page_404 return render_404
end end
end end
end end
...@@ -160,6 +160,7 @@ class Ability ...@@ -160,6 +160,7 @@ class Ability
@project_report_rules ||= project_guest_rules + [ @project_report_rules ||= project_guest_rules + [
:create_commit_status, :create_commit_status,
:read_commit_statuses, :read_commit_statuses,
:read_build_artifacts,
:download_code, :download_code,
:fork_project, :fork_project,
:create_project_snippet, :create_project_snippet,
...@@ -175,7 +176,6 @@ class Ability ...@@ -175,7 +176,6 @@ class Ability
:create_merge_request, :create_merge_request,
:create_wiki, :create_wiki,
:manage_builds, :manage_builds,
:read_build_artifacts,
:push_code :push_code
] ]
end end
......
...@@ -128,6 +128,14 @@ module Ci ...@@ -128,6 +128,14 @@ module Ci
!self.commit.latest_builds_for_ref(self.ref).include?(self) !self.commit.latest_builds_for_ref(self.ref).include?(self)
end end
def depends_on_builds
# Get builds of the same type
latest_builds = self.commit.builds.similar(self).latest
# Return builds from previous stages
latest_builds.where('stage_idx < ?', stage_idx)
end
def trace_html def trace_html
html = Ci::Ansi2html::convert(trace) if trace.present? html = Ci::Ansi2html::convert(trace) if trace.present?
html || '' html || ''
......
...@@ -32,6 +32,10 @@ class ArtifactUploader < CarrierWave::Uploader::Base ...@@ -32,6 +32,10 @@ class ArtifactUploader < CarrierWave::Uploader::Base
self.class.storage == CarrierWave::Storage::File self.class.storage == CarrierWave::Storage::File
end end
def filename
file.try(:filename)
end
def exists? def exists?
file.try(:exists?) file.try(:exists?)
end end
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
%li(class="js-branch-#{branch.name}") %li(class="js-branch-#{branch.name}")
%div %div
= link_to namespace_project_tree_path(@project.namespace, @project, branch.name) do = link_to namespace_project_tree_path(@project.namespace, @project, branch.name) do
.branch-name.str-truncated= branch.name %span.item-title.str-truncated= branch.name
&nbsp; &nbsp;
- if branch.name == @repository.root_ref - if branch.name == @repository.root_ref
%span.label.label-primary default %span.label.label-primary default
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
= cache(cache_key) do = cache(cache_key) do
%li.commit.js-toggle-container{ id: "commit-#{commit.short_id}" } %li.commit.js-toggle-container{ id: "commit-#{commit.short_id}" }
.commit-row-title .commit-row-title
.commit-title.str-truncated %span.item-title.str-truncated
= link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit.id), class: "commit-row-message" = link_to_gfm commit.title, namespace_project_commit_path(project.namespace, project, commit.id), class: "commit-row-message"
- if commit.description? - if commit.description?
%a.text-expander.js-toggle-button ... %a.text-expander.js-toggle-button ...
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
%li %li
%div %div
= link_to namespace_project_tag_path(@project.namespace, @project, tag.name) do = link_to namespace_project_tag_path(@project.namespace, @project, tag.name) do
.tag-name %span.item-title
= icon('tag') = icon('tag')
= tag.name = tag.name
- if tag.message.present? - if tag.message.present?
......
...@@ -17,8 +17,8 @@ ...@@ -17,8 +17,8 @@
.pull-right .pull-right
= link_to namespace_project_tag_path(@project.namespace, @project, @tag.name), class: 'btn btn-remove remove-row grouped has_tooltip', title: "Delete tag", method: :delete, data: { confirm: "Deleting the '#{@tag.name}' tag cannot be undone. Are you sure?" } do = link_to namespace_project_tag_path(@project.namespace, @project, @tag.name), class: 'btn btn-remove remove-row grouped has_tooltip', title: "Delete tag", method: :delete, data: { confirm: "Deleting the '#{@tag.name}' tag cannot be undone. Are you sure?" } do
%i.fa.fa-trash-o %i.fa.fa-trash-o
.tag-name.title .title
= @tag.name %span.item-title= @tag.name
- if @tag.message.present? - if @tag.message.present?
%span.light %span.light
&nbsp; &nbsp;
......
...@@ -10,7 +10,8 @@ ...@@ -10,7 +10,8 @@
%i.fa.fa-sign-out %i.fa.fa-sign-out
= image_tag group_icon(group), class: "avatar s46 hidden-xs" = image_tag group_icon(group), class: "avatar s46 hidden-xs"
= link_to group.name, group, class: 'group-name' = link_to group, class: 'group-name' do
%span.item-title= group.name
- if group_member - if group_member
as as
...@@ -18,4 +19,3 @@ ...@@ -18,4 +19,3 @@
%div.light %div.light
#{pluralize(group.projects.count, "project")}, #{pluralize(group.users.count, "user")} #{pluralize(group.projects.count, "project")}, #{pluralize(group.users.count, "user")}
...@@ -27,17 +27,17 @@ restart() ...@@ -27,17 +27,17 @@ restart()
stop stop
fi fi
killall killall
start_sidekiq -d -L $sidekiq_logfile start_sidekiq -d -L $sidekiq_logfile >> $sidekiq_logfile 2>&1
} }
start_no_deamonize() start_no_deamonize()
{ {
start_sidekiq start_sidekiq >> $sidekiq_logfile 2>&1
} }
start_sidekiq() start_sidekiq()
{ {
bundle exec sidekiq -q post_receive -q mailers -q archive_repo -q system_hook -q project_web_hook -q gitlab_shell -q incoming_email -q runner -q common -q default -e $RAILS_ENV -P $sidekiq_pidfile $@ >> $sidekiq_logfile 2>&1 bundle exec sidekiq -q post_receive -q mailers -q archive_repo -q system_hook -q project_web_hook -q gitlab_shell -q incoming_email -q runner -q common -q default -e $RAILS_ENV -P $sidekiq_pidfile "$@"
} }
load_ok() load_ok()
...@@ -66,6 +66,9 @@ case "$1" in ...@@ -66,6 +66,9 @@ case "$1" in
start_no_deamonize) start_no_deamonize)
start_no_deamonize start_no_deamonize
;; ;;
start_foreground)
start_sidekiq
;;
restart) restart)
restart restart
;; ;;
......
...@@ -5,6 +5,7 @@ app_root=$(pwd) ...@@ -5,6 +5,7 @@ app_root=$(pwd)
unicorn_pidfile="$app_root/tmp/pids/unicorn.pid" unicorn_pidfile="$app_root/tmp/pids/unicorn.pid"
unicorn_config="$app_root/config/unicorn.rb" unicorn_config="$app_root/config/unicorn.rb"
unicorn_cmd="bundle exec unicorn_rails -c $unicorn_config -E $RAILS_ENV"
get_unicorn_pid() get_unicorn_pid()
{ {
...@@ -18,7 +19,12 @@ get_unicorn_pid() ...@@ -18,7 +19,12 @@ get_unicorn_pid()
start() start()
{ {
bundle exec unicorn_rails -D -c $unicorn_config -E $RAILS_ENV $unicorn_cmd -D
}
start_foreground()
{
$unicorn_cmd
} }
stop() stop()
...@@ -37,6 +43,9 @@ case "$1" in ...@@ -37,6 +43,9 @@ case "$1" in
start) start)
start start
;; ;;
start_foreground)
start_foreground
;;
stop) stop)
stop stop
;; ;;
......
...@@ -34,6 +34,8 @@ Rails.application.configure do ...@@ -34,6 +34,8 @@ Rails.application.configure do
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
# Open sent mails in browser # Open sent mails in browser
config.action_mailer.delivery_method = :letter_opener config.action_mailer.delivery_method = :letter_opener
# Don't make a mess when bootstrapping a development environment
config.action_mailer.perform_deliveries = (ENV['BOOTSTRAP'] != '1')
config.eager_load = false config.eager_load = false
end end
...@@ -18,18 +18,62 @@ Returns: ...@@ -18,18 +18,62 @@ Returns:
```json ```json
{ {
"id" : 79, "id": 48584,
"commands" : "", "ref": "0.1.1",
"path" : "", "tag": true,
"ref" : "", "sha": "d63117656af6ff57d99e50cc270f854691f335ad",
"sha" : "", "status": "success",
"project_id" : 6, "name": "pages",
"repo_url" : "git@demo.gitlab.com:gitlab/gitlab-shell.git", "token": "9dd60b4f1a439d1765357446c1084c",
"before_sha" : "" "stage": "test",
"project_id": 479,
"project_name": "test",
"commands": "echo commands",
"repo_url": "http://gitlab-ci-token:token@gitlab.example/group/test.git",
"before_sha": "0000000000000000000000000000000000000000",
"allow_git_fetch": false,
"options": {
"image": "docker:image",
"artifacts": {
"paths": [
"public"
]
},
"cache": {
"paths": [
"vendor"
]
}
},
"timeout": 3600,
"variables": [
{
"key": "CI_BUILD_TAG",
"value": "0.1.1",
"public": true
}
],
"depends_on_builds": [
{
"id": 48584,
"ref": "0.1.1",
"tag": true,
"sha": "d63117656af6ff57d99e50cc270f854691f335ad",
"status": "success",
"name": "build",
"token": "9dd60b4f1a439d1765357446c1084c",
"stage": "build",
"project_id": 479,
"project_name": "test",
"artifacts_file": {
"filename": "artifacts.zip",
"size": 0
}
}
]
} }
``` ```
### Update details of an existing build ### Update details of an existing build
PUT /ci/builds/:id PUT /ci/builds/:id
......
# Import your project from GitHub to GitLab # Import your project from GitHub to GitLab
It takes just a couple of steps to import your existing GitHub projects to GitLab. Keep in mind that it is possible only if _**Note:** In order to enable the GitHub import setting, you should first
GitHub support is enabled on your GitLab instance. You can read more about GitHub support [here](http://doc.gitlab.com/ce/integration/github.html) enable the [GitHub integration][gh-import] in your GitLab instance._
If you want to import from a GitHub Enterprise instance, you need to use GitLab Enterprise; please see the [EE docs for the GitHub integration](http://doc.gitlab.com/ee/integration/github.html). At its current state, GitHub importer can import:
* Sign in to GitLab.com and go to your dashboard. - the repository description
* To get to the importer page, you need to go to the "New project" page. - the git repository data
- the issues
- the pull requests
- the wiki pages
![New project page](github_importer/new_project_page.png) The importer page is visible when you [create a new project][new-project].
Click on the **GitHub** link and you will be redirected to GitHub for
permission to access your projects. After accepting, you'll be automatically
redirected to the importer.
* Click on the "Import project from GitHub" link and you will be redirected to GitHub for permission to access your projects. After accepting, you'll be automatically redirected to the importer. ![New project page on GitLab](img/import_projects_from_github_new_project_page.png)
![Importer page](github_importer/importer.png) ---
* To import a project, you can simple click "Add". The importer will import your repository, issues, and pull requests. Once the importer is done, a new GitLab project will be created with your imported data. While at the GitHub importer page, you can see the import statuses of your
GitHub projects. Those that are being imported will show a _started_ status,
those already imported will be green, whereas those that are not yet imported
have an **Import** button on the right side of the table. If you want, you can
import all your GitHub projects in one go by hitting **Import all projects**
in the upper left corner.
![GitHub importer page](img/import_projects_from_github_importer.png)
---
The importer will create any new namespaces if they don't exist or in the
case the namespace is taken, the project will be imported on the user's
namespace.
### Note ### Note
When you import your projects from GitHub, it is not possible to keep your labels, milestones, and cross-repository pull requests. We are working on improving this in the near future.
When you import your projects from GitHub, it is not possible to keep your
labels, milestones, and cross-repository pull requests. We are working on
improving this in the near future.
[gh-import]: ../../integration/github.md "GitHub integration"
[ee-gh]: http://doc.gitlab.com/ee/integration/github.html "GitHub integration for GitLab EE"
[new-project]: ../../gitlab-basics/create-project.md "How to create a new project in GitLab"
Feature: Project Builds Feature: Project Builds Artifacts
Background: Background:
Given I sign in as a user Given I sign in as a user
And I own a project And I own a project
And CI is enabled And project has CI enabled
And I have recent build for my project And project has a recent build
Scenario: I browse build summary page
When I visit recent build summary page
Then I see summary for build
And I see build trace
Scenario: I download build artifacts Scenario: I download build artifacts
Given recent build has artifacts available Given recent build has artifacts available
......
Feature: Project Builds Permissions
Background:
Given I sign in as a user
And project exists in some group namespace
And project has CI enabled
And project has a recent build
Scenario: I try to download build artifacts as guest
Given I am member of a project with a guest role
And recent build has artifacts available
When I access artifacts download page
Then page status code should be 404
Scenario: I try to download build artifacts as reporter
Given I am member of a project with a reporter role
And recent build has artifacts available
When I access artifacts download page
Then download of build artifacts archive starts
Feature: Project Builds Summary
Background:
Given I sign in as a user
And I own a project
And project has CI enabled
And project has a recent build
Scenario: I browse build summary page
When I visit recent build summary page
Then I see summary for build
And I see build trace
class Spinach::Features::ProjectBuilds < Spinach::FeatureSteps class Spinach::Features::ProjectBuildsArtifacts < Spinach::FeatureSteps
include SharedAuthentication include SharedAuthentication
include SharedProject include SharedProject
include SharedBuilds include SharedBuilds
include RepoHelpers include RepoHelpers
step 'I see summary for build' do
expect(page).to have_content "Build ##{@build.id}"
end
step 'I see build trace' do
expect(page).to have_css '#build-trace'
end
step 'I click artifacts download button' do step 'I click artifacts download button' do
page.within('.artifacts') { click_link 'Download' } page.within('.artifacts') { click_link 'Download' }
end end
step 'download of build artifacts archive starts' do
expect(page.response_headers['Content-Type']).to eq 'application/zip'
expect(page.response_headers['Content-Transfer-Encoding']).to eq 'binary'
end
step 'I click artifacts browse button' do step 'I click artifacts browse button' do
page.within('.artifacts') { click_link 'Browse' } page.within('.artifacts') { click_link 'Browse' }
end end
......
class Spinach::Features::ProjectBuildsPermissions < Spinach::FeatureSteps
include SharedAuthentication
include SharedProject
include SharedBuilds
include SharedPaths
include RepoHelpers
end
class Spinach::Features::ProjectBuildsSummary < Spinach::FeatureSteps
include SharedAuthentication
include SharedProject
include SharedBuilds
include RepoHelpers
step 'I see summary for build' do
expect(page).to have_content "Build ##{@build.id}"
end
step 'I see build trace' do
expect(page).to have_css '#build-trace'
end
end
module SharedBuilds module SharedBuilds
include Spinach::DSL include Spinach::DSL
step 'CI is enabled' do step 'project has CI enabled' do
@project.enable_ci @project.enable_ci
end end
step 'I have recent build for my project' do step 'project has a recent build' do
ci_commit = create :ci_commit, project: @project, sha: sample_commit.id ci_commit = create :ci_commit, project: @project, sha: sample_commit.id
@build = create :ci_build, commit: ci_commit @build = create :ci_build, commit: ci_commit
end end
...@@ -25,4 +25,13 @@ module SharedBuilds ...@@ -25,4 +25,13 @@ module SharedBuilds
gzip = fixture_file_upload(metadata, 'application/x-gzip') gzip = fixture_file_upload(metadata, 'application/x-gzip')
@build.update_attributes(artifacts_metadata: gzip) @build.update_attributes(artifacts_metadata: gzip)
end end
step 'download of build artifacts archive starts' do
expect(page.response_headers['Content-Type']).to eq 'application/zip'
expect(page.response_headers['Content-Transfer-Encoding']).to eq 'binary'
end
step 'I access artifacts download page' do
visit download_namespace_project_build_artifacts_path(@project.namespace, @project, @build)
end
end end
...@@ -7,6 +7,11 @@ module SharedProject ...@@ -7,6 +7,11 @@ module SharedProject
@project.team << [@user, :master] @project.team << [@user, :master]
end end
step "project exists in some group namespace" do
@group = create(:group, name: 'some group')
@project = create(:project, namespace: @group)
end
# Create a specific project called "Shop" # Create a specific project called "Shop"
step 'I own project "Shop"' do step 'I own project "Shop"' do
@project = Project.find_by(name: "Shop") @project = Project.find_by(name: "Shop")
...@@ -97,6 +102,18 @@ module SharedProject ...@@ -97,6 +102,18 @@ module SharedProject
@project ||= Project.first @project ||= Project.first
end end
# ----------------------------------------
# Project permissions
# ----------------------------------------
step 'I am member of a project with a guest role' do
@project.team << [@user, Gitlab::Access::GUEST]
end
step 'I am member of a project with a reporter role' do
@project.team << [@user, Gitlab::Access::REPORTER]
end
# ---------------------------------------- # ----------------------------------------
# Visibility of archived project # Visibility of archived project
# ---------------------------------------- # ----------------------------------------
...@@ -229,5 +246,4 @@ module SharedProject ...@@ -229,5 +246,4 @@ module SharedProject
project ||= create(:empty_project, visibility, name: project_name, namespace: user.namespace) project ||= create(:empty_project, visibility, name: project_name, namespace: user.namespace)
project.team << [user, :master] project.team << [user, :master]
end end
end end
...@@ -20,7 +20,7 @@ module Ci ...@@ -20,7 +20,7 @@ module Ci
if build if build
update_runner_info update_runner_info
present build, with: Entities::Build present build, with: Entities::BuildDetails
else else
not_found! not_found!
end end
...@@ -111,7 +111,7 @@ module Ci ...@@ -111,7 +111,7 @@ module Ci
build.artifacts_metadata = metadata build.artifacts_metadata = metadata
if build.save if build.save
present(build, with: Entities::Build) present(build, with: Entities::BuildDetails)
else else
render_validation_error!(build) render_validation_error!(build)
end end
......
...@@ -16,10 +16,19 @@ module Ci ...@@ -16,10 +16,19 @@ module Ci
end end
class Build < Grape::Entity class Build < Grape::Entity
expose :id, :commands, :ref, :sha, :status, :project_id, :repo_url, expose :id, :ref, :tag, :sha, :status
:before_sha, :allow_git_fetch, :project_name
expose :name, :token, :stage expose :name, :token, :stage
expose :project_id
expose :project_name
expose :artifacts_file, using: ArtifactFile, if: lambda { |build, opts| build.artifacts? }
end
class BuildDetails < Build
expose :commands
expose :repo_url
expose :before_sha
expose :allow_git_fetch
expose :token
expose :options do |model| expose :options do |model|
model.options model.options
...@@ -30,7 +39,7 @@ module Ci ...@@ -30,7 +39,7 @@ module Ci
end end
expose :variables expose :variables
expose :artifacts_file, using: ArtifactFile expose :depends_on_builds, using: Build
end end
class Runner < Grape::Entity class Runner < Grape::Entity
......
...@@ -142,8 +142,11 @@ module Gitlab ...@@ -142,8 +142,11 @@ module Gitlab
email = auth_hash.email email = auth_hash.email
end end
name = auth_hash.name
name = ::Namespace.clean_path(username) if name.strip.empty?
{ {
name: auth_hash.name, name: name,
username: ::Namespace.clean_path(username), username: ::Namespace.clean_path(username),
email: email, email: email,
password: auth_hash.password, password: auth_hash.password,
......
...@@ -426,6 +426,30 @@ describe Ci::Build, models: true do ...@@ -426,6 +426,30 @@ describe Ci::Build, models: true do
it { is_expected.to include(project.web_url[7..-1]) } it { is_expected.to include(project.web_url[7..-1]) }
end end
describe :depends_on_builds do
let!(:build) { FactoryGirl.create :ci_build, commit: commit, name: 'build', stage_idx: 0, stage: 'build' }
let!(:rspec_test) { FactoryGirl.create :ci_build, commit: commit, name: 'rspec', stage_idx: 1, stage: 'test' }
let!(:rubocop_test) { FactoryGirl.create :ci_build, commit: commit, name: 'rubocop', stage_idx: 1, stage: 'test' }
let!(:staging) { FactoryGirl.create :ci_build, commit: commit, name: 'staging', stage_idx: 2, stage: 'deploy' }
it 'to have no dependents if this is first build' do
expect(build.depends_on_builds).to be_empty
end
it 'to have one dependent if this is test' do
expect(rspec_test.depends_on_builds.map(&:id)).to contain_exactly(build.id)
end
it 'to have all builds from build and test stage if this is last' do
expect(staging.depends_on_builds.map(&:id)).to contain_exactly(build.id, rspec_test.id, rubocop_test.id)
end
it 'to have retried builds instead the original ones' do
retried_rspec = Ci::Build.retry(rspec_test)
expect(staging.depends_on_builds.map(&:id)).to contain_exactly(build.id, retried_rspec.id, rubocop_test.id)
end
end
def create_mr(build, commit, factory: :merge_request, created_at: Time.now) def create_mr(build, commit, factory: :merge_request, created_at: Time.now)
FactoryGirl.create(factory, FactoryGirl.create(factory,
source_project_id: commit.gl_project_id, source_project_id: commit.gl_project_id,
......
...@@ -101,6 +101,18 @@ describe Ci::API::API do ...@@ -101,6 +101,18 @@ describe Ci::API::API do
{ "key" => "TRIGGER_KEY", "value" => "TRIGGER_VALUE", "public" => false }, { "key" => "TRIGGER_KEY", "value" => "TRIGGER_VALUE", "public" => false },
]) ])
end end
it "returns dependent builds" do
commit = FactoryGirl.create(:ci_commit, project: project)
commit.create_builds('master', false, nil, nil)
commit.builds.where(stage: 'test').each(&:success)
post ci_api("/builds/register"), token: runner.token, info: { platform: :darwin }
expect(response.status).to eq(201)
expect(json_response["depends_on_builds"].count).to eq(2)
expect(json_response["depends_on_builds"][0]["name"]).to eq("rspec")
end
end end
describe "PUT /builds/:id" do describe "PUT /builds/:id" do
......
...@@ -36,8 +36,8 @@ staging: ...@@ -36,8 +36,8 @@ staging:
script: "cap deploy stating" script: "cap deploy stating"
type: deploy type: deploy
tags: tags:
- capistrano - ruby
- debian - mysql
except: except:
- stable - stable
...@@ -47,8 +47,8 @@ production: ...@@ -47,8 +47,8 @@ production:
- cap deploy production - cap deploy production
- cap notify - cap notify
tags: tags:
- capistrano - ruby
- debian - mysql
only: only:
- master - master
- /^deploy-.*$/ - /^deploy-.*$/
......
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