Commit d9f7ad05 authored by Valery Sizov's avatar Valery Sizov

Merge branch 'master' into ce_upstream

parents 4e14c080 3b61dc47
...@@ -2,12 +2,21 @@ Please view this file on the master branch, on stable branches it's out of date. ...@@ -2,12 +2,21 @@ Please view this file on the master branch, on stable branches it's out of date.
v 8.3.0 (unreleased) v 8.3.0 (unreleased)
- Merge when build succeeds (Zeger-Jan van de Weg) - Merge when build succeeds (Zeger-Jan van de Weg)
v 8.4.0 (unreleased)
- Implement new UI for group page
v 8.3.0
- Add CAS support (tduehr)
- Bump rack-attack to 4.3.1 for security fix (Stan Hu)
- API support for starred projects for authorized user (Zeger-Jan van de Weg) - API support for starred projects for authorized user (Zeger-Jan van de Weg)
- Add link to merge request on build detail page.
- Add open_issues_count to project API (Stan Hu) - Add open_issues_count to project API (Stan Hu)
- Expand character set of usernames created by Omniauth (Corey Hinshaw) - Expand character set of usernames created by Omniauth (Corey Hinshaw)
- Add button to automatically merge a merge request when the build succeeds (Zeger-Jan van de Weg) - Add button to automatically merge a merge request when the build succeeds (Zeger-Jan van de Weg)
- Provide better diagnostic message upon project creation errors (Stan Hu) - Provide better diagnostic message upon project creation errors (Stan Hu)
- Bump devise to 3.5.3 to fix reset token expiring after account creation (Stan Hu) - Bump devise to 3.5.3 to fix reset token expiring after account creation (Stan Hu)
- Remove api credentials from link to build_page
- Deprecate GitLabCiService making it to always be inactive
- Bump gollum-lib to 4.1.0 (Stan Hu) - Bump gollum-lib to 4.1.0 (Stan Hu)
- Fix broken group avatar upload under "New group" (Stan Hu) - Fix broken group avatar upload under "New group" (Stan Hu)
- Update project repositorize size and commit count during import:repos task (Stan Hu) - Update project repositorize size and commit count during import:repos task (Stan Hu)
...@@ -19,13 +28,16 @@ v 8.3.0 (unreleased) ...@@ -19,13 +28,16 @@ v 8.3.0 (unreleased)
- Fix 500 error when update group member permission - Fix 500 error when update group member permission
- Trim leading and trailing whitespace of milestone and issueable titles (Jose Corcuera) - Trim leading and trailing whitespace of milestone and issueable titles (Jose Corcuera)
- Recognize issue/MR/snippet/commit links as references - Recognize issue/MR/snippet/commit links as references
- Backport JIRA features from EE to CE
- Add ignore whitespace change option to commit view - Add ignore whitespace change option to commit view
- Fire update hook from GitLab - Fire update hook from GitLab
- Allow account unlock via email
- Style warning about mentioning many people in a comment - Style warning about mentioning many people in a comment
- Fix: sort milestones by due date once again (Greg Smethells) - Fix: sort milestones by due date once again (Greg Smethells)
- Migrate all CI::Services and CI::WebHooks to Services and WebHooks - Migrate all CI::Services and CI::WebHooks to Services and WebHooks
- Don't show project fork event as "imported" - Don't show project fork event as "imported"
- Add API endpoint to fetch merge request commits list - Add API endpoint to fetch merge request commits list
- Don't create CI status for refs that doesn't have .gitlab-ci.yml, even if the builds are enabled
- Expose events API with comment information and author info - Expose events API with comment information and author info
- Fix: Ensure "Remove Source Branch" button is not shown when branch is being deleted. #3583 - Fix: Ensure "Remove Source Branch" button is not shown when branch is being deleted. #3583
- Run custom Git hooks when branch is created or deleted. - Run custom Git hooks when branch is created or deleted.
...@@ -58,6 +70,7 @@ v 8.3.0 (unreleased) ...@@ -58,6 +70,7 @@ v 8.3.0 (unreleased)
- Do not show build status unless builds are enabled and `.gitlab-ci.yml` is present - Do not show build status unless builds are enabled and `.gitlab-ci.yml` is present
- Persist runners registration token in database - Persist runners registration token in database
- Fix online editor should not remove newlines at the end of the file - Fix online editor should not remove newlines at the end of the file
- Expose Git's version in the admin area
v 8.2.3 v 8.2.3
- Fix application settings cache not expiring after changes (Stan Hu) - Fix application settings cache not expiring after changes (Stan Hu)
......
...@@ -358,7 +358,7 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor ...@@ -358,7 +358,7 @@ available at [http://contributor-covenant.org/version/1/1/0/](http://contributor
[core team]: https://about.gitlab.com/core-team/ [core team]: https://about.gitlab.com/core-team/
[getting help page]: https://about.gitlab.com/getting-help/ [getting help page]: https://about.gitlab.com/getting-help/
[Codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq [Codetriage]: http://www.codetriage.com/gitlabhq/gitlabhq
[up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=up+for+grabs [up-for-grabs]: https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=up-for-grabs
[medium-up-for-grabs]: https://medium.com/@kentcdodds/first-timers-only-78281ea47455 [medium-up-for-grabs]: https://medium.com/@kentcdodds/first-timers-only-78281ea47455
[ce-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/issues [ce-tracker]: https://gitlab.com/gitlab-org/gitlab-ce/issues
[ee-tracker]: https://gitlab.com/gitlab-org/gitlab-ee/issues [ee-tracker]: https://gitlab.com/gitlab-org/gitlab-ee/issues
......
...@@ -23,6 +23,7 @@ gem 'devise-async', '~> 0.9.0' ...@@ -23,6 +23,7 @@ gem 'devise-async', '~> 0.9.0'
gem 'doorkeeper', '~> 2.2.0' gem 'doorkeeper', '~> 2.2.0'
gem 'omniauth', '~> 1.2.2' gem 'omniauth', '~> 1.2.2'
gem 'omniauth-bitbucket', '~> 0.0.2' gem 'omniauth-bitbucket', '~> 0.0.2'
gem 'omniauth-cas3', '~> 1.1.2'
gem 'omniauth-facebook', '~> 3.0.0' gem 'omniauth-facebook', '~> 3.0.0'
gem 'omniauth-github', '~> 1.1.1' gem 'omniauth-github', '~> 1.1.1'
gem 'omniauth-gitlab', '~> 1.0.0' gem 'omniauth-gitlab', '~> 1.0.0'
...@@ -106,6 +107,9 @@ gem 'wikicloth', '0.8.1' ...@@ -106,6 +107,9 @@ gem 'wikicloth', '0.8.1'
gem 'asciidoctor', '~> 1.5.2' gem 'asciidoctor', '~> 1.5.2'
gem 'rouge', '~> 1.10.1' gem 'rouge', '~> 1.10.1'
# See https://groups.google.com/forum/#!topic/ruby-security-ann/aSbgDiwb24s
gem 'nokogiri', '1.6.7.1'
# Diffs # Diffs
gem 'diffy', '~> 3.0.3' gem 'diffy', '~> 3.0.3'
...@@ -180,7 +184,7 @@ gem "sanitize", '~> 2.0' ...@@ -180,7 +184,7 @@ gem "sanitize", '~> 2.0'
gem 'babosa', '~> 1.0.2' gem 'babosa', '~> 1.0.2'
# Protect against bruteforcing # Protect against bruteforcing
gem "rack-attack", '~> 4.3.0' gem "rack-attack", '~> 4.3.1'
# Ace editor # Ace editor
gem 'ace-rails-ap', '~> 2.0.1' gem 'ace-rails-ap', '~> 2.0.1'
......
...@@ -425,7 +425,7 @@ GEM ...@@ -425,7 +425,7 @@ GEM
grape grape
newrelic_rpm newrelic_rpm
newrelic_rpm (3.9.4.245) newrelic_rpm (3.9.4.245)
nokogiri (1.6.7) nokogiri (1.6.7.1)
mini_portile2 (~> 2.0.0.rc2) mini_portile2 (~> 2.0.0.rc2)
nprogress-rails (0.1.6.7) nprogress-rails (0.1.6.7)
oauth (0.4.7) oauth (0.4.7)
...@@ -444,6 +444,10 @@ GEM ...@@ -444,6 +444,10 @@ GEM
multi_json (~> 1.7) multi_json (~> 1.7)
omniauth (~> 1.1) omniauth (~> 1.1)
omniauth-oauth (~> 1.0) omniauth-oauth (~> 1.0)
omniauth-cas3 (1.1.3)
addressable (~> 2.3)
nokogiri (~> 1.6.6)
omniauth (~> 1.2)
omniauth-facebook (3.0.0) omniauth-facebook (3.0.0)
omniauth-oauth2 (~> 1.2) omniauth-oauth2 (~> 1.2)
omniauth-github (1.1.2) omniauth-github (1.1.2)
...@@ -512,7 +516,7 @@ GEM ...@@ -512,7 +516,7 @@ GEM
rack (1.6.4) rack (1.6.4)
rack-accept (0.4.5) rack-accept (0.4.5)
rack (>= 0.4) rack (>= 0.4)
rack-attack (4.3.0) rack-attack (4.3.1)
rack rack
rack-cors (0.4.0) rack-cors (0.4.0)
rack-mount (0.8.3) rack-mount (0.8.3)
...@@ -897,11 +901,13 @@ DEPENDENCIES ...@@ -897,11 +901,13 @@ DEPENDENCIES
net-ssh (~> 3.0.1) net-ssh (~> 3.0.1)
newrelic-grape newrelic-grape
newrelic_rpm (~> 3.9.4.245) newrelic_rpm (~> 3.9.4.245)
nokogiri (= 1.6.7.1)
nprogress-rails (~> 0.1.6.7) nprogress-rails (~> 0.1.6.7)
oauth2 (~> 1.0.0) oauth2 (~> 1.0.0)
octokit (~> 3.7.0) octokit (~> 3.7.0)
omniauth (~> 1.2.2) omniauth (~> 1.2.2)
omniauth-bitbucket (~> 0.0.2) omniauth-bitbucket (~> 0.0.2)
omniauth-cas3 (~> 1.1.2)
omniauth-facebook (~> 3.0.0) omniauth-facebook (~> 3.0.0)
omniauth-github (~> 1.1.1) omniauth-github (~> 1.1.1)
omniauth-gitlab (~> 1.0.0) omniauth-gitlab (~> 1.0.0)
...@@ -917,7 +923,7 @@ DEPENDENCIES ...@@ -917,7 +923,7 @@ DEPENDENCIES
poltergeist (~> 1.8.1) poltergeist (~> 1.8.1)
pry-rails pry-rails
quiet_assets (~> 1.0.2) quiet_assets (~> 1.0.2)
rack-attack (~> 4.3.0) rack-attack (~> 4.3.1)
rack-cors (~> 0.4.0) rack-cors (~> 0.4.0)
rack-oauth2 (~> 1.2.1) rack-oauth2 (~> 1.2.1)
rails (= 4.2.4) rails (= 4.2.4)
......
8.3.0.pre-ee 8.4.0.pre-ee
...@@ -76,7 +76,7 @@ ...@@ -76,7 +76,7 @@
.cover-block { .cover-block {
text-align: center; text-align: center;
background: #f7f8fa; background: $background-color;
margin: -$gl-padding; margin: -$gl-padding;
margin-bottom: 0; margin-bottom: 0;
padding: 44px $gl-padding; padding: 44px $gl-padding;
......
...@@ -5,7 +5,7 @@ html { ...@@ -5,7 +5,7 @@ html {
} }
body { body {
background-color: #EAEBEC !important; background-color: #F3F3F3 !important;
&.navless { &.navless {
background-color: white !important; background-color: white !important;
......
...@@ -123,7 +123,6 @@ ...@@ -123,7 +123,6 @@
padding: 0; padding: 0;
margin: 0; margin: 0;
list-style: none; list-style: none;
margin-top: 5px;
height: 56px; height: 56px;
li { li {
...@@ -131,9 +130,9 @@ ...@@ -131,9 +130,9 @@
a { a {
padding: 14px; padding: 14px;
font-size: 17px; font-size: 15px;
line-height: 28px; line-height: 28px;
color: #7f8fa4; color: #959494;
border-bottom: 2px solid transparent; border-bottom: 2px solid transparent;
&:hover, &:active, &:focus { &:hover, &:active, &:focus {
...@@ -143,8 +142,8 @@ ...@@ -143,8 +142,8 @@
} }
&.active a { &.active a {
color: #4c4e54; color: #616060;
border-bottom: 2px solid #1cacfc; border-bottom: 2px solid #4688f1;
} }
.badge { .badge {
......
$hover: #FFFAF1; $hover: #faf9f9;
$gl-text-color: #54565B; $gl-text-color: #54565B;
$gl-text-green: #4A2; $gl-text-green: #4A2;
$gl-text-red: #D12F19; $gl-text-red: #D12F19;
$gl-text-orange: #D90; $gl-text-orange: #D90;
$gl-header-color: #4c4e54; $gl-header-color: #323232;
$gl-link-color: #333c48; $gl-link-color: #333c48;
$md-text-color: #444; $md-text-color: #444;
$md-link-color: #3084bb; $md-link-color: #3084bb;
...@@ -15,13 +15,14 @@ $sidebar_width: 230px; ...@@ -15,13 +15,14 @@ $sidebar_width: 230px;
$avatar_radius: 50%; $avatar_radius: 50%;
$code_font_size: 13px; $code_font_size: 13px;
$code_line_height: 1.5; $code_line_height: 1.5;
$border-color: #dce0e6; $border-color: #efeff1;
$table-border-color: #eef0f2; $table-border-color: #eef0f2;
$background-color: #F7F8FA; $background-color: #faf9f9;
$header-height: 58px; $header-height: 58px;
$fixed-layout-width: 1280px; $fixed-layout-width: 1280px;
$gl-gray: #7f8fa4; $gl-gray: #5a5a5a;
$gl-padding: 16px; $gl-padding: 16px;
$gl-padding-top:10px;
$gl-avatar-size: 46px; $gl-avatar-size: 46px;
/* /*
...@@ -29,12 +30,12 @@ $gl-avatar-size: 46px; ...@@ -29,12 +30,12 @@ $gl-avatar-size: 46px;
*/ */
$white-light: #FFFFFF; $white-light: #FFFFFF;
$white-normal: #DCE0E5; $white-normal: #ededed;
$white-dark: #E4E7ED; $white-dark: #ededed;
$gray-light: #F0F2F5; $gray-light: #f7f7f7;
$gray-normal: #DCE0E5; $gray-normal: #ededed;
$gray-dark: #E4E7ED; $gray-dark: #ededed;
$green-light: #31AF64; $green-light: #31AF64;
$green-normal: #2FAA60; $green-normal: #2FAA60;
...@@ -52,11 +53,11 @@ $red-light: #F43263; ...@@ -52,11 +53,11 @@ $red-light: #F43263;
$red-normal: #E52C5A; $red-normal: #E52C5A;
$red-dark: #D22852; $red-dark: #D22852;
$border-white-light: #E3E7EC; $border-white-light: #F1F2F4;
$border-white-normal: #D6DAE2; $border-white-normal: #D6DAE2;
$border-white-dark: #C6CACF; $border-white-dark: #C6CACF;
$border-gray-light: #DCE0E5; $border-gray-light: #d1d1d1;
$border-gray-normal: #D6DAE2; $border-gray-normal: #D6DAE2;
$border-gray-dark: #C6CACF; $border-gray-dark: #C6CACF;
...@@ -76,6 +77,8 @@ $border-red-light: #E52C5A; ...@@ -76,6 +77,8 @@ $border-red-light: #E52C5A;
$border-red-normal: #D22852; $border-red-normal: #D22852;
$border-red-dark: #CA264F; $border-red-dark: #CA264F;
/* header */
$light-grey-header: #faf9f9;
/* /*
* State colors: * State colors:
......
class Admin::IdentitiesController < Admin::ApplicationController class Admin::IdentitiesController < Admin::ApplicationController
before_action :user before_action :user
before_action :identity, except: :index before_action :identity, except: [:index, :new, :create]
def new
@identity = Identity.new
end
def create
@identity = Identity.new(identity_params)
@identity.user_id = user.id
if @identity.save
redirect_to admin_user_identities_path(@user), notice: 'User identity was successfully created.'
else
render :new
end
end
def index def index
@identities = @user.identities @identities = @user.identities
......
...@@ -10,6 +10,7 @@ class ApplicationController < ActionController::Base ...@@ -10,6 +10,7 @@ class ApplicationController < ActionController::Base
before_action :authenticate_user_from_token! before_action :authenticate_user_from_token!
before_action :authenticate_user! before_action :authenticate_user!
before_action :validate_user_service_ticket!
before_action :reject_blocked! before_action :reject_blocked!
before_action :check_password_expiration before_action :check_password_expiration
before_action :ldap_security_check before_action :ldap_security_check
...@@ -202,6 +203,20 @@ class ApplicationController < ActionController::Base ...@@ -202,6 +203,20 @@ class ApplicationController < ActionController::Base
end end
end end
def validate_user_service_ticket!
return unless signed_in? && session[:service_tickets]
valid = session[:service_tickets].all? do |provider, ticket|
Gitlab::OAuth::Session.valid?(provider, ticket)
end
unless valid
session[:service_tickets] = nil
sign_out current_user
redirect_to new_user_session_path
end
end
def check_password_expiration def check_password_expiration
if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && !current_user.ldap_user? if current_user && current_user.password_expires_at && current_user.password_expires_at < Time.now && !current_user.ldap_user?
redirect_to new_profile_password_path and return redirect_to new_profile_password_path and return
......
class OmniauthCallbacksController < Devise::OmniauthCallbacksController class OmniauthCallbacksController < Devise::OmniauthCallbacksController
include AuthenticatesWithTwoFactor include AuthenticatesWithTwoFactor
protect_from_forgery except: [:kerberos, :saml] protect_from_forgery except: [:kerberos, :saml, :cas3]
Gitlab.config.omniauth.providers.each do |provider| Gitlab.config.omniauth.providers.each do |provider|
define_method provider['name'] do define_method provider['name'] do
...@@ -47,6 +47,14 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController ...@@ -47,6 +47,14 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
render 'errors/omniauth_error', layout: "errors", status: 422 render 'errors/omniauth_error', layout: "errors", status: 422
end end
def cas3
ticket = params['ticket']
if ticket
handle_service_ticket oauth['provider'], ticket
end
handle_omniauth
end
private private
def handle_omniauth def handle_omniauth
...@@ -89,6 +97,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController ...@@ -89,6 +97,12 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
redirect_to new_user_session_path redirect_to new_user_session_path
end end
def handle_service_ticket provider, ticket
Gitlab::OAuth::Session.create provider, ticket
session[:service_tickets] ||= {}
session[:service_tickets][provider] = ticket
end
def oauth def oauth
@oauth ||= request.env['omniauth.auth'] @oauth ||= request.env['omniauth.auth']
end end
......
...@@ -9,7 +9,7 @@ class Projects::ServicesController < Projects::ApplicationController ...@@ -9,7 +9,7 @@ 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, :build_events, :notify_only_broken_builds, :add_pusher, :jira_issue_transition_id, :build_events, :notify_only_broken_builds, :add_pusher,
:notify, :color, :notify, :color,
:server_host, :server_port, :default_irc_uri, :enable_ssl_verification, :server_host, :server_port, :default_irc_uri, :enable_ssl_verification, :jira_issue_transition_id,
:multiproject_enabled, :pass_unstable, :multiproject_enabled, :pass_unstable,
:jenkins_url, :project_name] :jenkins_url, :project_name]
......
...@@ -28,6 +28,8 @@ module MergeRequestsHelper ...@@ -28,6 +28,8 @@ module MergeRequestsHelper
def ci_build_details_path(merge_request) def ci_build_details_path(merge_request)
build_url = merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha, merge_request.source_branch) build_url = merge_request.source_project.ci_service.build_page(merge_request.last_commit.sha, merge_request.source_branch)
return nil unless build_url
parsed_url = URI.parse(build_url) parsed_url = URI.parse(build_url)
unless parsed_url.userinfo.blank? unless parsed_url.userinfo.blank?
......
...@@ -105,6 +105,14 @@ module ProjectsHelper ...@@ -105,6 +105,14 @@ module ProjectsHelper
end end
end end
def user_max_access_in_project(user_id, project)
level = project.team.max_member_access(user_id)
if level
Gitlab::Access.options_with_owner.key(level)
end
end
private private
def get_project_nav_tabs(project, current_user) def get_project_nav_tabs(project, current_user)
...@@ -290,14 +298,6 @@ module ProjectsHelper ...@@ -290,14 +298,6 @@ module ProjectsHelper
end end
end end
def user_max_access_in_project(user, project)
level = project.team.max_member_access(user)
if level
Gitlab::Access.options_with_owner.key(level)
end
end
def leave_project_message(project) def leave_project_message(project)
"Are you sure you want to leave \"#{project.name}\" project?" "Are you sure you want to leave \"#{project.name}\" project?"
end end
......
...@@ -135,6 +135,20 @@ module Ci ...@@ -135,6 +135,20 @@ module Ci
predefined_variables + yaml_variables + project_variables + trigger_variables predefined_variables + yaml_variables + project_variables + trigger_variables
end end
def merge_request
merge_requests = MergeRequest.includes(:merge_request_diff)
.where(source_branch: ref, source_project_id: commit.gl_project_id)
.reorder(iid: :asc)
merge_requests.find do |merge_request|
merge_request.commits.any? { |ci| ci.id == commit.sha }
end
end
def project
commit.project
end
def project_id def project_id
gl_project_id gl_project_id
end end
...@@ -166,7 +180,8 @@ module Ci ...@@ -166,7 +180,8 @@ module Ci
def extract_coverage(text, regex) def extract_coverage(text, regex)
begin begin
matches = text.gsub(Regexp.new(regex)).to_a.last matches = text.scan(Regexp.new(regex)).last
matches = matches.last if matches.kind_of?(Array)
coverage = matches.gsub(/\d+(\.\d+)?/).first coverage = matches.gsub(/\d+(\.\d+)?/).first
if coverage.present? if coverage.present?
......
...@@ -218,16 +218,6 @@ module Ci ...@@ -218,16 +218,6 @@ module Ci
update!(committed_at: DateTime.now) update!(committed_at: DateTime.now)
end end
##
# This method checks if build status should be displayed.
#
# Build status should be available only if builds are enabled
# on project level and `.gitlab-ci.yml` file is present.
#
def show_build_status?
project.builds_enabled? && ci_yaml_file
end
private private
def save_yaml_error(error) def save_yaml_error(error)
......
...@@ -37,7 +37,7 @@ module Participable ...@@ -37,7 +37,7 @@ module Participable
# Be aware that this method makes a lot of sql queries. # Be aware that this method makes a lot of sql queries.
# Save result into variable if you are going to reuse it inside same request # Save result into variable if you are going to reuse it inside same request
def participants(current_user = self.author, load_lazy_references: true) def participants(current_user = self.author)
participants = participants =
Gitlab::ReferenceExtractor.lazily do Gitlab::ReferenceExtractor.lazily do
self.class.participant_attrs.flat_map do |attr| self.class.participant_attrs.flat_map do |attr|
......
...@@ -87,7 +87,7 @@ class Issue < ActiveRecord::Base ...@@ -87,7 +87,7 @@ class Issue < ActiveRecord::Base
def referenced_merge_requests def referenced_merge_requests
Gitlab::ReferenceExtractor.lazily do Gitlab::ReferenceExtractor.lazily do
[self, *notes].flat_map do |note| [self, *notes].flat_map do |note|
note.all_references(load_lazy_references: false).merge_requests note.all_references.merge_requests
end end
end.sort_by(&:iid) end.sort_by(&:iid)
end end
......
...@@ -338,7 +338,7 @@ class MergeRequest < ActiveRecord::Base ...@@ -338,7 +338,7 @@ class MergeRequest < ActiveRecord::Base
issues = commits.flat_map { |c| c.closes_issues(current_user) } issues = commits.flat_map { |c| c.closes_issues(current_user) }
issues.push(*Gitlab::ClosingIssueExtractor.new(project, current_user). issues.push(*Gitlab::ClosingIssueExtractor.new(project, current_user).
closed_by_message(description)) closed_by_message(description))
issues.uniq issues.uniq(&:id)
else else
[] []
end end
......
...@@ -18,6 +18,11 @@ ...@@ -18,6 +18,11 @@
# note_events :boolean default(TRUE), not null # note_events :boolean default(TRUE), not null
# #
# TODO(ayufan): The GitLabCiService is deprecated and the type should be removed when the database entries are removed
class GitlabCiService < CiService class GitlabCiService < CiService
# this is no longer used # We override the active accessor to always make GitLabCiService disabled
# Otherwise the GitLabCiService can be picked, but should never be since it's deprecated
def active
false
end
end end
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
# bio :string(255) # bio :string(255)
# failed_attempts :integer default(0) # failed_attempts :integer default(0)
# locked_at :datetime # locked_at :datetime
# unlock_token :string(255)
# username :string(255) # username :string(255)
# can_create_group :boolean default(TRUE), not null # can_create_group :boolean default(TRUE), not null
# can_create_team :boolean default(TRUE), not null # can_create_team :boolean default(TRUE), not null
......
...@@ -16,9 +16,23 @@ class CreateCommitBuildsService ...@@ -16,9 +16,23 @@ class CreateCommitBuildsService
return false return false
end end
tag = Gitlab::Git.tag_ref?(origin_ref) commit = project.ci_commit(sha)
commit = project.ensure_ci_commit(sha) unless commit
commit = project.ci_commits.new(sha: sha)
# Skip creating ci_commit when no gitlab-ci.yml is found
unless commit.ci_yaml_file
return false
end
# Create a new ci_commit
commit.save!
end
# Skip creating builds for commits that have [ci skip]
unless commit.skip_ci? unless commit.skip_ci?
# Create builds for commit
tag = Gitlab::Git.tag_ref?(origin_ref)
commit.update_committed! commit.update_committed!
commit.create_builds(ref, tag, user) commit.create_builds(ref, tag, user)
end end
......
...@@ -248,6 +248,7 @@ class SystemNoteService ...@@ -248,6 +248,7 @@ class SystemNoteService
end end
end end
def self.cross_reference?(note_text) def self.cross_reference?(note_text)
note_text.start_with?(cross_reference_note_prefix) note_text.start_with?(cross_reference_note_prefix)
end end
......
...@@ -79,6 +79,10 @@ ...@@ -79,6 +79,10 @@
GitLab API GitLab API
%span.pull-right %span.pull-right
= API::API::version = API::API::version
%p
Git
%span.pull-right
= Gitlab::Git.version
%p %p
Ruby Ruby
%span.pull-right %span.pull-right
......
- page_title "Identities", @user.name, "Users" - page_title "Identities", @user.name, "Users"
= render 'admin/users/head' = render 'admin/users/head'
= link_to 'New Identity', new_admin_user_identity_path, class: 'pull-right btn btn-new'
- if @identities.present? - if @identities.present?
.table-holder .table-holder
%table.table %table.table
......
- page_title "New Identity"
%h3.page-title New identity
%hr
= render 'form'
<p>Hello <%= @resource.email %>!</p>
<p>Your account has been locked due to an excessive amount of unsuccessful sign in attempts.</p>
<p>Click the link below to unlock your account:</p>
<p><%= link_to 'Unlock your account', unlock_url(@resource, unlock_token: @token) %></p>
%p
Hello #{@resource.name}!
%p
Your GitLab account has been locked due to an excessive amount of unsuccessful
sign in attempts. Your account will automatically unlock in
= time_ago_in_words(Devise.unlock_in.from_now)
or you may click the link below to unlock now.
%p= link_to 'Unlock your account', unlock_url(@resource, unlock_token: @token)
<h2>Resend unlock instructions</h2>
<%= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f| %>
<%= devise_error_messages! %>
<div><%= f.label :email %><br />
<%= f.email_field :email %></div>
<div><%= f.submit "Resend unlock instructions" %></div>
<% end %>
<%= render partial: "devise/shared/links" %>
.login-box
.login-heading
%h3 Resend unlock email
.login-body
= form_for(resource, as: resource_name, url: unlock_path(resource_name), html: { method: :post }) do |f|
.devise-errors
= devise_error_messages!
.clearfix.append-bottom-20
= f.email_field :email, class: 'form-control', placeholder: 'Email', autofocus: 'autofocus', autocapitalize: 'off', autocorrect: 'off'
.clearfix
= f.submit 'Resend unlock instructions', class: 'btn btn-success'
.clearfix.prepend-top-20
= render 'devise/shared/sign_in_link'
.panel.panel-default.projects-list-holder .projects-list-holder
.panel-heading.clearfix .projects-search-form
.input-group .input-group
= search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false
- if can? current_user, :create_projects, @group - if can? current_user, :create_projects, @group
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
- if current_user - if current_user
= auto_discovery_link_tag(:atom, group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} activity") = auto_discovery_link_tag(:atom, group_url(@group, format: :atom, private_token: current_user.private_token), title: "#{@group.name} activity")
<<<<<<< HEAD
.dashboard .dashboard
.header-with-avatar.clearfix .header-with-avatar.clearfix
= image_tag group_icon(@group), class: "avatar group-avatar s90" = image_tag group_icon(@group), class: "avatar group-avatar s90"
...@@ -41,3 +42,49 @@ ...@@ -41,3 +42,49 @@
- else - else
%p %p
This group does not have public projects This group does not have public projects
=======
.cover-block
.avatar-holder
= link_to group_icon(@group), target: '_blank' do
= image_tag group_icon(@group), class: "avatar group-avatar s90"
.cover-title
= @group.name
.cover-desc.username
@#{@group.path}
- if @group.description.present?
.cover-desc.description
= markdown(@group.description, pipeline: :description)
- if can?(current_user, :read_group, @group)
%ul.center-top-menu.no-top
%li.active
= link_to "#activity", 'data-toggle' => 'tab' do
Activity
- if @projects.present?
%li
= link_to "#projects", 'data-toggle' => 'tab' do
Projects
.tab-content
.tab-pane.active#activity
.gray-content-block.activity-filter-block
- if current_user
= render "events/event_last_push", event: @last_push
.pull-right
= link_to group_path(@group, { format: :atom, private_token: current_user.private_token }), title: "Feed", class: 'btn rss-btn' do
%i.fa.fa-rss
= render 'shared/event_filter'
.content_list
= spinner
.tab-pane#projects
= render "projects", projects: @projects
- else
%p
This group does not have public projects
>>>>>>> master
...@@ -7,6 +7,10 @@ ...@@ -7,6 +7,10 @@
%strong.monospace= link_to @build.commit.short_sha, ci_status_path(@build.commit) %strong.monospace= link_to @build.commit.short_sha, ci_status_path(@build.commit)
from from
= link_to @build.ref, namespace_project_commits_path(@project.namespace, @project, @build.ref) = link_to @build.ref, namespace_project_commits_path(@project.namespace, @project, @build.ref)
- merge_request = @build.merge_request
- if merge_request
via
= link_to "merge request ##{merge_request.iid}", merge_request_path(merge_request)
#up-build-trace #up-build-trace
- if @commit.matrix_for_ref?(@build.ref) - if @commit.matrix_for_ref?(@build.ref)
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
- @commit.parents.each do |parent| - @commit.parents.each do |parent|
= link_to parent.short_id, namespace_project_commit_path(@project.namespace, @project, parent), class: "monospace" = link_to parent.short_id, namespace_project_commit_path(@project.namespace, @project, parent), class: "monospace"
- if @ci_commit && @ci_commit.show_build_status? - if @ci_commit
.pull-right .pull-right
= link_to ci_status_path(@ci_commit), class: "ci-status ci-#{@ci_commit.status}" do = link_to ci_status_path(@ci_commit), class: "ci-status ci-#{@ci_commit.status}" do
= ci_status_icon(@ci_commit) = ci_status_icon(@ci_commit)
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
%a.text-expander.js-toggle-button ... %a.text-expander.js-toggle-button ...
.pull-right .pull-right
- if ci_commit && ci_commit.show_build_status? - if ci_commit
= render_ci_status(ci_commit) = render_ci_status(ci_commit)
&nbsp; &nbsp;
= clipboard_button(clipboard_text: commit.id) = clipboard_button(clipboard_text: commit.id)
......
...@@ -15,9 +15,10 @@ ...@@ -15,9 +15,10 @@
%span.merge-request-info %span.merge-request-info
%strong %strong
= link_to_gfm merge_request.title, merge_request_path(merge_request), class: "row_title" = link_to_gfm merge_request.title, merge_request_path(merge_request), class: "row_title"
in - unless @issue.project.id == merge_request.target_project.id
- project = merge_request.target_project in
= link_to project.name_with_namespace, namespace_project_path(project.namespace, project) - project = merge_request.target_project
= link_to project.name_with_namespace, namespace_project_path(project.namespace, project)
%span.merge-request-status.prepend-left-10 %span.merge-request-status.prepend-left-10
- if merge_request.merged? - if merge_request.merged?
MERGED MERGED
......
...@@ -17,9 +17,9 @@ ...@@ -17,9 +17,9 @@
.issue-btn-group.pull-right .issue-btn-group.pull-right
- if can?(current_user, :update_merge_request, @merge_request) - if can?(current_user, :update_merge_request, @merge_request)
- if @merge_request.open? - if @merge_request.open?
= link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, class: "btn btn-grouped btn-close", title: "Close merge request" = link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, class: 'btn btn-grouped btn-close', title: 'Close merge request'
= link_to edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: "btn btn-grouped issuable-edit", id: "edit_merge_request" do = link_to edit_namespace_project_merge_request_path(@project.namespace, @project, @merge_request), class: 'btn btn-grouped issuable-edit', id: 'edit_merge_request' do
%i.fa.fa-pencil-square-o %i.fa.fa-pencil-square-o
Edit Edit
- if @merge_request.closed? - if @merge_request.closed?
= link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "btn btn-grouped btn-reopen reopen-mr-link", title: "Close merge request" = link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: 'btn btn-grouped btn-reopen reopen-mr-link', title: 'Reopen merge request'
...@@ -8,19 +8,15 @@ ...@@ -8,19 +8,15 @@
#{time_ago_with_tooltip(@merge_request.merge_event.created_at)} #{time_ago_with_tooltip(@merge_request.merge_event.created_at)}
%div %div
- if !@merge_request.source_branch_exists? || (params[:delete_source] == 'true') - if !@merge_request.source_branch_exists? || (params[:delete_source] == 'true')
= succeed '.' do The changes were merged into
The changes were merged into #{link_to @merge_request.target_branch, namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch"}.
= link_to namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch" do
= @merge_request.target_branch
The source branch has been removed. The source branch has been removed.
- elsif @merge_request.can_remove_source_branch?(current_user) - elsif @merge_request.can_remove_source_branch?(current_user)
.remove_source_branch_widget .remove_source_branch_widget
%p %p
= succeed '.' do The changes were merged into
The changes were merged into #{link_to @merge_request.target_branch, namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch"}.
= link_to namespace_project_commits_path(@project.namespace, @project, @merge_request.target_branch), class: "label-branch" do
= @merge_request.target_branch
You can remove the source branch now. You can remove the source branch now.
= link_to namespace_project_branch_path(@merge_request.source_project.namespace, @merge_request.source_project, @merge_request.source_branch), remote: true, method: :delete, class: "btn btn-primary btn-sm remove_source_branch" do = link_to namespace_project_branch_path(@merge_request.source_project.namespace, @merge_request.source_project, @merge_request.source_branch), remote: true, method: :delete, class: "btn btn-primary btn-sm remove_source_branch" do
%i.fa.fa-times %i.fa.fa-times
......
...@@ -71,7 +71,7 @@ ...@@ -71,7 +71,7 @@
= render default_project_view = render default_project_view
- if current_user - if current_user
- access = user_max_access_in_project(current_user, @project) - access = user_max_access_in_project(current_user.id, @project)
- if access - if access
.prepend-top-20.project-footer .prepend-top-20.project-footer
.gray-content-block.footer-block.center .gray-content-block.footer-block.center
......
...@@ -380,6 +380,15 @@ production: &base ...@@ -380,6 +380,15 @@ production: &base
# arguments, followed by optional 'args' which can be either a hash or an array. # arguments, followed by optional 'args' which can be either a hash or an array.
# Documentation for this is available at http://doc.gitlab.com/ce/integration/omniauth.html # Documentation for this is available at http://doc.gitlab.com/ce/integration/omniauth.html
providers: providers:
# See omniauth-cas3 for more configuration details
# - { name: 'cas3',
# label: 'cas3',
# args: {
# url: 'https://sso.example.com',
# disable_ssl_verification: false,
# login_url: '/cas/login',
# service_validate_url: '/cas/p3/serviceValidate',
# logout_url: '/cas/logout'} }
# - { name: 'github', # - { name: 'github',
# app_id: 'YOUR_APP_ID', # app_id: 'YOUR_APP_ID',
# app_secret: 'YOUR_APP_SECRET', # app_secret: 'YOUR_APP_SECRET',
...@@ -418,6 +427,10 @@ production: &base ...@@ -418,6 +427,10 @@ production: &base
# application_name: 'YOUR_APP_NAME', # application_name: 'YOUR_APP_NAME',
# application_password: 'YOUR_APP_PASSWORD' } } # application_password: 'YOUR_APP_PASSWORD' } }
# SSO maximum session duration in seconds. Defaults to CAS default of 8 hours.
# cas3:
# session_duration: 28800
# Shared file storage settings # Shared file storage settings
shared: shared:
# path: /mnt/gitlab # Default: shared # path: /mnt/gitlab # Default: shared
......
...@@ -164,6 +164,10 @@ Settings.omniauth['block_auto_created_users'] = true if Settings.omniauth['block ...@@ -164,6 +164,10 @@ Settings.omniauth['block_auto_created_users'] = true if Settings.omniauth['block
Settings.omniauth['auto_link_ldap_user'] = false if Settings.omniauth['auto_link_ldap_user'].nil? Settings.omniauth['auto_link_ldap_user'] = false if Settings.omniauth['auto_link_ldap_user'].nil?
Settings.omniauth['providers'] ||= [] Settings.omniauth['providers'] ||= []
Settings.omniauth['cas3'] ||= Settingslogic.new({})
Settings.omniauth.cas3['session_duration'] ||= 8.hours
Settings.omniauth['session_tickets'] ||= Settingslogic.new({})
Settings.omniauth.session_tickets['cas3'] = 'ticket'
# Fill out omniauth-gitlab settings. It is needed for easy set up GHE or GH by just specifying url. # Fill out omniauth-gitlab settings. It is needed for easy set up GHE or GH by just specifying url.
......
...@@ -121,14 +121,14 @@ Devise.setup do |config| ...@@ -121,14 +121,14 @@ Devise.setup do |config|
config.lock_strategy = :failed_attempts config.lock_strategy = :failed_attempts
# Defines which key will be used when locking and unlocking an account # Defines which key will be used when locking and unlocking an account
# config.unlock_keys = [ :email ] config.unlock_keys = [ :email ]
# Defines which strategy will be used to unlock an account. # Defines which strategy will be used to unlock an account.
# :email = Sends an unlock link to the user email # :email = Sends an unlock link to the user email
# :time = Re-enables login after a certain amount of time (see :unlock_in below) # :time = Re-enables login after a certain amount of time (see :unlock_in below)
# :both = Enables both strategies # :both = Enables both strategies
# :none = No unlock strategy. You should handle unlocking by yourself. # :none = No unlock strategy. You should handle unlocking by yourself.
config.unlock_strategy = :time config.unlock_strategy = :both
# Number of authentication tries before locking an account if lock_strategy # Number of authentication tries before locking an account if lock_strategy
# is failed attempts. # is failed attempts.
...@@ -241,6 +241,16 @@ Devise.setup do |config| ...@@ -241,6 +241,16 @@ Devise.setup do |config|
# An Array from the configuration will be expanded. # An Array from the configuration will be expanded.
provider_arguments.concat provider['args'] provider_arguments.concat provider['args']
when Hash when Hash
# Add procs for handling SLO
if provider['name'] == 'cas3'
provider['args'][:on_single_sign_out] = lambda do |request|
ticket = request.params[:session_index]
raise "Service Ticket not found." unless Gitlab::OAuth::Session.valid?(:cas3, ticket)
Gitlab::OAuth::Session.destroy(:cas3, ticket)
true
end
end
# A Hash from the configuration will be passed as is. # A Hash from the configuration will be passed as is.
provider_arguments << provider['args'].symbolize_keys provider_arguments << provider['args'].symbolize_keys
end end
......
...@@ -193,7 +193,7 @@ Rails.application.routes.draw do ...@@ -193,7 +193,7 @@ Rails.application.routes.draw do
namespace :admin do namespace :admin do
resources :users, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do resources :users, constraints: { id: /[a-zA-Z.\/0-9_\-]+/ } do
resources :keys, only: [:show, :destroy] resources :keys, only: [:show, :destroy]
resources :identities, only: [:index, :edit, :update, :destroy] resources :identities, except: [:show]
delete 'stop_impersonation' => 'impersonation#destroy', on: :collection delete 'stop_impersonation' => 'impersonation#destroy', on: :collection
......
class AddUnlockTokenToUser < ActiveRecord::Migration
def change
add_column :users, :unlock_token, :string
end
end
This diff is collapsed.
...@@ -27,7 +27,6 @@ The API_TOKEN will take the Secure Variable value: `SECURE`. ...@@ -27,7 +27,6 @@ The API_TOKEN will take the Secure Variable value: `SECURE`.
| **CI_BUILD_TAG** | 0.5 | The commit tag name. Present only when building tags. | | **CI_BUILD_TAG** | 0.5 | The commit tag name. Present only when building tags. |
| **CI_BUILD_NAME** | 0.5 | The name of the build as defined in `.gitlab-ci.yml` | | **CI_BUILD_NAME** | 0.5 | The name of the build as defined in `.gitlab-ci.yml` |
| **CI_BUILD_STAGE** | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` | | **CI_BUILD_STAGE** | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` |
| **CI_BUILD_BEFORE_SHA** | all | The first commit that were included in push request |
| **CI_BUILD_REF_NAME** | all | The branch or tag name for which project is built | | **CI_BUILD_REF_NAME** | all | The branch or tag name for which project is built |
| **CI_BUILD_ID** | all | The unique id of the current build that GitLab CI uses internally | | **CI_BUILD_ID** | all | The unique id of the current build that GitLab CI uses internally |
| **CI_BUILD_REPO** | all | The URL to clone the Git repository | | **CI_BUILD_REPO** | all | The URL to clone the Git repository |
...@@ -40,7 +39,6 @@ The API_TOKEN will take the Secure Variable value: `SECURE`. ...@@ -40,7 +39,6 @@ The API_TOKEN will take the Secure Variable value: `SECURE`.
Example values: Example values:
```bash ```bash
export CI_BUILD_BEFORE_SHA="9df57456fa9de2a6d335ca5edf9750ed812b9df0"
export CI_BUILD_ID="50" export CI_BUILD_ID="50"
export CI_BUILD_REF="1ecfd275763eff1d6b4844ea3168962458c9f27a" export CI_BUILD_REF="1ecfd275763eff1d6b4844ea3168962458c9f27a"
export CI_BUILD_REF_NAME="master" export CI_BUILD_REF_NAME="master"
......
...@@ -336,7 +336,8 @@ The above script will: ...@@ -336,7 +336,8 @@ The above script will:
### artifacts ### artifacts
_**Note:** Introduced in GitLab Runner v0.7.0._ _**Note:** Introduced in GitLab Runner v0.7.0. Also, the Windows shell executor
does not currently support artifact uploads._
`artifacts` is used to specify list of files and directories which should be `artifacts` is used to specify list of files and directories which should be
attached to build after success. Below are some examples. attached to build after success. Below are some examples.
......
...@@ -5,11 +5,12 @@ GitLab integrates with multiple third-party services to allow external issue tra ...@@ -5,11 +5,12 @@ GitLab integrates with multiple third-party services to allow external issue tra
See the documentation below for details on how to configure these services. See the documentation below for details on how to configure these services.
- [Jira](jira.md) Integrate with the JIRA issue tracker - [Jira](jira.md) Integrate with the JIRA issue tracker
- [External issue tracker](external-issue-tracker.md) Redmine, bugzilla, etc. - [External issue tracker](external-issue-tracker.md) Redmine, JIRA, etc.
- [LDAP](ldap.md) Set up sign in via LDAP - [LDAP](ldap.md) Set up sign in via LDAP
- [Jenkins](jenkins.md) Integrate with the Jenkins CI - [Jenkins](jenkins.md) Integrate with the Jenkins CI
- [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab, and Google via OAuth. - [OmniAuth](omniauth.md) Sign in via Twitter, GitHub, GitLab, and Google via OAuth.
- [SAML](saml.md) Configure GitLab as a SAML 2.0 Service Provider - [SAML](saml.md) Configure GitLab as a SAML 2.0 Service Provider
- [CAS](cas.md) Configure GitLab to sign in using CAS
- [Slack](slack.md) Integrate with the Slack chat service - [Slack](slack.md) Integrate with the Slack chat service
- [Kerberos](kerberos.md) Integrate with Kerberos - [Kerberos](kerberos.md) Integrate with Kerberos
- [OAuth2 provider](oauth_provider.md) OAuth2 application creation - [OAuth2 provider](oauth_provider.md) OAuth2 application creation
......
# CAS OmniAuth Provider
To enable the CAS OmniAuth provider you must register your application with your CAS instance. This requires the service URL GitLab will supply to CAS. It should be something like: `https://gitlab.example.com:443/users/auth/cas3/callback?url`. By default handling for SLO is enabled, you only need to configure CAS for backchannel logout.
1. On your GitLab server, open the configuration file.
For omnibus package:
```sh
sudo editor /etc/gitlab/gitlab.rb
```
For installations from source:
```sh
cd /home/git/gitlab
sudo -u git -H editor config/gitlab.yml
```
1. See [Initial OmniAuth Configuration](omniauth.md#initial-omniauth-configuration) for initial settings.
1. Add the provider configuration:
For omnibus package:
```ruby
gitlab_rails['omniauth_providers'] = [
{
name: "cas3",
label: "cas",
args: {
url: 'CAS_SERVER',
login_url: '/CAS_PATH/login',
service_validate_url: '/CAS_PATH/p3/serviceValidate',
logout_url: '/CAS_PATH/logout'} }
}
}
]
```
For installations from source:
```
- { name: 'cas3',
label: 'cas',
args: {
url: 'CAS_SERVER',
login_url: '/CAS_PATH/login',
service_validate_url: '/CAS_PATH/p3/serviceValidate',
logout_url: '/CAS_PATH/logout'} }
```
1. Change 'CAS_PATH' to the root of your CAS instance (ie. `cas`).
1. If your CAS instance does not use default TGC lifetimes, update the `cas3.session_duration` to at least the current TGC maximum lifetime. To explicitly disable SLO, regardless of CAS settings, set this to 0.
1. Save the configuration file.
1. Restart GitLab for the changes to take effect.
On the sign in page there should now be a CAS tab in the sign in form.
...@@ -20,6 +20,10 @@ module Gitlab ...@@ -20,6 +20,10 @@ module Gitlab
def blank_ref?(ref) def blank_ref?(ref)
ref == BLANK_SHA ref == BLANK_SHA
end end
def version
Gitlab::VersionInfo.parse(Gitlab::Popen.popen(%W(#{Gitlab.config.git.bin_path} --version)).first)
end
end end
end end
end end
module Gitlab
module OAuth
module Session
def self.create(provider, ticket)
Rails.cache.write("gitlab:#{provider}:#{ticket}", ticket, expires_in: Gitlab.config.omniauth.cas3.session_duration)
end
def self.destroy(provider, ticket)
Rails.cache.delete("gitlab:#{provider}:#{ticket}")
end
def self.valid?(provider, ticket)
Rails.cache.read("gitlab:#{provider}:#{ticket}").present?
end
end
end
end
...@@ -19,30 +19,13 @@ describe 'Commits' do ...@@ -19,30 +19,13 @@ describe 'Commits' do
let!(:build) { FactoryGirl.create :ci_build, commit: commit } let!(:build) { FactoryGirl.create :ci_build, commit: commit }
describe 'Project commits' do describe 'Project commits' do
context 'builds enabled' do before do
context '.gitlab-ci.yml found' do visit namespace_project_commits_path(project.namespace, project, :master)
before do end
visit namespace_project_commits_path(project.namespace, project, :master)
end
it 'should show build status' do
page.within("//li[@id='commit-#{commit.short_sha}']") do
expect(page).to have_css(".ci-status-link")
end
end
end
context 'no .gitlab-ci.yml found' do it 'should show build status' do
before do page.within("//li[@id='commit-#{commit.short_sha}']") do
stub_ci_commit_yaml_file(nil) expect(page).to have_css(".ci-status-link")
visit namespace_project_commits_path(project.namespace, project, :master)
end
it 'should not show build status' do
page.within("//li[@id='commit-#{commit.short_sha}']") do
expect(page).to have_no_css(".ci-status-link")
end
end
end end
end end
end end
......
...@@ -70,6 +70,20 @@ feature 'Project', feature: true do ...@@ -70,6 +70,20 @@ feature 'Project', feature: true do
end end
end end
describe 'leave project link' do
let(:user) { create(:user) }
let(:project) { create(:project, namespace: user.namespace) }
before do
login_with(user)
project.team.add_user(user, Gitlab::Access::MASTER)
visit namespace_project_path(project.namespace, project)
end
it { expect(page).to have_content('You have Master access to this project.') }
it { expect(page).to have_link('Leave this project') }
end
def remove_with_confirm(button_text, confirm_with) def remove_with_confirm(button_text, confirm_with)
click_button button_text click_button button_text
fill_in 'confirm_name_input', with: confirm_with fill_in 'confirm_name_input', with: confirm_with
......
require 'spec_helper' require 'spec_helper'
describe MergeRequestsHelper do describe MergeRequestsHelper do
describe "#issues_sentence" do describe 'ci_build_details_path' do
let(:project) { create :project }
let(:merge_request) { MergeRequest.new }
let(:ci_service) { CiService.new }
let(:last_commit) { Ci::Commit.new({}) }
before do
allow(merge_request).to receive(:source_project).and_return(project)
allow(merge_request).to receive(:last_commit).and_return(last_commit)
allow(project).to receive(:ci_service).and_return(ci_service)
allow(last_commit).to receive(:sha).and_return('12d65c')
end
it 'does not include api credentials in a link' do
allow(ci_service).
to receive(:build_page).and_return("http://secretuser:secretpass@jenkins.example.com:8888/job/test1/scm/bySHA1/12d65c")
expect(helper.ci_build_details_path(merge_request)).to_not match("secret")
end
end
describe '#issues_sentence' do
subject { issues_sentence(issues) } subject { issues_sentence(issues) }
let(:issues) do let(:issues) do
[build(:issue, iid: 1), build(:issue, iid: 2), build(:issue, iid: 3)] [build(:issue, iid: 1), build(:issue, iid: 2), build(:issue, iid: 3)]
end end
it { is_expected.to eq('#1, #2, and #3') } it { is_expected.to eq('#1, #2, and #3') }
context 'for JIRA issues' do
let(:project) { create(:project) }
let(:issues) do
[
JiraIssue.new('JIRA-123', project),
JiraIssue.new('JIRA-456', project),
JiraIssue.new('FOOBAR-7890', project)
]
end
it { is_expected.to eq('FOOBAR-7890, JIRA-123, and JIRA-456') }
end
end end
describe "#format_mr_branch_names" do describe '#format_mr_branch_names' do
describe "within the same project" do describe 'within the same project' do
let(:merge_request) { create(:merge_request) } let(:merge_request) { create(:merge_request) }
subject { format_mr_branch_names(merge_request) } subject { format_mr_branch_names(merge_request) }
it { is_expected.to eq([merge_request.source_branch, merge_request.target_branch]) } it { is_expected.to eq([merge_request.source_branch, merge_request.target_branch]) }
end end
describe "within different projects" do describe 'within different projects' do
let(:project) { create(:project) } let(:project) { create(:project) }
let(:fork_project) { create(:project, forked_from_project: project) } let(:fork_project) { create(:project, forked_from_project: project) }
let(:merge_request) { create(:merge_request, source_project: fork_project, target_project: project) } let(:merge_request) { create(:merge_request, source_project: fork_project, target_project: project) }
......
...@@ -53,6 +53,16 @@ describe ProjectsHelper do ...@@ -53,6 +53,16 @@ describe ProjectsHelper do
end end
end end
describe 'user_max_access_in_project' do
let(:project) { create(:project) }
let(:user) { create(:user) }
before do
project.team.add_user(user, Gitlab::Access::MASTER)
end
it { expect(helper.user_max_access_in_project(user.id, project)).to eq('Master') }
end
describe "readme_cache_key" do describe "readme_cache_key" do
let(:project) { create(:project) } let(:project) { create(:project) }
......
...@@ -189,6 +189,12 @@ describe Ci::Build, models: true do ...@@ -189,6 +189,12 @@ describe Ci::Build, models: true do
it { is_expected.to eq(98.29) } it { is_expected.to eq(98.29) }
end end
context 'using a regex capture' do
subject { build.extract_coverage('TOTAL 9926 3489 65%', 'TOTAL\s+\d+\s+\d+\s+(\d{1,3}\%)') }
it { is_expected.to eq(65) }
end
end end
describe :variables do describe :variables do
...@@ -390,4 +396,68 @@ describe Ci::Build, models: true do ...@@ -390,4 +396,68 @@ describe Ci::Build, models: true do
it { is_expected.to include('gitlab-ci-token') } it { is_expected.to include('gitlab-ci-token') }
it { is_expected.to include(project.web_url[7..-1]) } it { is_expected.to include(project.web_url[7..-1]) }
end end
def create_mr(build, commit, factory: :merge_request, created_at: Time.now)
FactoryGirl.create(factory,
source_project_id: commit.gl_project_id,
target_project_id: commit.gl_project_id,
source_branch: build.ref,
created_at: created_at)
end
describe :merge_request do
context 'when a MR has a reference to the commit' do
before do
@merge_request = create_mr(build, commit, factory: :merge_request)
commits = [double(id: commit.sha)]
allow(@merge_request).to receive(:commits).and_return(commits)
allow(MergeRequest).to receive_message_chain(:includes, :where, :reorder).and_return([@merge_request])
end
it 'returns the single associated MR' do
expect(build.merge_request.id).to eq(@merge_request.id)
end
end
context 'when there is not a MR referencing the commit' do
it 'returns nil' do
expect(build.merge_request).to be_nil
end
end
context 'when more than one MR have a reference to the commit' do
before do
@merge_request = create_mr(build, commit, factory: :merge_request)
@merge_request.close!
@merge_request2 = create_mr(build, commit, factory: :merge_request)
commits = [double(id: commit.sha)]
allow(@merge_request).to receive(:commits).and_return(commits)
allow(@merge_request2).to receive(:commits).and_return(commits)
allow(MergeRequest).to receive_message_chain(:includes, :where, :reorder).and_return([@merge_request, @merge_request2])
end
it 'returns the first MR' do
expect(build.merge_request.id).to eq(@merge_request.id)
end
end
context 'when a Build is created after the MR' do
before do
@merge_request = create_mr(build, commit, factory: :merge_request_with_diffs)
commit2 = FactoryGirl.create :ci_commit, project: project
@build2 = FactoryGirl.create :ci_build, commit: commit2
commits = [double(id: commit.sha), double(id: commit2.sha)]
allow(@merge_request).to receive(:commits).and_return(commits)
allow(MergeRequest).to receive_message_chain(:includes, :where, :reorder).and_return([@merge_request])
end
it 'returns the current MR' do
expect(@build2.merge_request.id).to eq(@merge_request.id)
end
end
end
end end
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
# bio :string(255) # bio :string(255)
# failed_attempts :integer default(0) # failed_attempts :integer default(0)
# locked_at :datetime # locked_at :datetime
# unlock_token :string(255)
# username :string(255) # username :string(255)
# can_create_group :boolean default(TRUE), not null # can_create_group :boolean default(TRUE), not null
# can_create_team :boolean default(TRUE), not null # can_create_team :boolean default(TRUE), not null
......
...@@ -52,7 +52,7 @@ describe CreateCommitBuildsService, services: true do ...@@ -52,7 +52,7 @@ describe CreateCommitBuildsService, services: true do
end end
end end
it 'skips commits without .gitlab-ci.yml' do it 'skips creating ci_commit for refs without .gitlab-ci.yml' do
stub_ci_commit_yaml_file(nil) stub_ci_commit_yaml_file(nil)
result = service.execute(project, user, result = service.execute(project, user,
ref: 'refs/heads/0_1', ref: 'refs/heads/0_1',
...@@ -60,13 +60,11 @@ describe CreateCommitBuildsService, services: true do ...@@ -60,13 +60,11 @@ describe CreateCommitBuildsService, services: true do
after: '31das312', after: '31das312',
commits: [{ message: 'Message' }] commits: [{ message: 'Message' }]
) )
expect(result).to be_persisted expect(result).to be_falsey
expect(result.builds.any?).to be_falsey expect(Ci::Commit.count).to eq(0)
expect(result.status).to eq('skipped')
expect(result.yaml_errors).to be_nil
end end
it 'skips commits if yaml is invalid' do it 'fails commits if yaml is invalid' do
message = 'message' message = 'message'
allow_any_instance_of(Ci::Commit).to receive(:git_commit_message) { message } allow_any_instance_of(Ci::Commit).to receive(:git_commit_message) { message }
stub_ci_commit_yaml_file('invalid: file: file') stub_ci_commit_yaml_file('invalid: file: file')
...@@ -77,6 +75,7 @@ describe CreateCommitBuildsService, services: true do ...@@ -77,6 +75,7 @@ describe CreateCommitBuildsService, services: true do
after: '31das312', after: '31das312',
commits: commits commits: commits
) )
expect(commit).to be_persisted
expect(commit.builds.any?).to be false expect(commit.builds.any?).to be false
expect(commit.status).to eq('failed') expect(commit.status).to eq('failed')
expect(commit.yaml_errors).to_not be_nil expect(commit.yaml_errors).to_not be_nil
...@@ -97,6 +96,7 @@ describe CreateCommitBuildsService, services: true do ...@@ -97,6 +96,7 @@ describe CreateCommitBuildsService, services: true do
after: '31das312', after: '31das312',
commits: commits commits: commits
) )
expect(commit).to be_persisted
expect(commit.builds.any?).to be false expect(commit.builds.any?).to be false
expect(commit.status).to eq("skipped") expect(commit.status).to eq("skipped")
end end
...@@ -112,6 +112,7 @@ describe CreateCommitBuildsService, services: true do ...@@ -112,6 +112,7 @@ describe CreateCommitBuildsService, services: true do
commits: commits commits: commits
) )
expect(commit).to be_persisted
expect(commit.builds.first.name).to eq("staging") expect(commit.builds.first.name).to eq("staging")
end end
...@@ -124,6 +125,7 @@ describe CreateCommitBuildsService, services: true do ...@@ -124,6 +125,7 @@ describe CreateCommitBuildsService, services: true do
after: '31das312', after: '31das312',
commits: commits commits: commits
) )
expect(commit).to be_persisted
expect(commit.builds.any?).to be false expect(commit.builds.any?).to be false
expect(commit.status).to eq("skipped") expect(commit.status).to eq("skipped")
expect(commit.yaml_errors).to be_nil expect(commit.yaml_errors).to be_nil
...@@ -140,6 +142,7 @@ describe CreateCommitBuildsService, services: true do ...@@ -140,6 +142,7 @@ describe CreateCommitBuildsService, services: true do
after: '31das312', after: '31das312',
commits: commits commits: commits
) )
expect(commit).to be_persisted
expect(commit.builds.count(:all)).to eq(2) expect(commit.builds.count(:all)).to eq(2)
commit = service.execute(project, user, commit = service.execute(project, user,
...@@ -148,6 +151,7 @@ describe CreateCommitBuildsService, services: true do ...@@ -148,6 +151,7 @@ describe CreateCommitBuildsService, services: true do
after: '31das312', after: '31das312',
commits: commits commits: commits
) )
expect(commit).to be_persisted
expect(commit.builds.count(:all)).to eq(2) expect(commit.builds.count(:all)).to eq(2)
end end
...@@ -163,6 +167,7 @@ describe CreateCommitBuildsService, services: true do ...@@ -163,6 +167,7 @@ describe CreateCommitBuildsService, services: true do
commits: commits commits: commits
) )
expect(commit).to be_persisted
expect(commit.status).to eq("failed") expect(commit.status).to eq("failed")
expect(commit.builds.any?).to be false expect(commit.builds.any?).to be false
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