Commit 2e4a33b2 authored by Sytse Sijbrandij's avatar Sytse Sijbrandij

Merge branch 'master' of dev.gitlab.org:gitlab/gitlabhq

parents e6631c87 fbe9b00f
......@@ -39,3 +39,4 @@ public/assets/
.envrc
dump.rdb
tags
.gitlab_shell_secret
v 7.5.0
- API: Add support for Hipchat (Kevin Houdebert)
- Add time zone configuration on gitlab.yml (Sullivan Senechal)
v 7.4.0
- Refactored membership logic
- Improve error reporting on users API (Julien Bianchi)
......
......@@ -101,7 +101,11 @@ For examples of feedback on merge requests please look at already [closed merge
1. Contains functionality we think other users will benefit from too
1. Doesn't add configuration options since they complicate future changes
1. Changes after submitting the merge request should be in separate commits (no squashing). You will be asked to squash when the review is over, before merging.
1. It conforms to the following style guides
1. It conforms to the following style guides.
If your change touches a line that does not follow the style,
modify the entire line to follow it. This prevents linting tools from generating warnings.
Don't touch neighbouring lines. As an exception, automatic mass refactoring modifications
may leave style non-compliant.
## Style guides
......
7.4.0-pre
7.5.0.pre
class Activities
class @Activities
constructor: ->
Pager.init 20, true
$(".event_filter_link").bind "click", (event) =>
......@@ -27,5 +27,3 @@ class Activities
event_filters.splice index, 1
$.cookie "event_filter", event_filters.join(","), { path: '/' }
@Activities = Activities
class Admin
class @Admin
constructor: ->
$('input#user_force_random_password').on 'change', (elem) ->
elems = $('#user_password, #user_password_confirmation')
......@@ -51,5 +51,3 @@ class Admin
$('li.group_member').bind 'ajax:success', ->
Turbolinks.visit(location.href)
@Admin = Admin
class BlobView
class @BlobView
constructor: ->
# handle multi-line select
handleMultiSelect = (e) ->
......@@ -71,6 +71,3 @@ class BlobView
# Highlight the correct lines when the hash part of the URL changes
$(window).on("hashchange", highlightBlobLines)
@BlobView = BlobView
class Commit
class @Commit
constructor: ->
$('.files .diff-file').each ->
new CommitFile(this)
@Commit = Commit
class CommitFile
class @CommitFile
constructor: (file) ->
if $('.image', file).length
new ImageFile(file)
@CommitFile = CommitFile
class ImageFile
class @ImageFile
# Width where images must fits in, for 2-up this gets divided by 2
@availWidth = 900
......@@ -124,5 +124,3 @@ class ImageFile
else
img.on 'load', =>
callback.call(this, domImg.naturalWidth, domImg.naturalHeight)
@ImageFile = ImageFile
class CommitsList
class @CommitsList
@data =
ref: null
limit: 0
......@@ -53,5 +53,3 @@ class CommitsList
@disable
callback: =>
this.getOld()
this.CommitsList = CommitsList
class ConfirmDangerModal
class @ConfirmDangerModal
constructor: (form, text) ->
@form = form
$('.js-confirm-text').text(text || '')
......@@ -16,5 +16,3 @@ class ConfirmDangerModal
$('.js-confirm-danger-submit').on 'click', =>
@form.submit()
@ConfirmDangerModal = ConfirmDangerModal
class Dashboard
class @Dashboard
constructor: ->
@initSidebarTab()
......@@ -28,6 +28,3 @@ class Dashboard
# show tab from cookie
sidebar_filter = $.cookie(key)
$("#" + sidebar_filter).tab('show') if sidebar_filter
@Dashboard = Dashboard
class Diff
class @Diff
UNFOLD_COUNT = 20
constructor: ->
$(document).on('click', '.js-unfold', (event) =>
......@@ -41,6 +41,3 @@ class Diff
lines = line.children().slice(0, 2)
line_numbers = ($(l).attr('data-linenumber') for l in lines)
(parseInt(line_number) for line_number in line_numbers)
@Diff = Diff
class Flash
class @Flash
constructor: (message, type)->
flash = $(".flash-container")
flash.html("")
......@@ -10,5 +10,3 @@ class Flash
flash.click -> $(@).fadeOut()
flash.show()
@Flash = Flash
class GroupMembers
class @GroupMembers
constructor: ->
$('li.group_member').bind 'ajax:success', ->
$(this).fadeOut()
@GroupMembers = GroupMembers
$ ->
# avatar
$('.js-choose-group-avatar-button').bind "click", ->
......
class Issue
class @Issue
constructor: ->
$('.edit-issue.inline-update input[type="submit"]').hide()
$(".issue-box .inline-update").on "change", "select", ->
......@@ -15,5 +15,3 @@ class Issue
"issue"
updateTaskState
)
@Issue = Issue
class Labels
class @Labels
constructor: ->
form = $('.label-form')
@setupLabelForm(form)
......@@ -31,5 +31,3 @@ class Labels
# Notify the form, that color has changed
$('.label-form').trigger('keyup')
e.preventDefault()
@Labels = Labels
class MergeRequest
class @MergeRequest
constructor: (@opts) ->
@initContextWidget()
this.$el = $('.merge-request')
......@@ -132,5 +132,3 @@ class MergeRequest
this.$('.automerge_widget').hide()
this.$('.merge-in-progress').hide()
this.$('.automerge_widget.already_cannot_be_merged').show()
this.MergeRequest = MergeRequest
class Milestone
class @Milestone
@updateIssue: (li, issue_url, data) ->
$.ajax
type: "PUT"
......@@ -115,5 +115,3 @@ class Milestone
Milestone.updateMergeRequest(ui.item, merge_request_url, data)
).disableSelection()
@Milestone = Milestone
class Notes
class @Notes
@interval: null
constructor: (notes_url, note_ids, last_fetched_at) ->
......@@ -514,7 +514,3 @@ class Notes
else
form.find('.js-note-target-reopen').text('Reopen')
form.find('.js-note-target-close').text('Close')
@Notes = Notes
class NotesVotes
class @NotesVotes
updateVotes: ->
votes = $("#votes .votes")
notes = $("#notes-list .note .vote")
......@@ -18,5 +18,3 @@ class NotesVotes
# replace vote numbers
votes.find(".upvotes").text votes.find(".upvotes").text().replace(/\d+/, upvotes)
votes.find(".downvotes").text votes.find(".downvotes").text().replace(/\d+/, downvotes)
@NotesVotes = NotesVotes
class Project
class @Project
constructor: ->
$('.project-edit-container').on 'ajax:before', =>
$('.project-edit-container').hide()
......@@ -24,9 +24,6 @@ class Project
else
$('#project_issues_tracker_id').removeAttr('disabled')
@Project = Project
$ ->
# Git clone panel switcher
scope = $ '.git-clone-holder'
......
class ProjectImport
class @ProjectImport
constructor: ->
setTimeout ->
Turbolinks.visit(location.href)
, 5000
@ProjectImport = ProjectImport
class SearchAutocomplete
class @SearchAutocomplete
constructor: (search_autocomplete_path, project_id, project_ref) ->
project_id = '' unless project_id
project_ref = '' unless project_ref
......@@ -9,5 +9,3 @@ class SearchAutocomplete
minLength: 1
select: (event, ui) ->
location.href = ui.item.url
@SearchAutocomplete = SearchAutocomplete
class window.StatGraph
class @StatGraph
@log: {}
@get_log: ->
@log
......
class window.ContributorsStatGraph
class @ContributorsStatGraph
init: (log) ->
@parsed_log = ContributorsStatGraphUtil.parse_log(log)
@set_current_field("commits")
......
class window.ContributorsGraph
class @ContributorsGraph
MARGIN:
top: 20
right: 20
......@@ -44,7 +44,7 @@ class window.ContributorsGraph
set_data: (data) ->
@data = data
class window.ContributorsMasterGraph extends ContributorsGraph
class @ContributorsMasterGraph extends ContributorsGraph
constructor: (@data) ->
@width = $('.container').width() - 70
@height = 200
......@@ -117,7 +117,7 @@ class window.ContributorsMasterGraph extends ContributorsGraph
@svg.select("path").attr("d", @area)
@svg.select(".y.axis").call(@y_axis)
class window.ContributorsAuthorGraph extends ContributorsGraph
class @ContributorsAuthorGraph extends ContributorsGraph
constructor: (@data) ->
@width = $('.container').width()/2 - 100
@height = 200
......
class TeamMembers
class @TeamMembers
constructor: ->
$('.team-members .project-access-select').on "change", ->
$(this.form).submit()
@TeamMembers = TeamMembers
class TreeView
class @TreeView
constructor: ->
@initKeyNav()
......@@ -39,5 +39,3 @@ class TreeView
else if e.which is 13
path = $('.tree-item.selected .tree-item-file-name a').attr('href')
Turbolinks.visit(path)
@TreeView = TreeView
class Wikis
class @Wikis
constructor: ->
$('.build-new-wiki').bind "click", ->
field = $('#new_wiki_path')
......@@ -7,6 +7,3 @@ class Wikis
if(slug.length > 0)
location.href = path + "/" + slug
@Wikis = Wikis
......@@ -75,7 +75,7 @@
}
.participants {
margin-bottom: 10px;
margin-bottom: 20px;
}
.issues_bulk_update {
......
......@@ -113,30 +113,36 @@
font-size: 15px;
border-bottom: 1px solid #BBB;
color: #777;
background-color: #F5F5F5;
&.ci-success {
color: $bg_success;
border-color: $border_success;
background-color: #F1FAF1;
}
&.ci-pending {
color: #548;
border-color: #548;
background-color: #F4F1FA;
}
&.ci-running {
color: $bg_warning;
border-color: $border_warning;
background-color: #FAF5F1;
}
&.ci-failed {
color: $bg_danger;
border-color: $border_danger;
background-color: #FAF1F1;
}
&.ci-error {
color: $bg_danger;
border-color: $border_danger;
background-color: #FAF1F1;
}
}
......
......@@ -31,17 +31,11 @@ class Admin::ProjectsController < Admin::ApplicationController
protected
def project
id = params[:project_id] || params[:id]
@project = Project.find_with_namespace(id)
@project = Project.find_with_namespace(params[:id])
@project || render_404
end
def group
@group ||= project.group
end
def repository
@repository ||= project.repository
@group ||= @project.group
end
end
......@@ -7,7 +7,6 @@ class ApplicationController < ActionController::Base
before_filter :check_password_expiration
before_filter :add_abilities
before_filter :ldap_security_check
before_filter :dev_tools if Rails.env == 'development'
before_filter :default_headers
before_filter :add_gon_variables
before_filter :configure_permitted_parameters, if: :devise_controller?
......@@ -81,28 +80,31 @@ class ApplicationController < ActionController::Base
end
def project
id = params[:project_id] || params[:id]
# Redirect from
# localhost/group/project.git
# to
# localhost/group/project
#
if id =~ /\.git\Z/
redirect_to request.original_url.gsub(/\.git\Z/, '') and return
end
unless @project
id = params[:project_id] || params[:id]
# Redirect from
# localhost/group/project.git
# to
# localhost/group/project
#
if id =~ /\.git\Z/
redirect_to request.original_url.gsub(/\.git\Z/, '') and return
end
@project = Project.find_with_namespace(id)
@project = Project.find_with_namespace(id)
if @project and can?(current_user, :read_project, @project)
@project
elsif current_user.nil?
@project = nil
authenticate_user!
else
@project = nil
render_404 and return
if @project and can?(current_user, :read_project, @project)
@project
elsif current_user.nil?
@project = nil
authenticate_user!
else
@project = nil
render_404 and return
end
end
@project
end
def repository
......@@ -119,14 +121,6 @@ class ApplicationController < ActionController::Base
return access_denied! unless can?(current_user, action, project)
end
def authorize_code_access!
return access_denied! unless can?(current_user, :download_code, project)
end
def authorize_push!
return access_denied! unless can?(current_user, :push_code, project)
end
def authorize_labels!
# Labels should be accessible for issues and/or merge requests
authorize_read_issue! || authorize_read_merge_request!
......@@ -170,9 +164,6 @@ class ApplicationController < ActionController::Base
response.headers["Expires"] = "Fri, 01 Jan 1990 00:00:00 GMT"
end
def dev_tools
end
def default_headers
headers['X-Frame-Options'] = 'DENY'
headers['X-XSS-Protection'] = '1; mode=block'
......
......@@ -19,6 +19,7 @@ class Groups::GroupMembersController < ApplicationController
def destroy
@users_group = @group.group_members.find(params[:id])
if can?(current_user, :destroy, @users_group) # May fail if last owner.
@users_group.destroy
respond_to do |format|
......
......@@ -2,7 +2,7 @@ class Projects::BaseTreeController < Projects::ApplicationController
include ExtractsPath
before_filter :authorize_read_project!
before_filter :authorize_code_access!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
end
......@@ -4,7 +4,7 @@ class Projects::BlameController < Projects::ApplicationController
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_code_access!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
def show
......
......@@ -4,9 +4,9 @@ class Projects::BlobController < Projects::ApplicationController
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_code_access!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
before_filter :authorize_push!, only: [:destroy]
before_filter :authorize_push_code!, only: [:destroy]
before_filter :blob
......@@ -20,7 +20,7 @@ class Projects::BlobController < Projects::ApplicationController
flash[:notice] = "Your changes have been successfully committed"
redirect_to project_tree_path(@project, @ref)
else
flash[:alert] = result[:error]
flash[:alert] = result[:message]
render :show
end
end
......
......@@ -3,8 +3,8 @@ class Projects::BranchesController < Projects::ApplicationController
before_filter :authorize_read_project!
before_filter :require_non_empty_project
before_filter :authorize_code_access!
before_filter :authorize_push!, only: [:create, :destroy]
before_filter :authorize_download_code!
before_filter :authorize_push_code!, only: [:create, :destroy]
def index
@sort = params[:sort] || 'name'
......
......@@ -4,19 +4,19 @@
class Projects::CommitController < Projects::ApplicationController
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_code_access!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
before_filter :commit
def show
return git_not_found! unless @commit
@line_notes = project.notes.for_commit_id(commit.id).inline
@branches = project.repository.branch_names_contains(commit.id)
@line_notes = @project.notes.for_commit_id(commit.id).inline
@branches = @project.repository.branch_names_contains(commit.id)
@diffs = @commit.diffs
@note = project.build_commit_note(commit)
@notes_count = project.notes.for_commit_id(commit.id).count
@notes = project.notes.for_commit_id(@commit.id).not_inline.fresh
@note = @project.build_commit_note(commit)
@notes_count = @project.notes.for_commit_id(commit.id).count
@notes = @project.notes.for_commit_id(@commit.id).not_inline.fresh
@noteable = @commit
@comments_allowed = @reply_allowed = true
@comments_target = {
......@@ -32,6 +32,6 @@ class Projects::CommitController < Projects::ApplicationController
end
def commit
@commit ||= project.repository.commit(params[:id])
@commit ||= @project.repository.commit(params[:id])
end
end
......@@ -5,7 +5,7 @@ class Projects::CommitsController < Projects::ApplicationController
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_code_access!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
def show
......
class Projects::CompareController < Projects::ApplicationController
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_code_access!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
def index
......
......@@ -42,7 +42,7 @@ class Projects::DeployKeysController < Projects::ApplicationController
end
def enable
project.deploy_keys << available_keys.find(params[:id])
@project.deploy_keys << available_keys.find(params[:id])
redirect_to project_deploy_keys_path(@project)
end
......
class Projects::EditTreeController < Projects::BaseTreeController
before_filter :require_branch_head
before_filter :blob
before_filter :authorize_push!
before_filter :authorize_push_code!
before_filter :from_merge_request
before_filter :after_edit_path
......@@ -22,7 +22,7 @@ class Projects::EditTreeController < Projects::BaseTreeController
redirect_to after_edit_path
else
flash[:alert] = result[:error]
flash[:alert] = result[:message]
render :show
end
end
......
class Projects::GraphsController < Projects::ApplicationController
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_code_access!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
def show
......
......@@ -4,7 +4,7 @@ class Projects::NetworkController < Projects::ApplicationController
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_code_access!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
def show
......
class Projects::NewTreeController < Projects::BaseTreeController
before_filter :require_branch_head
before_filter :authorize_push!
before_filter :authorize_push_code!
def show
end
......
......@@ -4,7 +4,7 @@ class Projects::RawController < Projects::ApplicationController
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_code_access!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
def show
......
......@@ -3,7 +3,7 @@ class Projects::RefsController < Projects::ApplicationController
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_code_access!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
def switch
......
class Projects::RepositoriesController < Projects::ApplicationController
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_code_access!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
def archive
......
......@@ -3,8 +3,8 @@ class Projects::TagsController < Projects::ApplicationController
before_filter :authorize_read_project!
before_filter :require_non_empty_project
before_filter :authorize_code_access!
before_filter :authorize_push!, only: [:create]
before_filter :authorize_download_code!
before_filter :authorize_push_code!, only: [:create]
before_filter :authorize_admin_project!, only: [:destroy]
def index
......
......@@ -10,7 +10,7 @@ class Projects::TeamMembersController < Projects::ApplicationController
end
def new
@user_project_relation = project.project_members.new
@user_project_relation = @project.project_members.new
end
def create
......@@ -26,7 +26,7 @@ class Projects::TeamMembersController < Projects::ApplicationController
end
def update
@user_project_relation = project.project_members.find_by(user_id: member)
@user_project_relation = @project.project_members.find_by(user_id: member)
@user_project_relation.update_attributes(member_params)
unless @user_project_relation.valid?
......@@ -36,7 +36,7 @@ class Projects::TeamMembersController < Projects::ApplicationController
end
def destroy
@user_project_relation = project.project_members.find_by(user_id: member)
@user_project_relation = @project.project_members.find_by(user_id: member)
@user_project_relation.destroy
respond_to do |format|
......@@ -46,7 +46,7 @@ class Projects::TeamMembersController < Projects::ApplicationController
end
def leave
project.project_members.find_by(user_id: current_user).destroy
@project.project_members.find_by(user_id: current_user).destroy
respond_to do |format|
format.html { redirect_to :back }
......
......@@ -6,7 +6,6 @@ class ProjectsController < ApplicationController
# Authorize
before_filter :authorize_read_project!, except: [:index, :new, :create]
before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive, :retry_import]
before_filter :require_non_empty_project, only: [:blob, :tree, :graph]
layout 'navless', only: [:new, :create, :fork]
before_filter :set_title, only: [:new, :create]
......@@ -76,7 +75,7 @@ class ProjectsController < ApplicationController
end
def import
if project.import_finished?
if @project.import_finished?
redirect_to @project
return
end
......@@ -98,7 +97,7 @@ class ProjectsController < ApplicationController
end
def destroy
return access_denied! unless can?(current_user, :remove_project, project)
return access_denied! unless can?(current_user, :remove_project, @project)
::Projects::DestroyService.new(@project, current_user, {}).execute
......@@ -148,8 +147,8 @@ class ProjectsController < ApplicationController
end
def archive
return access_denied! unless can?(current_user, :archive_project, project)
project.archive!
return access_denied! unless can?(current_user, :archive_project, @project)
@project.archive!
respond_to do |format|
format.html { redirect_to @project }
......@@ -157,8 +156,8 @@ class ProjectsController < ApplicationController
end
def unarchive
return access_denied! unless can?(current_user, :archive_project, project)
project.unarchive!
return access_denied! unless can?(current_user, :archive_project, @project)
@project.unarchive!
respond_to do |format|
format.html { redirect_to @project }
......
......@@ -80,7 +80,7 @@ class Note < ActiveRecord::Base
note_options = {
project: project,
author: author,
note: "_mentioned in #{gfm_reference}_",
note: cross_reference_note_content(gfm_reference),
system: true
}
......@@ -174,7 +174,7 @@ class Note < ActiveRecord::Base
where(noteable_id: noteable.id)
end
notes.where('note like ?', "_mentioned in #{gfm_reference}_").
notes.where('note like ?', cross_reference_note_content(gfm_reference)).
system.any?
end
......@@ -182,8 +182,16 @@ class Note < ActiveRecord::Base
where("note like :query", query: "%#{query}%")
end
def cross_reference_note_prefix
'_mentioned in '
end
private
def cross_reference_note_content(gfm_reference)
cross_reference_note_prefix + "#{gfm_reference}_"
end
# Prepend the mentioner's namespaced project path to the GFM reference for
# cross-project references. For same-project references, return the
# unmodified GFM reference.
......@@ -249,6 +257,10 @@ class Note < ActiveRecord::Base
nil
end
def cross_reference?
note.start_with?(self.class.cross_reference_note_prefix)
end
def find_diff
return nil unless noteable && noteable.diffs.present?
......
......@@ -173,7 +173,7 @@ class Project < ActiveRecord::Base
end
def with_push
includes(:events).where('events.action = ?', Event::PUSHED)
joins(:events).where('events.action = ?', Event::PUSHED)
end
def active
......
......@@ -40,7 +40,8 @@ class SlackService < Service
project_name: project_name
))
credentials = webhook.match(/(\w*).slack.com.*services\/(.*)/)
credentials = webhook.match(/([\w-]*).slack.com.*services\/(.*)/)
if credentials.present?
subdomain = credentials[1]
token = credentials[2].split("token=").last
......
......@@ -10,12 +10,6 @@ module Files
private
def success
out = super()
out[:error] = ''
out
end
def repository
project.repository
end
......
......@@ -119,7 +119,7 @@ class NotificationService
# ignore gitlab service messages
return true if note.note =~ /\A_Status changed to closed_/
return true if note.note =~ /\A_mentioned in / && note.system == true
return true if note.cross_reference? && note.system == true
opts = { noteable_type: note.noteable_type, project_id: note.project_id }
......
......@@ -2,39 +2,20 @@
- if @group.errors.any?
.alert.alert-danger
%span= @group.errors.full_messages.first
.form-group.group_name_holder
= f.label :name, class: 'control-label' do
Group name
.col-sm-10
= f.text_field :name, placeholder: "Example Group", class: "form-control"
.form-group.group-description-holder
= f.label :description, "Details", class: 'control-label'
.col-sm-10
= f.text_area :description, maxlength: 250, class: "form-control js-gfm-input", rows: 4
= render 'shared/group_form', f: f
.form-group.group-description-holder
= f.label :avatar, "Group avatar", class: 'control-label'
.col-sm-10
%a.choose-btn.btn.btn-small.js-choose-group-avatar-button
%i.fa.fa-paperclip
%span Choose File ...
&nbsp;
%span.file_name.js-avatar-filename File name...
= f.file_field :avatar, class: "js-group-avatar-input hidden"
.light The maximum file size allowed is 100KB.
= render 'shared/choose_group_avatar_button', f: f
- if @group.new_record?
.form-group
.col-sm-2
.col-sm-10
.bs-callout.bs-callout-info
%ul
%li A group is a collection of several projects
%li Groups are private by default
%li Members of a group may only view projects they have permission to access
%li Group project URLs are prefixed with the group namespace
%li Existing projects may be moved into a group
= render 'shared/group_tips'
.form-actions
= f.submit 'Create group', class: "btn btn-create"
= link_to 'Cancel', admin_groups_path, class: "btn btn-cancel"
......
......@@ -74,13 +74,13 @@
%ul.well-list.group-users-list
- @members.each do |member|
- user = member.user
%li{class: dom_class(user)}
%li{class: dom_class(member), id: dom_id(user)}
.list-item-name
%strong
= link_to user.name, admin_user_path(user)
%span.pull-right.light
= member.human_access
= link_to group_group_members_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
= link_to group_group_member_path(@group, member), data: { confirm: remove_user_from_group_message(@group, user) }, method: :delete, remote: true, class: "btn-tiny btn btn-remove", title: 'Remove user from group' do
%i.fa.fa-minus.fa-inverse
.panel-footer
= paginate @members, param_name: 'members_page', theme: 'gitlab'
- loggers = [Gitlab::GitLogger, Gitlab::AppLogger,
Gitlab::ProductionLogger, Gitlab::SidekiqLogger]
%ul.nav.nav-tabs.log-tabs
%li.active
= link_to "githost.log", "#githost", 'data-toggle' => 'tab'
%li
= link_to "application.log", "#application", 'data-toggle' => 'tab'
%li
= link_to "production.log", "#production", 'data-toggle' => 'tab'
%li
= link_to "sidekiq.log", "#sidekiq", 'data-toggle' => 'tab'
- loggers.each do |klass|
%li{ class: (klass == Gitlab::GitLogger ? 'active' : '') }
= link_to klass::file_name, "##{klass::file_name_noext}",
'data-toggle' => 'tab'
%p.light To prevent performance issues admin logs output the last 2000 lines
.tab-content
.tab-pane.active#githost
.file-holder#README
.file-title
%i.fa.fa-file
githost.log
.pull-right
= link_to '#', class: 'log-bottom' do
%i.fa.fa-arrow-down
Scroll down
.file-content.logs
%ol
- Gitlab::GitLogger.read_latest.each do |line|
%li
%p= line
.tab-pane#application
.file-holder#README
.file-title
%i.fa.fa-file
application.log
.pull-right
= link_to '#', class: 'log-bottom' do
%i.fa.fa-arrow-down
Scroll down
.file-content.logs
%ol
- Gitlab::AppLogger.read_latest.each do |line|
%li
%p= line
.tab-pane#production
.file-holder#README
.file-title
%i.fa.fa-file
production.log
.pull-right
= link_to '#', class: 'log-bottom' do
%i.fa.fa-arrow-down
Scroll down
.file-content.logs
%ol
- Gitlab::Logger.read_latest_for('production.log').each do |line|
%li
%p= line
.tab-pane#sidekiq
.file-holder#README
.file-title
%i.fa.fa-file
sidekiq.log
.pull-right
= link_to '#', class: 'log-bottom' do
%i.fa.fa-arrow-down
Scroll down
.file-content.logs
%ol
- Gitlab::Logger.read_latest_for('sidekiq.log').each do |line|
%li
%p= line
- loggers.each do |klass|
.tab-pane{ class: (klass == Gitlab::GitLogger ? 'active' : ''),
id: klass::file_name_noext }
.file-holder#README
.file-title
%i.fa.fa-file
= klass::file_name
.pull-right
= link_to '#', class: 'log-bottom' do
%i.fa.fa-arrow-down
Scroll down
.file-content.logs
%ol
- klass.read_latest.each do |line|
%li
%p= line
......@@ -46,5 +46,5 @@
%br
Public projects are an easy way to allow everyone to have read-only access.
.link_holder
= link_to explore_projects_path, class: "btn btn-new" do
= link_to trending_explore_projects_path, class: "btn btn-new" do
Browse public projects »
......@@ -11,16 +11,7 @@
- if @group.errors.any?
.alert.alert-danger
%span= @group.errors.full_messages.first
.form-group
= f.label :name, class: 'control-label' do
Group name
.col-sm-10
= f.text_field :name, placeholder: "Ex. OpenSource", class: "form-control left"
.form-group.group-description-holder
= f.label :description, "Details", class: 'control-label'
.col-sm-10
= f.text_area :description, maxlength: 250, class: "form-control js-gfm-input", rows: 4
= render 'shared/group_form', f: f
.form-group
.col-sm-2
......@@ -31,13 +22,7 @@
You can change your group avatar here
- else
You can upload a group avatar here
%a.choose-btn.btn.btn-small.js-choose-group-avatar-button
%i.fa.fa-paperclip
%span Choose File ...
&nbsp;
%span.file_name.js-avatar-filename File name...
= f.file_field :avatar, class: "js-group-avatar-input hidden"
.light The maximum file size allowed is 100KB.
= render 'shared/choose_group_avatar_button', f: f
- if @group.avatar?
%hr
= link_to 'Remove avatar', group_avatar_path(@group.to_param), data: { confirm: "Group avatar will be removed. Are you sure?"}, method: :delete, class: "btn btn-remove btn-small remove-avatar"
......
......@@ -2,37 +2,18 @@
- if @group.errors.any?
.alert.alert-danger
%span= @group.errors.full_messages.first
.form-group
= f.label :name, class: 'control-label' do
Group name
.col-sm-10
= f.text_field :name, placeholder: "Ex. OpenSource", class: "form-control", tabindex: 1, autofocus: true
.form-group.group-description-holder
= f.label :description, "Details", class: 'control-label'
.col-sm-10
= f.text_area :description, maxlength: 250, class: "form-control js-gfm-input", rows: 4, tabindex: 2
= render 'shared/group_form', f: f, autofocus: true
.form-group.group-description-holder
= f.label :avatar, "Group avatar", class: 'control-label'
.col-sm-10
%a.choose-btn.btn.btn-small.js-choose-group-avatar-button
%i.fa.fa-paperclip
%span Choose File ...
&nbsp;
%span.file_name.js-avatar-filename File name...
= f.file_field :avatar, class: "js-group-avatar-input hidden"
.light The maximum file size allowed is 100KB.
= render 'shared/choose_group_avatar_button', f: f
.form-group
.col-sm-2
.col-sm-10
%ul
%li A group is a collection of several projects
%li Groups are private by default
%li Members of a group may only view projects they have permission to access
%li Group project URLs are prefixed with the group namespace
%li Existing projects may be moved into a group
= render 'shared/group_tips'
.form-actions
= f.submit 'Create group', class: "btn btn-create", tabindex: 3
%a.choose-btn.btn.btn-small.js-choose-group-avatar-button
%i.fa.fa-paperclip
%span Choose File ...
&nbsp;
%span.file_name.js-avatar-filename File name...
= f.file_field :avatar, class: 'js-group-avatar-input hidden'
.light The maximum file size allowed is 100KB.
.form-group
= f.label :name, class: 'control-label' do
Group name
.col-sm-10
= f.text_field :name, placeholder: 'Example Group', class: 'form-control',
autofocus: local_assigns[:autofocus] || false
.form-group.group-description-holder
= f.label :description, 'Details', class: 'control-label'
.col-sm-10
= f.text_area :description, maxlength: 250,
class: 'form-control js-gfm-input', rows: 4
%ul
%li A group is a collection of several projects
%li Groups are private by default
%li Members of a group may only view projects they have permission to access
%li Group project URLs are prefixed with the group namespace
%li Existing projects may be moved into a group
......@@ -25,6 +25,7 @@ module Gitlab
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
# NOTE: Please prefer set time zone on config/gitlab.yml configuration file.
# config.time_zone = 'Central Time (US & Canada)'
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
......
......@@ -33,6 +33,11 @@ production: &base
# Uncomment and customize if you can't use the default user to run GitLab (default: 'git')
# user: git
## Date & Time settings
# Uncomment and customize if you want to change the default time zone of GitLab application.
# To see all available zones, run `bundle exec rake time:zones:all`
# time_zone: 'UTC'
## Email settings
# Email address used in the "From" field in mails sent by GitLab
email_from: example@example.com
......
......@@ -61,7 +61,6 @@ Settings.ldap['enabled'] = false if Settings.ldap['enabled'].nil?
if Settings.ldap['enabled'] || Rails.env.test?
if Settings.ldap['host'].present?
server = Settings.ldap.except('sync_time')
server['label'] = 'LDAP'
server['provider_name'] = 'ldap'
Settings.ldap['servers'] = {
'ldap' => server
......@@ -69,6 +68,7 @@ if Settings.ldap['enabled'] || Rails.env.test?
end
Settings.ldap['servers'].each do |key, server|
server['label'] ||= 'LDAP'
server['allow_username_or_email_login'] = false if server['allow_username_or_email_login'].nil?
server['active_directory'] = true if server['active_directory'].nil?
server['provider_name'] ||= "ldap#{key}".downcase
......@@ -103,6 +103,7 @@ Settings.gitlab['user_home'] ||= begin
rescue ArgumentError # no user configured
'/home/' + Settings.gitlab['user']
end
Settings.gitlab['time_zone'] ||= nil
Settings.gitlab['signup_enabled'] ||= false
Settings.gitlab['signin_enabled'] ||= true if Settings.gitlab['signin_enabled'].nil?
Settings.gitlab['restricted_visibility_levels'] = Settings.send(:verify_constant_array, Gitlab::VisibilityLevel, Settings.gitlab['restricted_visibility_levels'], [])
......
if Gitlab::LDAP::Config.enabled?
module OmniAuth::Strategies
server = Gitlab.config.ldap.servers.values.first
const_set(server['provider_class'], Class.new(LDAP))
klass = server['provider_class']
const_set(klass, Class.new(LDAP)) unless klass == 'LDAP'
end
OmniauthCallbacksController.class_eval do
......
# Be sure to restart your server when you modify this file.
require 'securerandom'
# Your secret key for verifying the gitlab_shell.
secret_file = Rails.root.join('.gitlab_shell_secret')
gitlab_shell_symlink = File.join(Gitlab.config.gitlab_shell.path, '.gitlab_shell_secret')
unless File.exist? secret_file
# Generate a new token of 16 random hexadecimal characters and store it in secret_file.
token = SecureRandom.hex(16)
File.write(secret_file, token)
end
if File.exist?(Gitlab.config.gitlab_shell.path) && !File.exist?(gitlab_shell_symlink)
FileUtils.symlink(secret_file, gitlab_shell_symlink)
end
\ No newline at end of file
Time.zone = Gitlab.config.gitlab.time_zone || Time.zone
# Services
## GitLab CI
### Edit GitLab CI service
Set GitLab CI service for a project.
```
PUT /projects/:id/services/gitlab-ci
```
Parameters:
- `token` (required) - CI project token
- `project_url` (required) - CI project url
### Delete GitLab CI service
Delete GitLab CI service settings for a project.
```
DELETE /projects/:id/services/gitlab-ci
```
## Hipchat
### Edit Hipchat service
Set Hipchat service for project.
```
PUT /projects/:id/services/hipchat
```
Parameters:
- `token` (required) - Hipchat token
- `room` (required) - Hipchat room name
### Delete Hipchat service
Delete Hipchat service for a project.
```
DELETE /projects/:id/services/hipchat
```
......@@ -74,8 +74,8 @@ Is the system packaged Git too old? Remove it and compile from source.
# Download and compile from source
cd /tmp
curl -L --progress https://www.kernel.org/pub/software/scm/git/git-2.0.0.tar.gz | tar xz
cd git-2.0.0/
curl -L --progress https://www.kernel.org/pub/software/scm/git/git-2.1.2.tar.gz | tar xz
cd git-2.1.2/
make prefix=/usr/local all
# Install into /usr/local/bin
......@@ -165,9 +165,9 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da
### Clone the Source
# Clone GitLab repository
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 7-3-stable gitlab
sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab-ce.git -b 7-4-stable gitlab
**Note:** You can change `7-3-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
**Note:** You can change `7-4-stable` to `master` if you want the *bleeding edge* version, but never install master on a production server!
### Configure It
......
......@@ -510,6 +510,10 @@ Code above produces next output:
| cell 1 | cell 2 |
| cell 3 | cell 4 |
**Note**
The row of dashes between the table header and body must have at least three dashes in each column.
## References
- This document leveraged heavily from the [Markdown-Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet).
......
# From 6.x or 7.x to 7.3
# From 6.x or 7.x to 7.4
This allows you to upgrade any version of GitLab from 6.0 and up (including 7.0 and up) to 7.3.
This allows you to upgrade any version of GitLab from 6.0 and up (including 7.0 and up) to 7.4.
## Global issue numbers
......@@ -70,7 +70,7 @@ sudo -u git -H git checkout -- db/schema.rb # local changes will be restored aut
For GitLab Community Edition:
```bash
sudo -u git -H git checkout 7-3-stable
sudo -u git -H git checkout 7-4-stable
```
OR
......@@ -78,7 +78,7 @@ OR
For GitLab Enterprise Edition:
```bash
sudo -u git -H git checkout 7-3-stable-ee
sudo -u git -H git checkout 7-4-stable-ee
```
## 4. Install additional packages
......@@ -152,14 +152,14 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
TIP: to see what changed in `gitlab.yml.example` in this release use next command:
```
git diff 6-0-stable:config/gitlab.yml.example 7-3-stable:config/gitlab.yml.example
git diff 6-0-stable:config/gitlab.yml.example 7-4-stable:config/gitlab.yml.example
```
* Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-3-stable/config/gitlab.yml.example but with your settings.
* Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-3-stable/config/unicorn.rb.example but with your settings.
* Make `/home/git/gitlab-shell/config.yml` the same as https://gitlab.com/gitlab-org/gitlab-shell/blob/v2.0.0/config.yml.example but with your settings.
* HTTP setups: Make `/etc/nginx/sites-available/nginx` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-3-stable/lib/support/nginx/gitlab but with your settings.
* HTTPS setups: Make `/etc/nginx/sites-available/nginx-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-3-stable/lib/support/nginx/gitlab-ssl but with your settings.
* Make `/home/git/gitlab/config/gitlab.yml` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-4-stable/config/gitlab.yml.example but with your settings.
* Make `/home/git/gitlab/config/unicorn.rb` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-4-stable/config/unicorn.rb.example but with your settings.
* Make `/home/git/gitlab-shell/config.yml` the same as https://gitlab.com/gitlab-org/gitlab-shell/blob/v2.0.1/config.yml.example but with your settings.
* HTTP setups: Make `/etc/nginx/sites-available/nginx` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-4-stable/lib/support/nginx/gitlab but with your settings.
* HTTPS setups: Make `/etc/nginx/sites-available/nginx-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-4-stable/lib/support/nginx/gitlab-ssl but with your settings.
* Copy rack attack middleware config
```bash
......
......@@ -74,7 +74,7 @@ sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
# Enable Redis socket for default Debian / Ubuntu path
echo 'unixsocket /var/run/redis/redis.sock' | sudo tee -a /etc/redis/redis.conf
# Be sure redis group can write to the socket, enable only if supported (>= redis 2.4.0).
sed -i '/# unixsocketperm/ s/^# unixsocketperm.*/unixsocketperm 0775/' /etc/redis/redis.conf
sudo sed -i '/# unixsocketperm/ s/^# unixsocketperm.*/unixsocketperm 0775/' /etc/redis/redis.conf
# Activate the changes to redis.conf
sudo service redis-server restart
# Add git to the redis group
......
# From 7.3 to 7.4
## GitLab 7.4 has not been released yet!
### 0. Backup
This document currently just serves as a place to keep track of updates that will be needed for the 7.4 update.
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 1. Stop server
```bash
sudo service gitlab stop
```
### 2. Get latest code
```bash
cd /home/git/gitlab
sudo -u git -H git fetch --all
sudo -u git -H git checkout -- db/schema.rb # local changes will be restored automatically
```
For GitLab Community Edition:
```bash
sudo -u git -H git checkout 7-4-stable
```
OR
For GitLab Enterprise Edition:
```bash
sudo -u git -H git checkout 7-4-stable-ee
```
### 3. Install libs, migrations, etc.
```bash
cd /home/git/gitlab
# MySQL installations (note: the line below states '--without ... postgres')
sudo -u git -H bundle install --without development test postgres --deployment
# PostgreSQL installations (note: the line below states '--without ... mysql')
sudo -u git -H bundle install --without development test mysql --deployment
# Run database migrations
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
# Clean up assets and cache
sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
# Update init.d script
sudo cp lib/support/init.d/gitlab /etc/init.d/gitlab
```
### 4. Configure Redis to use sockets
# Configure redis to use sockets
sudo cp /etc/redis/redis.conf /etc/redis/redis.conf.orig
# Disable Redis listening on TCP by setting 'port' to 0
sed 's/^port .*/port 0/' /etc/redis/redis.conf.orig | sudo tee /etc/redis/redis.conf
# Enable Redis socket for default Debian / Ubuntu path
echo 'unixsocket /var/run/redis/redis.sock' | sudo tee -a /etc/redis/redis.conf
# Be sure redis group can write to the socket, enable only if supported (>= redis 2.4.0).
sed -i '/# unixsocketperm/ s/^# unixsocketperm.*/unixsocketperm 0775/' /etc/redis/redis.conf
# Activate the changes to redis.conf
sudo service redis-server restart
# Add git to the redis group
sudo usermod -aG redis git
# Configure Redis connection settings
sudo -u git -H cp config/resque.yml.example config/resque.yml
# Change the Redis socket path if you are not using the default Debian / Ubuntu configuration
sudo -u git -H editor config/resque.yml
# Configure gitlab-shell to use Redis sockets
sudo -u git -H sed -i 's|^ # socket.*| socket: /var/run/redis/redis.sock|' /home/git/gitlab-shell/config.yml
### 5. Update config files
#### New configuration options for gitlab.yml
There are new configuration options available for gitlab.yml. View them with the command below and apply them to your current gitlab.yml.
## Update config files
```
git diff origin/7-3-stable:config/gitlab.yml.example origin/7-4-stable:config/gitlab.yml.example
```
#### Change timeout for unicorn
```
# config/unicorn.rb
timeout 60
```
#### Change nginx https settings
* HTTPS setups: Make `/etc/nginx/sites-available/nginx-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-4-stable/lib/support/nginx/gitlab-ssl but with your setting
#### Update database.yml config file(for mysql only) if needed (basically it is required for old gitlab installations)
* Add `collation: utf8_general_ci` to config/database.yml as seen in [config/database.yml.mysql](config/database.yml.mysql)
## Optional optimizations for GitLab setups with MySQL databases
### 6. Start application
sudo service gitlab start
sudo service nginx restart
### 7. Check application status
Check if GitLab and its environment are configured correctly:
sudo -u git -H bundle exec rake gitlab:env:info RAILS_ENV=production
To make sure you didn't miss anything run a more thorough check with:
sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
If all items are green, then congratulations upgrade is complete!
### 8. Update OmniAuth configuration
When using Google omniauth login, changes of the Google account required.
Ensure that `Contacts API` and the `Google+ API` are enabled in the [Google Developers Console](https://console.developers.google.com/).
More details can be found at the [integration documentation](../integration/google.md).
### 9. Optional optimizations for GitLab setups with MySQL databases
Only applies if running MySQL database created with GitLab 6.7 or earlier. If you are not experiencing any issues you may not need the following instructions however following them will bring your database in line with the latest recommended installation configuration and help avoid future issues. Be sure to follow these directions exactly. These directions should be safe for any MySQL instance but to be sure make a current MySQL database backup beforehand.
......@@ -75,3 +196,22 @@ mysql> \q
# Set production -> password: the password your replaced $password with earlier
sudo -u git -H editor /home/git/gitlab/config/database.yml
```
## Things went south? Revert to previous version (7.3)
### 1. Revert the code to the previous version
Follow the [upgrade guide from 7.2 to 7.3](7.2-to-7.3.md), except for the database migration
(The backup is already migrated to the previous version)
### 2. Restore from the backup:
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:restore RAILS_ENV=production
```
If you have more than one backup *.tar file(s) please add `BACKUP=timestamp_of_backup` to the command above.
......@@ -20,3 +20,10 @@ Feature: Admin Groups
When I visit admin group page
When I select user "John Doe" from user list as "Reporter"
Then I should see "John Doe" in team list in every project as "Reporter"
@javascript
Scenario: Remove user from group
Given we have user "John Doe" in group
When I visit admin group page
And I remove user "John Doe" from group
Then I should not see "John Doe" in team list
......@@ -34,6 +34,16 @@ Feature: Project Source Browse Files
Then I am redirected to the new file
And I should see its new content
@javascript
Scenario: If I enter an illegal file name I see an error message
Given I click on "new file" link in repo
And I fill the new file name with an illegal name
And I edit code
And I fill the commit message
And I click on "Commit changes"
Then I am on the new file page
And I see a commit error message
@javascript
Scenario: I can edit file
Given I click on ".gitignore" file in repo
......@@ -50,6 +60,16 @@ Feature: Project Source Browse Files
Then I am redirected to the ".gitignore"
And I should see its new content
@javascript @wip
Scenario: If I don't change the content of the file I see an error message
Given I click on ".gitignore" file in repo
And I click button "edit"
And I fill the commit message
And I click on "Commit changes"
# Test fails because carriage returns are added to the file.
Then I am on the ".gitignore" edit file page
And I see a commit error message
@javascript
Scenario: I can see editing preview
Given I click on ".gitignore" file in repo
......
......@@ -37,8 +37,7 @@ class Spinach::Features::AdminGroups < Spinach::FeatureSteps
end
When 'I select user "John Doe" from user list as "Reporter"' do
user = User.find_by(name: "John Doe")
select2(user.id, from: "#user_ids", multiple: true)
select2(user_john.id, from: "#user_ids", multiple: true)
within "#new_team_member" do
select "Reporter", from: "access_level"
end
......@@ -58,9 +57,29 @@ class Spinach::Features::AdminGroups < Spinach::FeatureSteps
end
end
step 'we have user "John Doe" in group' do
current_group.add_user(user_john, Gitlab::Access::REPORTER)
end
step 'I remove user "John Doe" from group' do
within "#user_#{user_john.id}" do
click_link 'Remove user from group'
end
end
step 'I should not see "John Doe" in team list' do
within ".group-users-list" do
page.should_not have_content "John Doe"
end
end
protected
def current_group
@group ||= Group.first
end
def user_john
@user_john ||= User.find_by(name: "John Doe")
end
end
......@@ -61,6 +61,10 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
fill_in :file_name, with: new_file_name
end
step 'I fill the new file name with an illegal name' do
fill_in :file_name, with: '.git'
end
step 'I fill the commit message' do
fill_in :commit_message, with: 'Not yet a commit message.'
end
......@@ -151,6 +155,10 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
expect(page).not_to have_link('permalink')
end
step 'I see a commit error message' do
expect(page).to have_content('Your changes could not be committed')
end
private
def set_new_content
......
......@@ -265,6 +265,15 @@ module SharedPaths
visit project_blob_path(@project, File.join(root_ref, '.gitignore'))
end
step 'I am on the new file page' do
current_path.should eq(project_new_tree_path(@project, root_ref))
end
step 'I am on the ".gitignore" edit file page' do
current_path.should eq(project_edit_tree_path(
@project, File.join(root_ref, '.gitignore')))
end
step 'I visit project source page for "6d39438"' do
visit project_tree_path(@project, "6d39438")
end
......
......@@ -85,7 +85,7 @@ module API
branch_name: branch_name
}
else
render_api_error!(result[:error], 400)
render_api_error!(result[:message], 400)
end
end
......@@ -117,7 +117,7 @@ module API
branch_name: branch_name
}
else
render_api_error!(result[:error], 400)
render_api_error!(result[:message], 400)
end
end
......@@ -149,7 +149,7 @@ module API
branch_name: branch_name
}
else
render_api_error!(result[:error], 400)
render_api_error!(result[:message], 400)
end
end
end
......
......@@ -67,6 +67,10 @@ module API
unauthorized! unless current_user
end
def authenticate_by_gitlab_shell_token!
unauthorized! unless secret_token == params['secret_token']
end
def authenticated_as_admin!
forbidden! unless current_user.is_admin?
end
......@@ -193,5 +197,9 @@ module API
abilities
end
end
def secret_token
File.read(Rails.root.join('.gitlab_shell_secret'))
end
end
end
module API
# Internal access API
class Internal < Grape::API
before {
authenticate_by_gitlab_shell_token!
}
namespace 'internal' do
# Check if git command is allowed to project
#
......
......@@ -28,7 +28,7 @@ module API
# Delete GitLab CI service settings
#
# Example Request:
# DELETE /projects/:id/keys/:id
# DELETE /projects/:id/services/gitlab-ci
delete ":id/services/gitlab-ci" do
if user_project.gitlab_ci_service
user_project.gitlab_ci_service.update_attributes(
......@@ -38,7 +38,41 @@ module API
)
end
end
# Set Hipchat service for project
#
# Parameters:
# token (required) - Hipchat token
# room (required) - Hipchat room name
#
# Example Request:
# PUT /projects/:id/services/hipchat
put ':id/services/hipchat' do
required_attributes! [:token, :room]
attrs = attributes_for_keys [:token, :room]
user_project.build_missing_services
if user_project.hipchat_service.update_attributes(
attrs.merge(active: true))
true
else
not_found!
end
end
# Delete Hipchat service settings
#
# Example Request:
# DELETE /projects/:id/services/hipchat
delete ':id/services/hipchat' do
if user_project.hipchat_service
user_project.hipchat_service.update_attributes(
active: false,
token: nil,
room: nil
)
end
end
end
end
end
......@@ -30,7 +30,7 @@ module Backup
if File.exists?(path_to_repo(wiki))
print " * #{wiki.path_with_namespace} ... "
if wiki.empty?
if wiki.repository.empty?
puts " [SKIPPED]".cyan
else
output, status = Gitlab::Popen.popen(%W(git --git-dir=#{path_to_repo(wiki)} bundle create #{path_to_bundle(wiki)} --all))
......
module Gitlab
class AppLogger < Gitlab::Logger
def self.file_name
'application.log'
def self.file_name_noext
'application'
end
def format_message(severity, timestamp, progname, msg)
......
module Gitlab
class GitLogger < Gitlab::Logger
def self.file_name
'githost.log'
def self.file_name_noext
'githost'
end
def format_message(severity, timestamp, progname, msg)
......
module Gitlab
class Logger < ::Logger
def self.file_name
file_name_noext + '.log'
end
def self.error(message)
build.error(message)
end
......
module Gitlab
class ProductionLogger < Gitlab::Logger
def self.file_name_noext
'production'
end
end
end
module Gitlab
class SidekiqLogger < Gitlab::Logger
def self.file_name_noext
'sidekiq'
end
end
end
......@@ -91,8 +91,7 @@ server {
# resolver_timeout 10s;
## [Optional] Generate a stronger DHE parameter:
## cd /etc/ssl/certs
## sudo openssl dhparam -out dhparam.pem 4096
## sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 4096
##
# ssl_dhparam /etc/ssl/certs/dhparam.pem;
......
......@@ -11,7 +11,7 @@ namespace :gitlab do
home_dir = Rails.env.test? ? Rails.root.join('tmp/tests') : Settings.gitlab.user_home
gitlab_url = Settings.gitlab.url
# gitlab-shell requires a / at the end of the url
gitlab_url += "/" unless gitlab_url.match(/\/$/)
gitlab_url += '/' unless gitlab_url.end_with?('/')
repos_path = Gitlab.config.gitlab_shell.repos_path
target_dir = Gitlab.config.gitlab_shell.path
......
......@@ -77,5 +77,25 @@ describe SlackService do
WebMock.should have_requested(:post, api_url).once
end
end
context 'with new webhook syntax with slack allowed team name' do
before do
@allowed_webhook = 'https://gitlab-hq-123.slack.com/services/hooks/incoming-webhook?token=cdIj4r4LfXUOySDUjp0tk3OI'
slack_service.stub(
project: project,
project_id: project.id,
service_hook: true,
webhook: @allowed_webhook
)
WebMock.stub_request(:post, @allowed_webhook)
end
it "should call Slack API" do
slack_service.execute(sample_data)
WebMock.should have_requested(:post, @allowed_webhook).once
end
end
end
end
......@@ -5,10 +5,11 @@ describe API::API, api: true do
let(:user) { create(:user) }
let(:key) { create(:key, user: user) }
let(:project) { create(:project) }
let(:secret_token) { File.read Rails.root.join('.gitlab_shell_secret') }
describe "GET /internal/check", no_db: true do
it do
get api("/internal/check")
get api("/internal/check"), secret_token: secret_token
response.status.should == 200
json_response['api_version'].should == API::API.version
......@@ -17,7 +18,7 @@ describe API::API, api: true do
describe "GET /internal/discover" do
it do
get(api("/internal/discover"), key_id: key.id)
get(api("/internal/discover"), key_id: key.id, secret_token: secret_token)
response.status.should == 200
......@@ -159,7 +160,8 @@ describe API::API, api: true do
api("/internal/allowed"),
key_id: key.id,
project: project.path_with_namespace,
action: 'git-upload-pack'
action: 'git-upload-pack',
secret_token: secret_token
)
end
......@@ -169,7 +171,8 @@ describe API::API, api: true do
changes: 'd14d6c0abdd253381df51a723d58691b2ee1ab08 570e7b2abdd848b95f2f578043fc23bd6f6fd24d refs/heads/master',
key_id: key.id,
project: project.path_with_namespace,
action: 'git-receive-pack'
action: 'git-receive-pack',
secret_token: secret_token
)
end
......@@ -179,7 +182,8 @@ describe API::API, api: true do
ref: 'master',
key_id: key.id,
project: project.path_with_namespace,
action: 'git-upload-archive'
action: 'git-upload-archive',
secret_token: secret_token
)
end
end
......@@ -27,4 +27,30 @@ describe API::API, api: true do
project.gitlab_ci_service.should be_nil
end
end
describe 'PUT /projects/:id/services/hipchat' do
it 'should update hipchat settings' do
put api("/projects/#{project.id}/services/hipchat", user),
token: 'secret-token', room: 'test'
response.status.should == 200
project.hipchat_service.should_not be_nil
end
it 'should return if required fields missing' do
put api("/projects/#{project.id}/services/gitlab-ci", user),
token: 'secret-token', active: true
response.status.should == 400
end
end
describe 'DELETE /projects/:id/services/hipchat' do
it 'should delete hipchat settings' do
delete api("/projects/#{project.id}/services/hipchat", user)
response.status.should == 200
project.hipchat_service.should be_nil
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