Commit afde800b authored by James Lopez's avatar James Lopez

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce into fix/unexistent-group-500

parents 5eb936dc 5e0ee54c
...@@ -9,6 +9,21 @@ v 8.5.0 (unreleased) ...@@ -9,6 +9,21 @@ v 8.5.0 (unreleased)
- Whitelist raw "abbr" elements when parsing Markdown (Benedict Etzel) - Whitelist raw "abbr" elements when parsing Markdown (Benedict Etzel)
- Don't vendor minified JS - Don't vendor minified JS
- Display 404 error on group not found - Display 404 error on group not found
- Track project import failure
- Fix visibility level text in admin area (Zeger-Jan van de Weg)
- Update the ExternalIssue regex pattern (Blake Hitchcock)
v 8.4.2 (unreleased)
- Bump required gitlab-workhorse version to bring in a fix for missing
artifacts in the build artifacts browser
- Get rid of those ugly borders on the file tree view
- Bump gitlab_git version to 7.2.24 in order to bring in a performance
improvement when checking if a repository was empty
- Add instrumentation for Gitlab::Git::Repository instance methods so we can
track them in Performance Monitoring.
v 8.4.2 (unreleased)
- Fix method undefined when using external commit status in builds
v 8.4.1 v 8.4.1
- Apply security updates for Rails (4.2.5.1), rails-html-sanitizer (1.0.3), - Apply security updates for Rails (4.2.5.1), rails-html-sanitizer (1.0.3),
......
...@@ -5,11 +5,11 @@ class @ShortcutsIssuable extends ShortcutsNavigation ...@@ -5,11 +5,11 @@ class @ShortcutsIssuable extends ShortcutsNavigation
constructor: (isMergeRequest) -> constructor: (isMergeRequest) ->
super() super()
Mousetrap.bind('a', -> Mousetrap.bind('a', ->
$('.js-assignee').select2('open') $('.block.assignee .edit-link').trigger('click')
return false return false
) )
Mousetrap.bind('m', -> Mousetrap.bind('m', ->
$('.js-milestone').select2('open') $('.block.milestone .edit-link').trigger('click')
return false return false
) )
Mousetrap.bind('r', => Mousetrap.bind('r', =>
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
border: 1px solid $border-color; border: 1px solid $border-color;
&.readme-holder { &.readme-holder {
margin-top: 10px;
border-bottom: 0; border-bottom: 0;
} }
......
...@@ -38,7 +38,7 @@ table { ...@@ -38,7 +38,7 @@ table {
td { td {
border-color: $table-border-color; border-color: $table-border-color;
border-bottom: 1px solid; border-bottom: 1px solid $border-color;
} }
} }
} }
......
.member-search-form { .member-search-form {
float: left; float: left;
input[type='search'] {
width: 225px;
vertical-align: bottom;
@media (max-width: $screen-xs-max) {
width: 100px;
vertical-align: bottom;
}
}
} }
.milestone-row { .milestone-row {
......
...@@ -22,8 +22,6 @@ ...@@ -22,8 +22,6 @@
&:hover { &:hover {
td { td {
background: $hover; background: $hover;
border-top: 1px solid #ADF;
border-bottom: 1px solid #ADF;
} }
cursor: pointer; cursor: pointer;
} }
......
...@@ -2,17 +2,18 @@ class GroupsController < Groups::ApplicationController ...@@ -2,17 +2,18 @@ class GroupsController < Groups::ApplicationController
include IssuesAction include IssuesAction
include MergeRequestsAction include MergeRequestsAction
skip_before_action :authenticate_user!, only: [:show, :issues, :merge_requests]
respond_to :html respond_to :html
before_action :group, except: [:new, :create]
skip_before_action :authenticate_user!, only: [:index, :show, :issues, :merge_requests]
before_action :group, except: [:index, :new, :create]
# Authorize # Authorize
before_action :authorize_read_group!, except: [:show, :new, :create, :autocomplete] before_action :authorize_read_group!, except: [:index, :show, :new, :create, :autocomplete]
before_action :authorize_admin_group!, only: [:edit, :update, :destroy, :projects] before_action :authorize_admin_group!, only: [:edit, :update, :destroy, :projects]
before_action :authorize_create_group!, only: [:new, :create] before_action :authorize_create_group!, only: [:new, :create]
# Load group projects # Load group projects
before_action :load_projects, except: [:new, :create, :projects, :edit, :update, :autocomplete] before_action :load_projects, except: [:index, :new, :create, :projects, :edit, :update, :autocomplete]
before_action :event_filter, only: :show before_action :event_filter, only: :show
layout :determine_layout layout :determine_layout
......
...@@ -83,7 +83,11 @@ module LabelsHelper ...@@ -83,7 +83,11 @@ module LabelsHelper
end end
def text_color_for_bg(bg_color) def text_color_for_bg(bg_color)
r, g, b = bg_color.slice(1,7).scan(/.{2}/).map(&:hex) if bg_color.length == 4
r, g, b = bg_color[1, 4].scan(/./).map { |v| (v * 2).hex }
else
r, g, b = bg_color[1, 7].scan(/.{2}/).map(&:hex)
end
if (r + g + b) > 500 if (r + g + b) > 500
'#333333' '#333333'
......
...@@ -31,7 +31,7 @@ class ExternalIssue ...@@ -31,7 +31,7 @@ class ExternalIssue
# Pattern used to extract `JIRA-123` issue references from text # Pattern used to extract `JIRA-123` issue references from text
def self.reference_pattern def self.reference_pattern
%r{(?<issue>([A-Z\-]+-)\d+)} %r{(?<issue>\b([A-Z][A-Z0-9_]+-)\d+)}
end end
def to_reference(_from_project = nil) def to_reference(_from_project = nil)
......
module Projects
class ImportService < BaseService
include Gitlab::ShellAdapter
class Error < StandardError; end
ALLOWED_TYPES = [
'bitbucket',
'fogbugz',
'gitlab',
'github',
'google_code'
]
def execute
if unknown_url?
# In this case, we only want to import issues, not a repository.
create_repository
else
import_repository
end
import_data
success
rescue Error => e
error(e.message)
end
private
def create_repository
unless project.create_repository
raise Error, 'The repository could not be created.'
end
end
def import_repository
begin
gitlab_shell.import_repository(project.path_with_namespace, project.import_url)
rescue Gitlab::Shell::Error => e
raise Error, e.message
end
end
def import_data
return unless has_importer?
unless importer.execute
raise Error, 'The remote data could not be imported.'
end
end
def has_importer?
ALLOWED_TYPES.include?(project.import_type)
end
def importer
class_name = "Gitlab::#{project.import_type.camelize}Import::Importer"
class_name.constantize.new(project)
end
def unknown_url?
project.import_url == Project::UNKNOWN_IMPORT_URL
end
end
end
...@@ -14,11 +14,11 @@ ...@@ -14,11 +14,11 @@
.form-group.project-visibility-level-holder .form-group.project-visibility-level-holder
= f.label :default_project_visibility, class: 'control-label col-sm-2' = f.label :default_project_visibility, class: 'control-label col-sm-2'
.col-sm-10 .col-sm-10
= render('shared/visibility_radios', model_method: :default_project_visibility, form: f, selected_level: @application_setting.default_project_visibility, form_model: Project) = render('shared/visibility_radios', model_method: :default_project_visibility, form: f, selected_level: @application_setting.default_project_visibility, form_model: Project.new)
.form-group.project-visibility-level-holder .form-group.project-visibility-level-holder
= f.label :default_snippet_visibility, class: 'control-label col-sm-2' = f.label :default_snippet_visibility, class: 'control-label col-sm-2'
.col-sm-10 .col-sm-10
= render('shared/visibility_radios', model_method: :default_snippet_visibility, form: f, selected_level: @application_setting.default_snippet_visibility, form_model: PersonalSnippet) = render('shared/visibility_radios', model_method: :default_snippet_visibility, form: f, selected_level: @application_setting.default_snippet_visibility, form_model: ProjectSnippet.new)
.form-group .form-group
= f.label :restricted_visibility_levels, class: 'control-label col-sm-2' = f.label :restricted_visibility_levels, class: 'control-label col-sm-2'
.col-sm-10 .col-sm-10
...@@ -268,4 +268,4 @@ ...@@ -268,4 +268,4 @@
= f.text_field :sentry_dsn, class: 'form-control' = f.text_field :sentry_dsn, class: 'form-control'
.form-actions .form-actions
= f.submit 'Save', class: 'btn btn-primary' = f.submit 'Save', class: 'btn btn-save'
...@@ -22,5 +22,5 @@ ...@@ -22,5 +22,5 @@
%code= Doorkeeper.configuration.native_redirect_uri %code= Doorkeeper.configuration.native_redirect_uri
for local tests for local tests
.form-actions .form-actions
= f.submit 'Submit', class: "btn btn-primary wide" = f.submit 'Submit', class: "btn btn-save wide"
= link_to "Cancel", admin_applications_path, class: "btn btn-default" = link_to "Cancel", admin_applications_path, class: "btn btn-default"
...@@ -21,6 +21,5 @@ ...@@ -21,6 +21,5 @@
- else - else
.form-actions .form-actions
= f.submit 'Save changes', class: "btn btn-primary" = f.submit 'Save changes', class: "btn btn-save"
= link_to 'Cancel', admin_group_path(@group), class: "btn btn-cancel" = link_to 'Cancel', admin_group_path(@group), class: "btn btn-cancel"
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
%td %td
.pull-right .pull-right
- if current_user && can?(current_user, :read_build_artifacts, commit_status.project) && commit_status.artifacts? - if current_user && can?(current_user, :read_build_artifacts, commit_status.project) && commit_status.artifacts_download_url
= link_to commit_status.artifacts_download_url, title: 'Download artifacts' do = link_to commit_status.artifacts_download_url, title: 'Download artifacts' do
%i.fa.fa-download %i.fa.fa-download
- if current_user && can?(current_user, :manage_builds, commit_status.project) - if current_user && can?(current_user, :manage_builds, commit_status.project)
......
...@@ -4,52 +4,20 @@ class RepositoryImportWorker ...@@ -4,52 +4,20 @@ class RepositoryImportWorker
sidekiq_options queue: :gitlab_shell sidekiq_options queue: :gitlab_shell
def perform(project_id) attr_accessor :project, :current_user
project = Project.find(project_id)
if project.import_url == Project::UNKNOWN_IMPORT_URL def perform(project_id)
# In this case, we only want to import issues, not a repository. @project = Project.find(project_id)
unless project.create_repository @current_user = @project.creator
project.update(import_error: "The repository could not be created.")
project.import_fail
return
end
else
begin
gitlab_shell.import_repository(project.path_with_namespace, project.import_url)
rescue Gitlab::Shell::Error => e
project.update(import_error: e.message)
project.import_fail
return
end
end
data_import_result = result = Projects::ImportService.new(project, current_user).execute
case project.import_type
when 'github'
Gitlab::GithubImport::Importer.new(project).execute
when 'gitlab'
Gitlab::GitlabImport::Importer.new(project).execute
when 'bitbucket'
Gitlab::BitbucketImport::Importer.new(project).execute
when 'google_code'
Gitlab::GoogleCodeImport::Importer.new(project).execute
when 'fogbugz'
Gitlab::FogbugzImport::Importer.new(project).execute
else
true
end
unless data_import_result if result[:status] == :error
project.update(import_error: "The remote issue data could not be imported.") project.update(import_error: result[:message])
project.import_fail project.import_fail
return return
end end
if project.import_type == 'bitbucket'
Gitlab::BitbucketImport::KeyDeleter.new(project).execute
end
project.import_finish project.import_finish
end end
end end
...@@ -176,7 +176,7 @@ Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled']. ...@@ -176,7 +176,7 @@ Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].
Settings.gitlab['twitter_sharing_enabled'] ||= true if Settings.gitlab['twitter_sharing_enabled'].nil? Settings.gitlab['twitter_sharing_enabled'] ||= true if Settings.gitlab['twitter_sharing_enabled'].nil?
Settings.gitlab['restricted_visibility_levels'] = Settings.send(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], []) Settings.gitlab['restricted_visibility_levels'] = Settings.send(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], [])
Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil? Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing)) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?)|([A-Z]*-\d*))+)' if Settings.gitlab['issue_closing_pattern'].nil? Settings.gitlab['issue_closing_pattern'] = '((?:[Cc]los(?:e[sd]?|ing)|[Ff]ix(?:e[sd]|ing)?|[Rr]esolv(?:e[sd]?|ing)) +(?:(?:issues? +)?%{issue_ref}(?:(?:, *| +and +)?)|([A-Z][A-Z0-9_]+-\d+))+)' if Settings.gitlab['issue_closing_pattern'].nil?
Settings.gitlab['default_projects_features'] ||= {} Settings.gitlab['default_projects_features'] ||= {}
Settings.gitlab['webhook_timeout'] ||= 10 Settings.gitlab['webhook_timeout'] ||= 10
Settings.gitlab['max_attachment_size'] ||= 10 Settings.gitlab['max_attachment_size'] ||= 10
......
## This patch is from rails 4.2-stable. Remove it when 4.2.6 is released
## https://github.com/rails/rails/issues/21108
module ActiveRecord
module ConnectionAdapters
class AbstractMysqlAdapter < AbstractAdapter
# SHOW VARIABLES LIKE 'name'
def show_variable(name)
variables = select_all("select @@#{name} as 'Value'", 'SCHEMA')
variables.first['Value'] unless variables.empty?
rescue ActiveRecord::StatementInvalid
nil
end
# MySQL is too stupid to create a temporary table for use subquery, so we have
# to give it some prompting in the form of a subsubquery. Ugh!
def subquery_for(key, select)
subsubselect = select.clone
subsubselect.projections = [key]
subselect = Arel::SelectManager.new(select.engine)
subselect.project Arel.sql(key.name)
# Materialized subquery by adding distinct
# to work with MySQL 5.7.6 which sets optimizer_switch='derived_merge=on'
subselect.from subsubselect.distinct.as('__active_record_temp')
end
end
end
end
module ActiveRecord
module ConnectionAdapters
class MysqlAdapter < AbstractMysqlAdapter
ADAPTER_NAME = 'MySQL'.freeze
# Get the client encoding for this database
def client_encoding
return @client_encoding if @client_encoding
result = exec_query(
"select @@character_set_client",
'SCHEMA')
@client_encoding = ENCODINGS[result.rows.last.last]
end
end
end
end
...@@ -13,8 +13,8 @@ ability of downloading the files separately. ...@@ -13,8 +13,8 @@ ability of downloading the files separately.
**Note:** **Note:**
The artifacts browser will be available only for new artifacts that are sent The artifacts browser will be available only for new artifacts that are sent
to GitLab using GitLab Runner version 1.0 and up. You will not be available to to GitLab using GitLab Runner version 1.0 and up. It will not be possible to
see the browser for old artifacts already uploaded to GitLab. browse old artifacts already uploaded to GitLab.
## Enabling build artifacts ## Enabling build artifacts
......
...@@ -51,3 +51,12 @@ Feature: Project Builds Artifacts ...@@ -51,3 +51,12 @@ Feature: Project Builds Artifacts
And I click artifacts browse button And I click artifacts browse button
And I click a link to file within build artifacts And I click a link to file within build artifacts
Then download of a file extracted from build artifacts should start Then download of a file extracted from build artifacts should start
@javascript
Scenario: I click on a row in an artifacts table
Given recent build has artifacts available
And recent build has artifacts metadata available
When I visit recent build details page
And I click artifacts browse button
And I click a first row within build artifacts table
Then page with a coresponding path is loading
...@@ -73,4 +73,14 @@ class Spinach::Features::ProjectBuildsArtifacts < Spinach::FeatureSteps ...@@ -73,4 +73,14 @@ class Spinach::Features::ProjectBuildsArtifacts < Spinach::FeatureSteps
expect(response_json[:archive]).to end_with('build_artifacts.zip') expect(response_json[:archive]).to end_with('build_artifacts.zip')
expect(response_json[:entry]).to eq Base64.encode64('ci_artifacts.txt') expect(response_json[:entry]).to eq Base64.encode64('ci_artifacts.txt')
end end
step 'I click a first row within build artifacts table' do
row = first('tr[data-link]')
@row_path = row['data-link']
row.click
end
step 'page with a coresponding path is loading' do
expect(current_path).to eq @row_path
end
end end
...@@ -13,12 +13,36 @@ module Gitlab ...@@ -13,12 +13,36 @@ module Gitlab
end end
def execute def execute
project_identifier = project.import_source import_issues if has_issues?
return true unless client.project(project_identifier)["has_issues"] true
rescue ActiveRecord::RecordInvalid => e
raise Projects::ImportService::Error.new, e.message
ensure
Gitlab::BitbucketImport::KeyDeleter.new(project).execute
end
#Issues && Comments private
issues = client.issues(project_identifier)
def gl_user_id(project, bitbucket_id)
if bitbucket_id
user = User.joins(:identities).find_by("identities.extern_uid = ? AND identities.provider = 'bitbucket'", bitbucket_id.to_s)
(user && user.id) || project.creator_id
else
project.creator_id
end
end
def identifier
project.import_source
end
def has_issues?
client.project(identifier)["has_issues"]
end
def import_issues
issues = client.issues(identifier)
issues.each do |issue| issues.each do |issue|
body = '' body = ''
...@@ -33,7 +57,7 @@ module Gitlab ...@@ -33,7 +57,7 @@ module Gitlab
body = @formatter.author_line(author) body = @formatter.author_line(author)
body += issue["content"] body += issue["content"]
comments = client.issue_comments(project_identifier, issue["local_id"]) comments = client.issue_comments(identifier, issue["local_id"])
if comments.any? if comments.any?
body += @formatter.comments_header body += @formatter.comments_header
...@@ -56,20 +80,9 @@ module Gitlab ...@@ -56,20 +80,9 @@ module Gitlab
author_id: gl_user_id(project, reporter) author_id: gl_user_id(project, reporter)
) )
end end
rescue ActiveRecord::RecordInvalid => e
true raise Projects::ImportService::Error, e.message
end end
private
def gl_user_id(project, bitbucket_id)
if bitbucket_id
user = User.joins(:identities).find_by("identities.extern_uid = ? AND identities.provider = 'bitbucket'", bitbucket_id.to_s)
(user && user.id) || project.creator_id
else
project.creator_id
end
end
end end
end end
end end
...@@ -35,8 +35,8 @@ module Gitlab ...@@ -35,8 +35,8 @@ module Gitlab
end end
true true
rescue ActiveRecord::RecordInvalid rescue ActiveRecord::RecordInvalid => e
false raise Projects::ImportService::Error, e.message
end end
def import_pull_requests def import_pull_requests
...@@ -53,8 +53,8 @@ module Gitlab ...@@ -53,8 +53,8 @@ module Gitlab
end end
true true
rescue ActiveRecord::RecordInvalid rescue ActiveRecord::RecordInvalid => e
false raise Projects::ImportService::Error, e.message
end end
def import_comments(issue_number, noteable) def import_comments(issue_number, noteable)
...@@ -83,10 +83,13 @@ module Gitlab ...@@ -83,10 +83,13 @@ module Gitlab
true true
rescue Gitlab::Shell::Error => e rescue Gitlab::Shell::Error => e
if e.message =~ /repository not exported/ # GitHub error message when the wiki repo has not been created,
true # this means that repo has wiki enabled, but have no pages. So,
# we can skip the import.
if e.message !~ /repository not exported/
raise Projects::ImportService::Error, e.message
else else
false true
end end
end end
end end
......
require 'rails_helper'
describe GroupsController do
describe 'GET index' do
context 'as a user' do
it 'redirects to Groups Dashboard' do
sign_in(create(:user))
get :index
expect(response).to redirect_to(dashboard_groups_path)
end
end
context 'as a guest' do
it 'redirects to Explore Groups' do
get :index
expect(response).to redirect_to(explore_groups_path)
end
end
end
end
FactoryGirl.define do FactoryGirl.define do
factory :commit_status, class: CommitStatus do factory :commit_status, class: CommitStatus do
started_at 'Di 29. Okt 09:51:28 CET 2013'
finished_at 'Di 29. Okt 09:53:28 CET 2013'
name 'default' name 'default'
status 'success' status 'success'
description 'commit status' description 'commit status'
commit factory: :ci_commit_with_one_job commit factory: :ci_commit_with_one_job
started_at 'Tue, 26 Jan 2016 08:21:42 +0100'
finished_at 'Tue, 26 Jan 2016 08:23:42 +0100'
after(:build) do |build, evaluator|
build.project = build.commit.project
end
factory :generic_commit_status, class: GenericCommitStatus do factory :generic_commit_status, class: GenericCommitStatus do
name 'generic' name 'generic'
......
...@@ -16,83 +16,104 @@ describe 'Commits' do ...@@ -16,83 +16,104 @@ describe 'Commits' do
FactoryGirl.create :ci_commit, project: project, sha: project.commit.sha FactoryGirl.create :ci_commit, project: project, sha: project.commit.sha
end end
let!(:build) { FactoryGirl.create :ci_build, commit: commit } context 'commit status is Generic Commit Status' do
let!(:status) { FactoryGirl.create :generic_commit_status, commit: commit }
describe 'Project commits' do describe 'Commit builds' do
before do before do
visit namespace_project_commits_path(project.namespace, project, :master) visit ci_status_path(commit)
end end
it 'should show build status' do it { expect(page).to have_content commit.sha[0..7] }
page.within("//li[@id='commit-#{commit.short_sha}']") do
expect(page).to have_css(".ci-status-link") it 'contains generic commit status build' do
page.within('.table-holder') do
expect(page).to have_content "##{status.id}" # build id
expect(page).to have_content 'generic' # build name
end
end end
end end
end end
describe 'Commit builds' do context 'commit status is Ci Build' do
before do let!(:build) { FactoryGirl.create :ci_build, commit: commit }
visit ci_status_path(commit)
end
it { expect(page).to have_content commit.sha[0..7] }
it { expect(page).to have_content commit.git_commit_message }
it { expect(page).to have_content commit.git_author_name }
end
context 'Download artifacts' do describe 'Project commits' do
let(:artifacts_file) { fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') } before do
visit namespace_project_commits_path(project.namespace, project, :master)
end
before do it 'should show build status' do
build.update_attributes(artifacts_file: artifacts_file) page.within("//li[@id='commit-#{commit.short_sha}']") do
expect(page).to have_css(".ci-status-link")
end
end
end end
it do describe 'Commit builds' do
visit ci_status_path(commit) before do
click_on 'Download artifacts' visit ci_status_path(commit)
expect(page.response_headers['Content-Type']).to eq(artifacts_file.content_type) end
end
end
describe 'Cancel all builds' do it { expect(page).to have_content commit.sha[0..7] }
it 'cancels commit' do it { expect(page).to have_content commit.git_commit_message }
visit ci_status_path(commit) it { expect(page).to have_content commit.git_author_name }
click_on 'Cancel running'
expect(page).to have_content 'canceled'
end end
end
describe 'Cancel build' do context 'Download artifacts' do
it 'cancels build' do let(:artifacts_file) { fixture_file_upload(Rails.root + 'spec/fixtures/banana_sample.gif', 'image/gif') }
visit ci_status_path(commit)
click_on 'Cancel' before do
expect(page).to have_content 'canceled' build.update_attributes(artifacts_file: artifacts_file)
end end
end
describe '.gitlab-ci.yml not found warning' do it do
context 'ci builds enabled' do
it "does not show warning" do
visit ci_status_path(commit) visit ci_status_path(commit)
expect(page).not_to have_content '.gitlab-ci.yml not found in this commit' click_on 'Download artifacts'
expect(page.response_headers['Content-Type']).to eq(artifacts_file.content_type)
end end
end
it 'shows warning' do describe 'Cancel all builds' do
stub_ci_commit_yaml_file(nil) it 'cancels commit' do
visit ci_status_path(commit) visit ci_status_path(commit)
expect(page).to have_content '.gitlab-ci.yml not found in this commit' click_on 'Cancel running'
expect(page).to have_content 'canceled'
end end
end end
context 'ci builds disabled' do describe 'Cancel build' do
before do it 'cancels build' do
stub_ci_builds_disabled
stub_ci_commit_yaml_file(nil)
visit ci_status_path(commit) visit ci_status_path(commit)
click_on 'Cancel'
expect(page).to have_content 'canceled'
end end
end
describe '.gitlab-ci.yml not found warning' do
context 'ci builds enabled' do
it "does not show warning" do
visit ci_status_path(commit)
expect(page).not_to have_content '.gitlab-ci.yml not found in this commit'
end
it 'shows warning' do
stub_ci_commit_yaml_file(nil)
visit ci_status_path(commit)
expect(page).to have_content '.gitlab-ci.yml not found in this commit'
end
end
context 'ci builds disabled' do
before do
stub_ci_builds_disabled
stub_ci_commit_yaml_file(nil)
visit ci_status_path(commit)
end
it 'does not show warning' do it 'does not show warning' do
expect(page).not_to have_content '.gitlab-ci.yml not found in this commit' expect(page).not_to have_content '.gitlab-ci.yml not found in this commit'
end
end end
end end
end end
......
...@@ -66,5 +66,10 @@ describe LabelsHelper do ...@@ -66,5 +66,10 @@ describe LabelsHelper do
it 'uses dark text on light backgrounds' do it 'uses dark text on light backgrounds' do
expect(text_color_for_bg('#EEEEEE')).to eq('#333333') expect(text_color_for_bg('#EEEEEE')).to eq('#333333')
end end
it 'supports RGB triplets' do
expect(text_color_for_bg('#FFF')).to eq '#333333'
expect(text_color_for_bg('#000')).to eq '#FFFFFF'
end
end end
end end
...@@ -135,6 +135,17 @@ describe Gitlab::ClosingIssueExtractor, lib: true do ...@@ -135,6 +135,17 @@ describe Gitlab::ClosingIssueExtractor, lib: true do
message = "resolve #{reference}" message = "resolve #{reference}"
expect(subject.closed_by_message(message)).to eq([issue]) expect(subject.closed_by_message(message)).to eq([issue])
end end
context 'with an external issue tracker reference' do
it 'extracts the referenced issue' do
jira_project = create(:jira_project, name: 'JIRA_EXT1')
jira_issue = ExternalIssue.new("#{jira_project.name}-1", project: jira_project)
closing_issue_extractor = described_class.new jira_project
message = "Resolve #{jira_issue.to_reference}"
expect(closing_issue_extractor.closed_by_message(message)).to eq([jira_issue])
end
end
end end
context "with a cross-project reference" do context "with a cross-project reference" do
......
...@@ -10,6 +10,21 @@ describe ExternalIssue, models: true do ...@@ -10,6 +10,21 @@ describe ExternalIssue, models: true do
it { is_expected.to include_module(Referable) } it { is_expected.to include_module(Referable) }
end end
describe '.reference_pattern' do
it 'allows underscores in the project name' do
expect(ExternalIssue.reference_pattern.match('EXT_EXT-1234')[0]).to eq 'EXT_EXT-1234'
end
it 'allows numbers in the project name' do
expect(ExternalIssue.reference_pattern.match('EXT3_EXT-1234')[0]).to eq 'EXT3_EXT-1234'
end
it 'requires the project name to begin with A-Z' do
expect(ExternalIssue.reference_pattern.match('3EXT_EXT-1234')).to eq nil
expect(ExternalIssue.reference_pattern.match('EXT_EXT-1234')[0]).to eq 'EXT_EXT-1234'
end
end
describe '#to_reference' do describe '#to_reference' do
it 'returns a String reference to the object' do it 'returns a String reference to the object' do
expect(issue.to_reference).to eq issue.id expect(issue.to_reference).to eq issue.id
......
require 'spec_helper'
describe Projects::ImportService, services: true do
let!(:project) { create(:empty_project) }
let(:user) { project.creator }
subject { described_class.new(project, user) }
describe '#execute' do
context 'with unknown url' do
before do
project.import_url = Project::UNKNOWN_IMPORT_URL
end
it 'succeeds if repository is created successfully' do
expect(project).to receive(:create_repository).and_return(true)
result = subject.execute
expect(result[:status]).to eq :success
end
it 'fails if repository creation fails' do
expect(project).to receive(:create_repository).and_return(false)
result = subject.execute
expect(result[:status]).to eq :error
expect(result[:message]).to eq 'The repository could not be created.'
end
end
context 'with known url' do
before do
project.import_url = 'https://github.com/vim/vim.git'
end
it 'succeeds if repository import is successfully' do
expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).with(project.path_with_namespace, project.import_url).and_return(true)
result = subject.execute
expect(result[:status]).to eq :success
end
it 'fails if repository import fails' do
expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).with(project.path_with_namespace, project.import_url).and_raise(Gitlab::Shell::Error.new('Failed to import the repository'))
result = subject.execute
expect(result[:status]).to eq :error
expect(result[:message]).to eq 'Failed to import the repository'
end
end
context 'with valid importer' do
before do
stub_github_omniauth_provider
project.import_url = 'https://github.com/vim/vim.git'
project.import_type = 'github'
allow(project).to receive(:import_data).and_return(double.as_null_object)
end
it 'succeeds if importer succeeds' do
expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).with(project.path_with_namespace, project.import_url).and_return(true)
expect_any_instance_of(Gitlab::GithubImport::Importer).to receive(:execute).and_return(true)
result = subject.execute
expect(result[:status]).to eq :success
end
it 'fails if importer fails' do
expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).with(project.path_with_namespace, project.import_url).and_return(true)
expect_any_instance_of(Gitlab::GithubImport::Importer).to receive(:execute).and_return(false)
result = subject.execute
expect(result[:status]).to eq :error
expect(result[:message]).to eq 'The remote data could not be imported.'
end
it 'fails if importer raise an error' do
expect_any_instance_of(Gitlab::Shell).to receive(:import_repository).with(project.path_with_namespace, project.import_url).and_return(true)
expect_any_instance_of(Gitlab::GithubImport::Importer).to receive(:execute).and_raise(Projects::ImportService::Error.new('Github: failed to connect API'))
result = subject.execute
expect(result[:status]).to eq :error
expect(result[:message]).to eq 'Github: failed to connect API'
end
end
def stub_github_omniauth_provider
provider = OpenStruct.new(
name: 'github',
app_id: 'asd123',
app_secret: 'asd123'
)
Gitlab.config.omniauth.providers << provider
end
end
end
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