Commit c0577a31 authored by Valery Sizov's avatar Valery Sizov

Merge branch 'master' into ce_upstream_15_10

parents 6b5fb14f 1c542e28
v 8.1.0 (unreleased)
- added an issues template (Hannes Rosenögger)
v 8.1.0 v 8.1.0
- Add documentation for "Share project with group" API call - Add documentation for "Share project with group" API call
- Abiliy to disable 'Share with Group' feature (via UI and API) - Abiliy to disable 'Share with Group' feature (via UI and API)
......
...@@ -47,6 +47,12 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -47,6 +47,12 @@ class Projects::IssuesController < Projects::ApplicationController
) )
@issue = @project.issues.new(issue_params) @issue = @project.issues.new(issue_params)
# Set Issue description based on project template
if @project.issues_template.present?
@issue.description = @project.issues_template
end
respond_with(@issue) respond_with(@issue)
end end
......
...@@ -9,7 +9,8 @@ class Projects::ServicesController < Projects::ApplicationController ...@@ -9,7 +9,8 @@ class Projects::ServicesController < Projects::ApplicationController
:note_events, :send_from_committer_email, :disable_diffs, :external_wiki_url, :note_events, :send_from_committer_email, :disable_diffs, :external_wiki_url,
:jira_issue_transition_id, :jira_issue_transition_id,
:notify, :color, :notify, :color,
:server_host, :server_port, :default_irc_uri, :enable_ssl_verification] :server_host, :server_port, :default_irc_uri, :enable_ssl_verification,
:multiproject_enabled, :pass_unstable]
# Parameters to ignore if no value is specified # Parameters to ignore if no value is specified
FILTER_BLANK_PARAMS = [:password] FILTER_BLANK_PARAMS = [:password]
......
...@@ -201,7 +201,7 @@ class ProjectsController < ApplicationController ...@@ -201,7 +201,7 @@ class ProjectsController < ApplicationController
params.require(:project).permit( params.require(:project).permit(
:name, :path, :description, :issues_tracker, :tag_list, :name, :path, :description, :issues_tracker, :tag_list,
:issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :default_branch, :issues_enabled, :merge_requests_enabled, :snippets_enabled, :issues_tracker_id, :default_branch,
:wiki_enabled, :merge_requests_template, :visibility_level, :merge_requests_rebase_enabled, :wiki_enabled, :issues_template, :merge_requests_template, :visibility_level, :merge_requests_rebase_enabled,
:import_url, :last_activity_at, :namespace_id, :avatar, :import_url, :last_activity_at, :namespace_id, :avatar,
:approvals_before_merge, :approver_ids, :reset_approvals_on_push, :merge_requests_ff_only_enabled :approvals_before_merge, :approver_ids, :reset_approvals_on_push, :merge_requests_ff_only_enabled
) )
......
...@@ -11,9 +11,12 @@ ...@@ -11,9 +11,12 @@
# active :boolean default(FALSE), not null # active :boolean default(FALSE), not null
# properties :text # properties :text
# #
require 'uri'
class JenkinsService < CiService class JenkinsService < CiService
prop_accessor :project_url prop_accessor :project_url
prop_accessor :multiproject_enabled
prop_accessor :pass_unstable
validates :project_url, presence: true, if: :activated? validates :project_url, presence: true, if: :activated?
...@@ -46,13 +49,36 @@ class JenkinsService < CiService ...@@ -46,13 +49,36 @@ class JenkinsService < CiService
def fields def fields
[ [
{ type: 'text', name: 'project_url', placeholder: 'Jenkins project URL like http://jenkins.example.com/job/my-project/' } { type: 'text', name: 'project_url', placeholder: 'Jenkins project URL like http://jenkins.example.com/job/my-project/' },
{ type: 'checkbox', name: 'multiproject_enabled', title: "Multi-project setup enabled?",
help: "Multi-project mode is configured in Jenkins Gitlab Hook plugin." },
{ type: 'checkbox', name: 'pass_unstable', title: 'Should unstable builds be treated as passing?',
help: 'Unstable builds will be treated as passing.' }
] ]
end end
def multiproject_enabled?
self.multiproject_enabled == '1'
end
def pass_unstable?
self.pass_unstable == '1'
end
def build_page(sha, ref = nil) def build_page(sha, ref = nil)
base_url = ref.nil? || ref == 'master' ? project_url : "#{project_url}_#{ref}" if multiproject_enabled? && ref.present?
base_url + "/scm/bySHA1/#{sha}" URI.encode("#{base_project_url}/#{project.name}_#{ref.gsub('/', '_')}/scm/bySHA1/#{sha}").to_s
else
"#{project_url}/scm/bySHA1/#{sha}"
end
end
# When multi-project is enabled we need to have a different URL. Rather than
# relying on the user to provide the proper URL depending on multi-project
# we just parse the URL and make sure it's how we want it.
def base_project_url
url = URI.parse(project_url)
URI.join(url, '/job').to_s
end end
def commit_status(sha, ref = nil) def commit_status(sha, ref = nil)
...@@ -72,7 +98,7 @@ class JenkinsService < CiService ...@@ -72,7 +98,7 @@ class JenkinsService < CiService
if response.code == 200 if response.code == 200
# img.build-caption-status-icon for old jenkins version # img.build-caption-status-icon for old jenkins version
src = Nokogiri.parse(response).css('img.build-caption-status-icon,.build-caption>img').first.attributes['src'].value src = Nokogiri.parse(response).css('img.build-caption-status-icon,.build-caption>img').first.attributes['src'].value
if src =~ /blue\.png$/ if src =~ /blue\.png$/ || (src =~ /yellow\.png/ && pass_unstable?)
'success' 'success'
elsif src =~ /(red|aborted|yellow)\.png$/ elsif src =~ /(red|aborted|yellow)\.png$/
'failed' 'failed'
......
%fieldset.issues-feature
%legend
Issues:
.form-group
= f.label :issues_template, class: 'control-label' do
Description template
.col-sm-10
= f.text_area :issues_template, class: "form-control", rows: 3
...@@ -24,7 +24,7 @@ ...@@ -24,7 +24,7 @@
= f.label :merge_requests_template, class: 'control-label' do = f.label :merge_requests_template, class: 'control-label' do
Description template Description template
.col-sm-10 .col-sm-10
= f.text_area :merge_requests_template, placeholder: "This MR should have: *", class: "form-control", rows: 3 = f.text_area :merge_requests_template, class: "form-control", rows: 3
.form-group .form-group
= f.label :approvals_before_merge, class: 'control-label' do = f.label :approvals_before_merge, class: 'control-label' do
......
...@@ -77,6 +77,8 @@ ...@@ -77,6 +77,8 @@
%br %br
%span.descr Share code pastes with others out of git repository %span.descr Share code pastes with others out of git repository
= render 'issues_settings', f: f
= render 'merge_request_settings', f: f = render 'merge_request_settings', f: f
%fieldset.features %fieldset.features
......
class AddIssuesTemplateToProject < ActiveRecord::Migration
def change
add_column :projects, :issues_template, :text
end
end
...@@ -691,6 +691,7 @@ ActiveRecord::Schema.define(version: 20151008130321) do ...@@ -691,6 +691,7 @@ ActiveRecord::Schema.define(version: 20151008130321) do
t.boolean "reset_approvals_on_push", default: true t.boolean "reset_approvals_on_push", default: true
t.integer "commit_count", default: 0 t.integer "commit_count", default: 0
t.boolean "merge_requests_ff_only_enabled", default: false t.boolean "merge_requests_ff_only_enabled", default: false
t.text "issues_template"
end end
add_index "projects", ["created_at", "id"], name: "index_projects_on_created_at_and_id", using: :btree add_index "projects", ["created_at", "id"], name: "index_projects_on_created_at_and_id", using: :btree
......
...@@ -39,6 +39,35 @@ Now navigate to GitLab services page and activate Jenkins ...@@ -39,6 +39,35 @@ Now navigate to GitLab services page and activate Jenkins
Done! Now when you push to GitLab - it will create a build for Jenkins. Done! Now when you push to GitLab - it will create a build for Jenkins.
And also you will be able to see merge request build status with a link to the Jenkins build. And also you will be able to see merge request build status with a link to the Jenkins build.
### Multi-project Configuration
The GitLab Hook plugin in Jenkins supports the automatic creation of a project
for each feature branch. After configuration GitLab will trigger feature branch
builds and a corresponding project will be created in Jenkins.
Configure the GitLab Hook plugin in Jenkins. Go to 'Manage Jenkins' and then
'Configure System'. Find the 'GitLab Web Hook' section and configure as shown below.
![Jenkins Multi-project Configuration](jenkins_multiproject_configuration.png)
In the Jenkins service in GitLab, check the 'Multi-project setup enabled?'.
![Jenkins Multi-project Enabled](jenkins_multiproject_enabled.png)
### Mark unstable build as passing
When using some plugins in Jenkins, an unstable build status will result when
tests are not passing. In these cases the unstable status in Jenkins should
register as a failure in GitLab on the merge request page. In other cases you
may not want an unstable status to display as a build failure in GitLab. Control
this behavior using the 'Should unstable builds be treated as passing?' setting
in the Jenkins service in GitLab.
When checked, unstable builds will display as green or passing in GitLab. By
default unstable builds display in GitLab as red or failed.
![Jenkins Unstable Passing](jenkins_unstable_passing.png)
## Development ## Development
An explanation of how this works in case anyone want to improve it or develop this service for another CI tool. An explanation of how this works in case anyone want to improve it or develop this service for another CI tool.
......
...@@ -77,6 +77,14 @@ class Spinach::Features::Project < Spinach::FeatureSteps ...@@ -77,6 +77,14 @@ class Spinach::Features::Project < Spinach::FeatureSteps
expect(find_field('project_merge_requests_template').value).to eq 'This merge request should contain the following.' expect(find_field('project_merge_requests_template').value).to eq 'This merge request should contain the following.'
end end
step 'I fill in issues template' do
fill_in 'project_issues_template', with: "This issue should contain the following."
end
step 'I should see project with issues template saved' do
expect(find_field('project_issues_template').value).to eq 'This issue should contain the following.'
end
step 'I should see project "Shop" README link' do step 'I should see project "Shop" README link' do
page.within '.project-side' do page.within '.project-side' do
expect(page).to have_content "README.md" expect(page).to have_content "README.md"
......
...@@ -10,7 +10,7 @@ module SharedProject ...@@ -10,7 +10,7 @@ module SharedProject
# 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")
@project ||= create(:project, name: "Shop", namespace: @user.namespace, snippets_enabled: true, merge_requests_template: "This merge request should contain the following.") @project ||= create(:project, name: "Shop", namespace: @user.namespace, snippets_enabled: true, issues_template: "This issue should contain the following.", merge_requests_template: "This merge request should contain the following.")
@project.team << [@user, :master] @project.team << [@user, :master]
end end
......
...@@ -97,6 +97,7 @@ module Grack ...@@ -97,6 +97,7 @@ module Grack
# Set @user if authentication succeeded # Set @user if authentication succeeded
identity = ::Identity.find_by(provider: 'kerberos', extern_uid: krb_principal) identity = ::Identity.find_by(provider: 'kerberos', extern_uid: krb_principal)
identity ||= ::Identity.find_by(provider: 'kerberos', extern_uid: krb_principal.split("@")[0])
@user = identity.user if identity @user = identity.user if identity
else else
# Authentication with username and password # Authentication with username and password
......
...@@ -35,31 +35,85 @@ describe JenkinsService do ...@@ -35,31 +35,85 @@ describe JenkinsService do
eos eos
end end
describe :commit_status do
before do before do
@service = JenkinsService.new @service = JenkinsService.new
allow(@service).to receive_messages( allow(@service).to receive_messages(
service_hook: true, service_hook: true,
project_url: 'http://jenkins.gitlab.org/projects/2', project_url: 'http://jenkins.gitlab.org/job/2',
multiproject_enabled: '0',
pass_unstable: '0',
token: 'verySecret' token: 'verySecret'
) )
end end
describe :commit_status do
statuses = { 'blue.png' => 'success', 'yellow.png' => 'failed', 'red.png' => 'failed', 'aborted.png' => 'failed', 'blue-anime.gif' => 'running', 'grey.png' => 'pending' } statuses = { 'blue.png' => 'success', 'yellow.png' => 'failed', 'red.png' => 'failed', 'aborted.png' => 'failed', 'blue-anime.gif' => 'running', 'grey.png' => 'pending' }
statuses.each do |icon, state| statuses.each do |icon, state|
it "should have a status of #{state} when the icon #{icon} exists." do it "should have a status of #{state} when the icon #{icon} exists." do
stub_request(:get, "http://jenkins.gitlab.org/projects/2/scm/bySHA1/2ab7834c").to_return(status: 200, body: status_body_for_icon(icon), headers: {}) stub_request(:get, "http://jenkins.gitlab.org/job/2/scm/bySHA1/2ab7834c").to_return(status: 200, body: status_body_for_icon(icon), headers: {})
expect(@service.commit_status("2ab7834c", 'master')).to eq(state) expect(@service.commit_status("2ab7834c", 'master')).to eq(state)
end end
end end
end end
describe 'commit status with passing unstable' do
before do
@service = JenkinsService.new
allow(@service).to receive_messages(
service_hook: true,
project_url: 'http://jenkins.gitlab.org/job/2',
multiproject_enabled: '0',
pass_unstable: '1',
token: 'verySecret'
)
end
it "should have a status of success when the icon yellow exists." do
stub_request(:get, "http://jenkins.gitlab.org/job/2/scm/bySHA1/2ab7834c").to_return(status: 200, body: status_body_for_icon('yellow.png'), headers: {})
expect(@service.commit_status("2ab7834c", 'master')).to eq('success')
end
end
describe 'multiproject enabled' do
let!(:project) { create(:project) }
before do
@service = JenkinsService.new
allow(@service).to receive_messages(
service_hook: true,
project_url: 'http://jenkins.gitlab.org/job/2',
multiproject_enabled: '1',
token: 'verySecret',
project: project
)
end
describe :build_page do
it { expect(@service.build_page("2ab7834c", 'master')).to eq("http://jenkins.gitlab.org/job/#{project.name}_master/scm/bySHA1/2ab7834c") }
end
describe :build_page_with_branch do
it { expect(@service.build_page("2ab7834c", 'test_branch')).to eq("http://jenkins.gitlab.org/job/#{project.name}_test_branch/scm/bySHA1/2ab7834c") }
end
end
describe 'multiproject disabled' do
before do
@service = JenkinsService.new
allow(@service).to receive_messages(
service_hook: true,
project_url: 'http://jenkins.gitlab.org/job/2',
multiproject_enabled: '0',
token: 'verySecret'
)
end
describe :build_page do describe :build_page do
it { expect(@service.build_page("2ab7834c", 'master')).to eq("http://jenkins.gitlab.org/projects/2/scm/bySHA1/2ab7834c") } it { expect(@service.build_page("2ab7834c", 'master')).to eq("http://jenkins.gitlab.org/job/2/scm/bySHA1/2ab7834c") }
end end
describe :build_page_with_branch do describe :build_page_with_branch do
it { expect(@service.build_page("2ab7834c", 'test_branch')).to eq("http://jenkins.gitlab.org/projects/2_test_branch/scm/bySHA1/2ab7834c") } it { expect(@service.build_page("2ab7834c", 'test_branch')).to eq("http://jenkins.gitlab.org/job/2/scm/bySHA1/2ab7834c") }
end
end end
end 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