Commit 1a7e3476 authored by Valery Sizov's avatar Valery Sizov

Merge remote-tracking branch 'origin/master' into backup_restore_drop_sequences

Conflicts:
	CHANGELOG
parents 8146271d c58edd7c
......@@ -4,8 +4,18 @@ v 7.5.0
- Fix LDAP authentication for Git HTTP access
- Fix LDAP config lookup for provider 'ldap'
- Drop all sequences during Postgres database restore
- Project title links to project homepage (Ben Bodenmiller)
- Add Atlassian Bamboo CI service (Drew Blessing)
- Mentioned @user will receive email even if he is not participating in issue or commit
- Session API: Use case-insensitive authentication like in UI (Andrey Krivko)
- Tie up loose ends with annotated tags: API & UI (Sean Edge)
- Return valid json for deleting branch via API (sponsored by O'Reilly Media)
- Expose username in project events API (sponsored by O'Reilly Media)
v 7.4.3
- Fix raw snippets view
- Fix security issue for member api
- Fix buildbox integration
v 7.4.2
- Fix internal snippet exposing for unauthenticated users
......@@ -50,7 +60,7 @@ v 7.4.0
- Fix ambiguous sha problem with mentioned commit
- Fixed bug with apostrophe when at mentioning users
- Add active directory ldap option
- Developers can push to wiki repo. Protected branches does not affect wiki repo any more
- Developers can push to wiki repo. Protected branches does not affect wiki repo any more
- Faster rev list
- Fix branch removal
......
......@@ -54,6 +54,8 @@ We welcome merge requests with fixes and improvements to GitLab code, tests, and
Merge requests can be filed either at [gitlab.com](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests) or [github.com](https://github.com/gitlabhq/gitlabhq/pulls).
If you are new to GitLab development (or web development in general), search for the label `easyfix` ([gitlab.com](https://gitlab.com/gitlab-org/gitlab-ce/issues?label_name=easyfix), [github](https://github.com/gitlabhq/gitlabhq/labels/easyfix)). Those are issues easy to fix, marked by the GitLab core-team. If you are unsure how to proceed but want to help, mention one of the core-team members to give you a hint.
### Merge request guidelines
If you can, please submit a merge request with the fix or improvements including tests. If you don't know how to fix the issue but can write a test that exposes the issue we will accept that as well. In general bug fixes that include a regression test are merged quickly while new features without proper tests are least likely to receive timely feedback. The workflow to make a merge request is as follows:
......
......@@ -143,7 +143,7 @@ gem "gitlab-flowdock-git-hook", "~> 0.4.2"
gem "gemnasium-gitlab-service", "~> 0.2"
# Slack integration
gem "slack-notifier", "~> 0.3.2"
gem "slack-notifier", "~> 1.0.0"
# d3
gem "d3_rails", "~> 3.1.4"
......
......@@ -488,7 +488,7 @@ GEM
rack-protection (~> 1.4)
tilt (~> 1.3, >= 1.3.4)
six (0.2.0)
slack-notifier (0.3.2)
slack-notifier (1.0.0)
slim (2.0.2)
temple (~> 0.6.6)
tilt (>= 1.3.3, < 2.1)
......@@ -689,7 +689,7 @@ DEPENDENCIES
simplecov
sinatra
six
slack-notifier (~> 0.3.2)
slack-notifier (~> 1.0.0)
slim
spinach-rails
spring (= 1.1.3)
......
......@@ -58,8 +58,6 @@ class Dispatcher
when 'groups:show', 'projects:show'
new Activities()
shortcut_handler = new ShortcutsNavigation()
when 'projects:teams:members:index'
new TeamMembers()
when 'groups:members'
new GroupMembers()
new UsersSelect()
......
class @TeamMembers
constructor: ->
$('.team-members .project-access-select').on "change", ->
$(this.form).submit()
// Details
//--------
.js-details-container .content { display: none; }
.js-details-container .content.hide { display: block; }
.js-details-container.open .content { display: block; }
.js-details-container.open .content.hide { display: none; }
.js-details-container {
.content {
display: none;
&.hide { display: block; }
}
&.open .content {
display: block;
&.hide { display: none; }
}
}
// Toggle between two states.
.js-toggler-container .turn-on { display: block; }
.js-toggler-container .turn-off { display: none; }
.js-toggler-container.on .turn-on { display: none; }
.js-toggler-container.on .turn-off { display: block; }
.js-toggler-container {
.turn-on { display: block; }
.turn-off { display: none; }
&.on {
.turn-on { display: none; }
.turn-off { display: block; }
}
}
......@@ -186,3 +186,11 @@
}
}
}
.readme-holder .wiki, .note-body, .wiki-holder {
.white {
.highlight, pre, .hljs {
background: #F9F9F9;
}
}
}
class Projects::BaseTreeController < Projects::ApplicationController
include ExtractsPath
before_filter :authorize_read_project!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
end
......
......@@ -3,7 +3,6 @@ class Projects::BlameController < Projects::ApplicationController
include ExtractsPath
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
......
......@@ -3,7 +3,6 @@ class Projects::BlobController < Projects::ApplicationController
include ExtractsPath
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
before_filter :authorize_push_code!, only: [:destroy]
......
class Projects::BranchesController < Projects::ApplicationController
# Authorize
before_filter :authorize_read_project!
before_filter :require_non_empty_project
before_filter :authorize_download_code!
......@@ -19,6 +18,7 @@ class Projects::BranchesController < Projects::ApplicationController
def create
result = CreateBranchService.new(project, current_user).
execute(params[:branch_name], params[:ref])
if result[:status] == :success
@branch = result[:branch]
redirect_to project_tree_path(@project, @branch.name)
......
......@@ -3,7 +3,6 @@
# Not to be confused with CommitsController, plural.
class Projects::CommitController < Projects::ApplicationController
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
before_filter :commit
......
......@@ -4,7 +4,6 @@ class Projects::CommitsController < Projects::ApplicationController
include ExtractsPath
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
......
class Projects::CompareController < Projects::ApplicationController
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
......
class Projects::GraphsController < Projects::ApplicationController
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
......
......@@ -3,7 +3,6 @@ class Projects::NetworkController < Projects::ApplicationController
include ApplicationHelper
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
......
......@@ -3,7 +3,6 @@ class Projects::RawController < Projects::ApplicationController
include ExtractsPath
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
......
......@@ -2,7 +2,6 @@ class Projects::RefsController < Projects::ApplicationController
include ExtractsPath
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
......
class Projects::RepositoriesController < Projects::ApplicationController
# Authorize
before_filter :authorize_read_project!
before_filter :authorize_download_code!
before_filter :require_non_empty_project
......
class Projects::TagsController < Projects::ApplicationController
# Authorize
before_filter :authorize_read_project!
before_filter :require_non_empty_project
before_filter :authorize_download_code!
before_filter :authorize_push_code!, only: [:create]
before_filter :authorize_admin_project!, only: [:destroy]
......
......@@ -4,7 +4,6 @@ class ProjectsController < ApplicationController
before_filter :repository, except: [:new, :create]
# Authorize
before_filter :authorize_read_project!, except: [:index, :new, :create]
before_filter :authorize_admin_project!, only: [:edit, :update, :destroy, :transfer, :archive, :unarchive, :retry_import]
layout 'navless', only: [:new, :create, :fork]
......@@ -52,8 +51,6 @@ class ProjectsController < ApplicationController
return
end
return authenticate_user! unless @project.public? || current_user
limit = (params[:limit] || 20).to_i
@events = @project.events.recent
@events = event_filter.apply_filter(@events)
......
......@@ -62,6 +62,19 @@ module IssuesHelper
''
end
def issue_timestamp(issue)
# Shows the created at time and the updated at time if different
ts = "#{time_ago_with_tooltip(issue.created_at, 'bottom', 'note_created_ago')}"
if issue.updated_at != issue.created_at
ts << capture_haml do
haml_tag :small do
haml_concat " (Edited #{time_ago_with_tooltip(issue.updated_at, 'bottom', 'issue_edited_ago')})"
end
end
end
ts.html_safe
end
# Checks if issues_tracker setting exists in gitlab.yml
def external_issues_tracker_enabled?
Gitlab.config.issues_tracker && Gitlab.config.issues_tracker.values.any?
......
......@@ -42,12 +42,12 @@ module ProjectsHelper
def project_title(project)
if project.group
content_tag :span do
link_to(simple_sanitize(project.group.name), group_path(project.group)) + " / " + project.name
link_to(simple_sanitize(project.group.name), group_path(project.group)) + ' / ' + link_to(simple_sanitize(project.name), project_path(project))
end
else
owner = project.namespace.owner
content_tag :span do
link_to(simple_sanitize(owner.name), user_path(owner)) + " / " + project.name
link_to(simple_sanitize(owner.name), user_path(owner)) + ' / ' + link_to(simple_sanitize(project.name), project_path(project))
end
end
end
......
......@@ -66,7 +66,7 @@ module TreeHelper
def tree_breadcrumbs(tree, max_links = 2)
if @path.present?
part_path = ""
parts = @path.split("\/")
parts = @path.split('/')
yield('..', nil) if parts.count > max_links
......
......@@ -131,9 +131,10 @@ module Issuable
users.concat(mentions.reduce([], :|)).uniq
end
def to_hook_data
def to_hook_data(user)
{
object_kind: self.class.name.underscore,
user: user.hook_attrs,
object_attributes: hook_attrs
}
end
......
......@@ -186,10 +186,6 @@ class Event < ActiveRecord::Base
data[:ref]["refs/heads"]
end
def new_branch?
commit_from =~ /^00000/
end
def new_ref?
commit_from =~ /^00000/
end
......
......@@ -90,7 +90,7 @@ class Note < ActiveRecord::Base
note_options.merge!(noteable: noteable)
end
create(note_options)
create(note_options) unless cross_reference_disallowed?(noteable, mentioner)
end
def create_milestone_change_note(noteable, project, author, milestone)
......@@ -165,6 +165,15 @@ class Note < ActiveRecord::Base
[:discussion, type.try(:underscore), id, line_code].join("-").to_sym
end
# Determine if cross reference note should be created.
# eg. mentioning a commit in MR comments which exists inside a MR
# should not create "mentioned in" note.
def cross_reference_disallowed?(noteable, mentioner)
if mentioner.kind_of?(MergeRequest)
mentioner.commits.map(&:id).include? noteable.id
end
end
# Determine whether or not a cross-reference note already exists.
def cross_reference_exists?(noteable, mentioner)
gfm_reference = mentioner_gfm_ref(noteable, mentioner)
......@@ -251,8 +260,8 @@ class Note < ActiveRecord::Base
def commit_author
@commit_author ||=
project.users.find_by(email: noteable.author_email) ||
project.users.find_by(name: noteable.author_name)
project.team.users.find_by(email: noteable.author_email) ||
project.team.users.find_by(name: noteable.author_name)
rescue
nil
end
......
......@@ -402,43 +402,8 @@ class Project < ActiveRecord::Base
end
def update_merge_requests(oldrev, newrev, ref, user)
return true unless ref =~ /heads/
branch_name = ref.gsub("refs/heads/", "")
commits = self.repository.commits_between(oldrev, newrev)
c_ids = commits.map(&:id)
# Close merge requests
mrs = self.merge_requests.opened.where(target_branch: branch_name).to_a
mrs = mrs.select(&:last_commit).select { |mr| c_ids.include?(mr.last_commit.id) }
mrs.uniq.each do |merge_request|
MergeRequests::MergeService.new.execute(merge_request, user, nil)
end
# Update code for merge requests into project between project branches
mrs = self.merge_requests.opened.by_branch(branch_name).to_a
# Update code for merge requests between project and project fork
mrs += self.fork_merge_requests.opened.by_branch(branch_name).to_a
mrs.uniq.each do |merge_request|
merge_request.reload_code
merge_request.mark_as_unchecked
end
# Add comment about pushing new commits to merge requests
comment_mr_with_commits(branch_name, commits, user)
true
end
def comment_mr_with_commits(branch_name, commits, user)
mrs = self.origin_merge_requests.opened.where(source_branch: branch_name).to_a
mrs += self.fork_merge_requests.opened.where(source_branch: branch_name).to_a
mrs.uniq.each do |merge_request|
Note.create_new_commits_note(merge_request, merge_request.project,
user, commits)
end
MergeRequests::RefreshService.new(self, user).
execute(oldrev, newrev, ref)
end
def valid_repo?
......
......@@ -37,13 +37,12 @@ class FlowdockService < Service
end
def execute(push_data)
repo_path = File.join(Gitlab.config.gitlab_shell.repos_path, "#{project.path_with_namespace}.git")
Flowdock::Git.post(
push_data[:ref],
push_data[:before],
push_data[:after],
token: token,
repo: repo_path,
repo: project.repository.path_to_repo,
repo_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}",
commit_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/commit/%s",
diff_url: "#{Gitlab.config.gitlab.url}/#{project.path_with_namespace}/compare/%s...%s",
......
......@@ -38,14 +38,13 @@ class GemnasiumService < Service
end
def execute(push_data)
repo_path = File.join(Gitlab.config.gitlab_shell.repos_path, "#{project.path_with_namespace}.git")
Gemnasium::GitlabService.execute(
ref: push_data[:ref],
before: push_data[:before],
after: push_data[:after],
token: token,
api_key: api_key,
repo: repo_path
repo: project.repository.path_to_repo
)
end
end
......@@ -28,7 +28,7 @@ class GitlabCiService < CiService
end
def commit_status_path(sha)
project_url + "/builds/#{sha}/status.json?token=#{token}"
project_url + "/commits/#{sha}/status.json?token=#{token}"
end
def get_ci_build(sha)
......@@ -55,7 +55,7 @@ class GitlabCiService < CiService
end
def build_page(sha)
project_url + "/builds/#{sha}"
project_url + "/commits/#{sha}"
end
def builds_path
......
......@@ -30,24 +30,20 @@ class SlackService < Service
def fields
[
{ type: 'text', name: 'webhook', placeholder: '' }
{ type: 'text', name: 'webhook', placeholder: 'https://hooks.slack.com/services/...' }
]
end
def execute(push_data)
return unless webhook.present?
message = SlackMessage.new(push_data.merge(
project_url: project_url,
project_name: project_name
))
credentials = webhook.match(/([\w-]*).slack.com.*services\/(.*)/)
if credentials.present?
subdomain = credentials[1]
token = credentials[2].split("token=").last
notifier = Slack::Notifier.new(subdomain, token)
notifier.ping(message.pretext, attachments: message.attachments)
end
notifier = Slack::Notifier.new(webhook)
notifier.ping(message.pretext, attachments: message.attachments)
end
private
......
......@@ -226,6 +226,11 @@ class User < ActiveRecord::Base
where("lower(name) LIKE :query OR lower(email) LIKE :query OR lower(username) LIKE :query", query: "%#{query.downcase}%")
end
def by_login(login)
where('lower(username) = :value OR lower(email) = :value',
value: login.to_s.downcase).first
end
def by_username_or_id(name_or_id)
where('users.username = ? OR users.id = ?', name_or_id.to_s, name_or_id.to_i).first
end
......@@ -493,6 +498,14 @@ class User < ActiveRecord::Base
end
end
def hook_attrs
{
name: name,
username: username,
avatar_url: avatar_url
}
end
def ensure_namespace_correct
# Ensure user has namespace
self.create_namespace!(path: self.username, name: self.username) unless self.namespace
......
......@@ -160,19 +160,19 @@ class GitPushService
ref_parts = ref.split('/')
# Return if this is not a push to a branch (e.g. new commits)
ref_parts[1] =~ /heads/ && oldrev != "0000000000000000000000000000000000000000"
ref_parts[1] =~ /heads/ && oldrev != Gitlab::Git::BLANK_SHA
end
def push_to_new_branch?(ref, oldrev)
ref_parts = ref.split('/')
ref_parts[1] =~ /heads/ && oldrev == "0000000000000000000000000000000000000000"
ref_parts[1] =~ /heads/ && oldrev == Gitlab::Git::BLANK_SHA
end
def push_remove_branch?(ref, newrev)
ref_parts = ref.split('/')
ref_parts[1] =~ /heads/ && newrev == "0000000000000000000000000000000000000000"
ref_parts[1] =~ /heads/ && newrev == Gitlab::Git::BLANK_SHA
end
def push_to_branch?(ref)
......
......@@ -4,7 +4,7 @@ module Issues
private
def execute_hooks(issue, action = 'open')
issue_data = issue.to_hook_data
issue_data = issue.to_hook_data(current_user)
issue_url = Gitlab::UrlBuilder.new(:issue).build(issue.id)
issue_data[:object_attributes].merge!(url: issue_url, action: action)
issue.project.execute_hooks(issue_data, :issue_hooks)
......
......@@ -13,7 +13,8 @@ module MergeRequests
def execute_project_hooks(merge_request)
if merge_request.project
merge_request.project.execute_hooks(merge_request.to_hook_data, :merge_request_hooks)
hook_data = merge_request.to_hook_data(current_user)
merge_request.project.execute_hooks(hook_data, :merge_request_hooks)
end
end
end
......
......@@ -7,7 +7,8 @@ module MergeRequests
def execute_hooks(merge_request)
if merge_request.project
merge_request.project.execute_hooks(merge_request.to_hook_data, :merge_request_hooks)
hook_data = merge_request.to_hook_data(current_user)
merge_request.project.execute_hooks(hook_data, :merge_request_hooks)
end
end
end
......
module MergeRequests
class RefreshService < MergeRequests::BaseService
def execute(oldrev, newrev, ref)
return true unless ref =~ /heads/
@branch_name = ref.gsub("refs/heads/", "")
@fork_merge_requests = @project.fork_merge_requests.opened
@commits = @project.repository.commits_between(oldrev, newrev)
close_merge_requests
reload_merge_requests
comment_mr_with_commits
true
end
private
# Collect open merge requests that target same branch we push into
# and close if push to master include last commit from merge request
# We need this to close(as merged) merge requests that were merged into
# target branch manually
def close_merge_requests
commit_ids = @commits.map(&:id)
merge_requests = @project.merge_requests.opened.where(target_branch: @branch_name).to_a
merge_requests = merge_requests.select(&:last_commit)
merge_requests = merge_requests.select do |merge_request|
commit_ids.include?(merge_request.last_commit.id)
end
merge_requests.uniq.select(&:source_project).each do |merge_request|
MergeRequests::MergeService.new.execute(merge_request, @current_user, nil)
end
end
# Refresh merge request diff if we push to source or target branch of merge request
# Note: we should update merge requests from forks too
def reload_merge_requests
merge_requests = @project.merge_requests.opened.by_branch(@branch_name).to_a
merge_requests += @fork_merge_requests.by_branch(@branch_name).to_a
merge_requests = filter_merge_requests(merge_requests)
merge_requests.each do |merge_request|
merge_request.reload_code
merge_request.mark_as_unchecked
end
end
# Add comment about pushing new commits to merge requests
def comment_mr_with_commits
merge_requests = @project.origin_merge_requests.opened.where(source_branch: @branch_name).to_a
merge_requests += @fork_merge_requests.where(source_branch: @branch_name).to_a
merge_requests = filter_merge_requests(merge_requests)
merge_requests.each do |merge_request|
Note.create_new_commits_note(merge_request, merge_request.project,
@current_user, @commits)
end
end
def filter_merge_requests(merge_requests)
merge_requests.uniq.select(&:source_project)
end
end
end
......@@ -18,7 +18,7 @@ class SystemHooksService
def build_event_data(model, event)
data = {
event_name: build_event_name(model, event),
created_at: model.created_at
created_at: model.created_at.xmlschema
}
case model
......
......@@ -26,6 +26,10 @@ class AttachmentUploader < CarrierWave::Uploader::Base
Gitlab.config.gitlab.relative_url_root + "/files/#{model.class.to_s.underscore}/#{model.id}/#{file.filename}"
end
def url
Gitlab.config.gitlab.relative_url_root + super unless super.nil?
end
def file_storage?
self.class.storage == CarrierWave::Storage::File
end
......
......@@ -6,5 +6,5 @@
title:
%code= @key.title
%p
If this key was added in error, you can remove it here:
If this key was added in error, you can remove it under
= link_to "SSH Keys", profile_keys_url
......@@ -2,6 +2,6 @@ Hi <%= @user.name %>!
A new public key was added to your account:
title.................. <%= @key.title %>
Title: <%= @key.title %>
If this key was added in error, you can remove it here: <%= profile_keys_url %>
If this key was added in error, you can remove it at <%= profile_keys_url %>
......@@ -23,5 +23,6 @@
tree_join(@commit.sha, @path)), class: 'btn btn-small'
- if allowed_tree_edit?
= link_to '#modal-remove-blob', class: "remove-blob btn btn-small btn-remove", "data-toggle" => "modal" do
= button_tag class: 'remove-blob btn btn-small btn-remove',
'data-toggle' => 'modal', 'data-target' => '#modal-remove-blob' do
Remove
......@@ -10,7 +10,10 @@
- if @commit.parent_ids.present?
= view_file_btn(@commit.parent_id, diff_file, project)
- else
%span= diff_file.new_path
- if diff_file.renamed_file
%span= "#{diff_file.old_path} renamed to #{diff_file.new_path}"
- else
%span= diff_file.new_path
- if diff_file.mode_changed?
%span.file-mode= "#{diff_file.diff.a_mode}#{diff_file.diff.b_mode}"
......
......@@ -39,7 +39,7 @@
Open
.creator
Created by #{link_to_member(@project, @issue.author)} #{time_ago_with_tooltip(@issue.created_at)}
Created by #{link_to_member(@project, @issue.author)} #{issue_timestamp(@issue)}
%h4.title
= gfm escape_once(@issue.title)
......
......@@ -10,11 +10,11 @@
- target_remote = @merge_request.target_project.namespace.nil? ? "target" :@merge_request.target_project.namespace.path
%p
%strong Step 1.
Checkout the branch we are going to merge and pull in the code
Fetch the code and create a new branch pointing to it
%pre.dark
:preserve
git checkout -b #{@merge_request.source_project_path}-#{@merge_request.source_branch} #{@merge_request.target_branch}
git pull #{@merge_request.source_project.http_url_to_repo} #{@merge_request.source_branch}
git fetch #{@merge_request.source_project.http_url_to_repo} #{@merge_request.source_branch}
git checkout -b #{@merge_request.source_project_path}-#{@merge_request.source_branch} FETCH_HEAD
%p
%strong Step 2.
Merge the branch and push the changes to GitLab
......
......@@ -19,14 +19,14 @@
Encoding
.col-sm-10
= select_tag :encoding, options_for_select([ "base64", "text" ], "text"), class: 'form-control'
= render 'shared/commit_message_container', params: params,
placeholder: 'Add new file'
.file-holder
.file-title
%i.fa.fa-file
.file-content.code
%pre#editor= params[:content]
= render 'shared/commit_message_container', params: params,
placeholder: 'Add new file'
= hidden_field_tag 'content', '', id: 'file-content'
= render 'projects/commit_button', ref: @ref,
cancel_path: project_tree_path(@project, @id)
......
......@@ -59,7 +59,7 @@
- if note.attachment.image?
= link_to note.attachment.secure_url, target: '_blank' do
= image_tag note.attachment.secure_url, class: 'note-image-attach'
.attachment.pull-right
.attachment
= link_to note.attachment.secure_url, target: "_blank" do
%i.fa.fa-paperclip
= note.attachment_identifier
......
......@@ -4,6 +4,9 @@
= link_to project_commits_path(@project, tag.name), class: "" do
%i.fa.fa-tag
= tag.name
- if tag.message.present?
&nbsp;
= tag.message
.pull-right
- if can? current_user, :download_code, @project
= render 'projects/repositories/download_archive', ref: tag.name, btn_class: 'btn-grouped btn-group-small'
......
......@@ -5,7 +5,7 @@
- unless @project.personal? && user == current_user
.pull-left
= form_for(member, as: :project_member, url: project_team_member_path(@project, member.user)) do |f|
= f.select :access_level, options_for_select(ProjectMember.access_roles, member.access_level), {}, class: "medium project-access-select span2 trigger-submit"
= f.select :access_level, options_for_select(ProjectMember.access_roles, member.access_level), {}, class: "trigger-submit"
&nbsp;
= link_to project_team_member_path(@project, user), data: { confirm: remove_from_project_team_message(@project, user)}, method: :delete, class: "btn-tiny btn btn-remove", title: 'Remove user from team' do
%i.fa.fa-minus.fa-inverse
......
......@@ -22,11 +22,6 @@ module Gitlab
# :all can be used as a placeholder for all plugins not explicitly named.
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
# 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.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
# config.i18n.default_locale = :de
......
......@@ -15,6 +15,7 @@
# Use at least one worker per core if you're on a dedicated server,
# more will usually help for _short_ waits on databases/caches.
# The minimum is 2
worker_processes 2
# Since Unicorn is never exposed to outside clients, it does not need to
......
password = if ENV['GITLAB_ROOT_PASSWORD'].blank?
"5iveL!fe"
else
ENV['GITLAB_ROOT_PASSWORD']
end
if ENV['GITLAB_ROOT_PASSWORD'].blank?
password = '5iveL!fe'
expire_time = Time.now
else
password = ENV['GITLAB_ROOT_PASSWORD']
expire_time = nil
end
admin = User.create(
email: "admin@example.com",
......@@ -10,7 +12,7 @@ admin = User.create(
username: 'root',
password: password,
password_confirmation: password,
password_expires_at: Time.now,
password_expires_at: expire_time,
theme_id: Gitlab::Theme::MARS
)
......
......@@ -23,7 +23,7 @@ class SerializeServiceProperties < ActiveRecord::Migration
associations[service.type.to_sym].each do |attribute|
service.send("#{attribute}=", service.attributes[attribute.to_s])
end
service.save!
service.save
end
remove_column :services, :project_url, :string
......
......@@ -10,7 +10,7 @@ class MoveSlackServiceToWebhook < ActiveRecord::Migration
slack_service.properties.delete('subdomain')
# Room is configured on the Slack side
slack_service.properties.delete('room')
slack_service.save!
slack_service.save
end
end
end
......
......@@ -211,3 +211,11 @@ Parameters:
It return 200 if succeed, 404 if the branch to be deleted does not exist
or 400 for other reasons. In case of an error, an explaining message is provided.
Success response:
```json
{
"branch_name": "my-removed-branch"
}
```
......@@ -186,6 +186,7 @@ Parameters:
"target_id": 830,
"target_type": "Issue",
"author_id": 1,
"author_username": "john",
"data": null,
"target_title": "Public project search field"
},
......@@ -196,6 +197,7 @@ Parameters:
"target_id": null,
"target_type": null,
"author_id": 1,
"author_username": "john",
"data": {
"before": "50d4420237a9de7be1304607147aec22e4a14af7",
"after": "c5feabde2d8cd023215af4d2ceeb7a64839fc428",
......@@ -231,6 +233,7 @@ Parameters:
"target_id": 840,
"target_type": "Issue",
"author_id": 1,
"author_username": "john",
"data": null,
"target_title": "Finish & merge Code search PR"
}
......
......@@ -56,6 +56,7 @@ Parameters:
[
{
"name": "v1.0.0",
"message": "Release 1.0.0",
"commit": {
"id": "2695effb5807a22ff3d138d593fd856244e155e7",
"parents": [],
......@@ -67,10 +68,11 @@ Parameters:
"committed_date": "2012-05-28T04:42:42-07:00",
"committer_email": "jack@example.com"
},
"protected": false
}
]
```
The message will be `nil` when creating a lightweight tag otherwise
it will contain the annotation.
It returns 200 if the operation succeed. In case of an error,
405 with an explaining error message is returned.
......
......@@ -78,7 +78,8 @@ GET /users
"is_admin": false,
"avatar_url": "http://localhost:3000/uploads/user/avatar/1/cd8.jpeg",
"can_create_group": true,
"can_create_project": true
"can_create_project": true,
"projects_limit": 100
}
]
```
......@@ -140,7 +141,8 @@ Parameters:
"color_scheme_id": 2,
"is_admin": false,
"can_create_group": true,
"can_create_project": true
"can_create_project": true,
"projects_limit": 100
}
```
......@@ -240,7 +242,8 @@ GET /user
"color_scheme_id": 2,
"is_admin": false,
"can_create_group": true,
"can_create_project": true
"can_create_project": true,
"projects_limit": 100
}
```
......
......@@ -76,6 +76,7 @@ Is the system packaged Git too old? Remove it and compile from source.
cd /tmp
curl -L --progress https://www.kernel.org/pub/software/scm/git/git-2.1.2.tar.gz | tar xz
cd git-2.1.2/
./configure
make prefix=/usr/local all
# Install into /usr/local/bin
......@@ -91,7 +92,7 @@ Then select 'Internet Site' and press enter to confirm the hostname.
## 2. Ruby
The use of ruby version managers such as [RVM](http://rvm.io/), [rbenv](https://github.com/sstephenson/rbenv) or [chruby](https://github.com/postmodern/chruby) with GitLab in production frequently leads to hard to diagnose problems. For example, GitLab Shell is called from OpenSSH and having a version manager can prevent pushing and pulling over SSH. Version managers are not supported and we strongly advise everyone to follow the instructions below to use a system ruby.
The use of Ruby version managers such as [RVM](http://rvm.io/), [rbenv](https://github.com/sstephenson/rbenv) or [chruby](https://github.com/postmodern/chruby) with GitLab in production frequently leads to hard to diagnose problems. For example, GitLab Shell is called from OpenSSH and having a version manager can prevent pushing and pulling over SSH. Version managers are not supported and we strongly advise everyone to follow the instructions below to use a system Ruby.
Remove the old Ruby 1.8 if present
......@@ -126,7 +127,8 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da
# Login to PostgreSQL
sudo -u postgres psql -d template1
# Create a user for GitLab.
# Create a user for GitLab
# Do not type the 'template1=#', this is part of the prompt
template1=# CREATE USER git CREATEDB;
# Create the GitLab production database & grant all privileges on database
......@@ -137,6 +139,9 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da
# Try connecting to the new database with the new user
sudo -u git -H psql -d gitlabhq_production
# Quit the database session
gitlabhq_production> \q
## 5. Redis
......@@ -194,7 +199,7 @@ We recommend using a PostgreSQL database. For MySQL check [MySQL setup guide](da
# Make sure GitLab can write to the log/ and tmp/ directories
sudo chown -R git log/
sudo chown -R git tmp/
sudo chmod -R u+rwX log/
sudo chmod -R u+rwX,go-w log/
sudo chmod -R u+rwX tmp/
# Create directory for satellites
......
......@@ -4,15 +4,23 @@
To enable Slack integration you must create an Incoming WebHooks integration on Slack;
1. Sign in to [Slack](https://slack.com) (https://YOURSUBDOMAIN.slack.com/services)
1. Click on the Integrations menu at the top of the page.
1. Add a new Integration.
1. [Sign in to Slack](https://slack.com/signin)
1. Select **Configure Integrations** from the dropdown next to your team name.
1. Select the **All Services** tab
1. Click **Add** next to Incoming Webhooks
1. Pick Incoming WebHooks
1. Choose the channel name you want to send notifications to, in the Settings section
1. Add Integrations.
- Optional step; You can change bot's name and avatar by clicking "change the name of your bot", and "change the icon" after that you have to click "Save settings".
Now, Slack is ready to get external hooks. Before you leave this page don't forget to get the Token that you'll need on GitLab. You can find it by clicking Expand button, located in the "Instructions for creating Incoming WebHooks" section. It's a random alpha-numeric text 24 characters long.
1. Choose the channel name you want to send notifications to
1. Click **Add Incoming WebHooks Integration**Add Integrations.
- Optional step; You can change bot's name and avatar by clicking modifying the bot name or avatar under **Integration Settings**.
1. Copy the **Webhook URL**, we'll need this later for GitLab.
## On GitLab
......@@ -26,10 +34,8 @@ After Slack is ready we need to setup GitLab. Here are the steps to achieve this
1. Fill in your Slack details
- Mark as active it
- Type your subdomain's prefix (If your subdomain is https://somedomain.slack.com you only have to type the somedomain)
- Type in the token you got from Slack
- Type in the channel name you want to use (eg. #announcements)
- Mark it as active
- Paste in the webhook url you got from Slack
Have fun :)
......
# Import
# Import bare repositories into your GitLab instance
## Import bare repositories into GitLab project instance
## Notes
Notes:
- The owner of the project will be the first admin
- The groups will be created as needed
- The owner of the group will be the first admin
- Existing projects will be skipped
- project owner will be a first admin
- groups will be created as needed
- group owner will be the first admin
- existing projects will be skipped
## How to use
How to use:
### Create a new folder inside the git repositories path. This will be the name of the new group.
1. copy your bare repos under git repos_path (see `config/gitlab.yml` gitlab_shell -> repos_path)
1. run the command below
- For omnibus-gitlab, it is located at: `/var/opt/gitlab/git-data/repositories` by default, unless you changed
it in the `/etc/gitlab/gitlab.rb` file.
- For manual installations, it is usually located at: `/home/git/repositories` or you can see where
your repositories are located by looking at `config/gitlab.yml` under the `gitlab_shell => repos_path` entry.
### Copy your bare repositories inside this newly created folder:
```
$ cp -r /old/git/foo.git/ /home/git/repositories/new_group/
```
### Run the command below depending on your type of installation:
#### Omnibus Installation
```
$ sudo gitlab-rake gitlab:import:repos
```
# omnibus-gitlab
sudo gitlab-rake gitlab:import:repos
# installation from source or cookbook
bundle exec rake gitlab:import:repos RAILS_ENV=production
#### Manual Installation
Before running this command you need to change the directory to where your GitLab installation is located:
```
$ cd /home/git/gitlab
$ sudo -u git -H bundle exec rake gitlab:import:repos RAILS_ENV=production
```
Example output:
#### Example output
```
Processing abcd.git
......
......@@ -143,35 +143,28 @@ Make sure the code quality indicators are green / good.
- [![Coverage Status](https://coveralls.io/repos/gitlabhq/gitlabhq/badge.png?branch=master)](https://coveralls.io/r/gitlabhq/gitlabhq)
### **4. Set VERSION**
### **4. Run release tool**
Change version in VERSION to `x.x.0.rc1`.
**Make sure EE `master` has latest changes from CE `master`**
### **5. Tag**
Create an annotated tag that points to the version change commit:
Get release tools
```
git tag -a vx.x.0.rc1 -m 'Version x.x.0.rc1'
git clone git@dev.gitlab.org:gitlab/release-tools.git
cd release-tools
```
Tags should be created for both GitLab CE and GitLab EE. Don't forget to push tags to all remotes.
Release candidate creates stable branch from master.
So we need to sync master branch between all CE remotes. Also do same for EE.
```
git push remote_name vx.x.0.rc1
bundle exec rake sync
```
### **6. Create stable branches**
For GitLab EE, append `-ee` to the branch.
`x-x-stable-ee`
Create release candidate and stable branch:
```
git checkout master
git pull
git checkout -b x-x-stable
git push <remote> x-x-stable
bundle exec rake release["x.x.0.rc1"]
```
Now developers can use master for merging new features.
......@@ -245,69 +238,45 @@ create an issue about it in order to discuss the next steps after the release.
# **22nd - Release CE and EE**
For GitLab EE, append `-ee` to the branches and tags.
**Make sure EE `x-x-stable-ee` has latest changes from CE `x-x-stable`**
`x-x-stable-ee`
`v.x.x.0-ee`
### **1. Release code**
Note: Merge CE into EE if needed.
### **1. Set VERSION to x.x.x and push**
- Change the GITLAB_SHELL_VERSION file in `master` of the CE repository if the version changed.
- Change the GITLAB_SHELL_VERSION file in `master` of the EE repository if the version changed.
- Change the VERSION file in `master` branch of the CE repository and commit and push to origin.
- Change the VERSION file in `master` branch of the EE repository and commit and push to origin.
### **2. Update installation.md**
Update [installation.md](/doc/install/installation.md) to the newest version in master.
### **3. Push latest changes from x-x-stable branch to dev.gitlab.org**
Get release tools
```
git checkout -b x-x-stable
git push origin x-x-stable
git clone git@dev.gitlab.org:gitlab/release-tools.git
cd release-tools
```
### **4. Build the Omnibus packages**
Follow the [release doc in the Omnibus repository](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/release.md).
This can happen before tagging because Omnibus uses tags in its own repo and SHA1's to refer to the GitLab codebase.
### **5. Create annotated tag vx.x.x**
In `x-x-stable` branch check for the SHA-1 of the commit with VERSION file changed. Tag that commit,
Bump version, create release tag and push to remotes:
```
git tag -a vx.x.0 -m 'Version x.x.0' xxxxx
bundle exec rake release["x.x.0"]
```
where `xxxxx` is SHA-1.
### **6. Push the tag and x-x-stable branch to the remotes**
### **2. Update installation.md**
For GitLab CE, push to dev, GitLab.com and GitHub.
Update [installation.md](/doc/install/installation.md) to the newest version in master.
For GitLab EE, push to the subscribers repo.
Make sure the branch is marked 'protected' on each of the remotes you pushed to.
### **3. Build the Omnibus packages**
Follow the [release doc in the Omnibus repository](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/release.md).
This can happen before tagging because Omnibus uses tags in its own repo and SHA1's to refer to the GitLab codebase.
```
git push <remote> x-x-stable(-ee)
git push <remote> vx.x.0
```
### **7. Publish packages for new release**
### **4. Publish packages for new release**
Update `downloads/index.html` and `downloads/archive/index.html` in `www-gitlab-com` repository.
### **8. Publish blog for new release**
### **5. Publish blog for new release**
Merge the [blog merge request](#1-prepare-the-blog-post) in `www-gitlab-com` repository.
### **9. Tweet to blog**
### **6. Tweet to blog**
Send out a tweet to share the good news with the world.
List the most important features and link to the blog post.
......
......@@ -10,6 +10,8 @@ Otherwise include it in the monthly release and note there was a regression fix
## Release Procedure
### Preparation
1. Verify that the issue can be reproduced
1. Note in the 'GitLab X.X regressions' that you will create a patch
1. Create an issue on private GitLab development server
......@@ -17,12 +19,33 @@ Otherwise include it in the monthly release and note there was a regression fix
1. Fix the issue on a feature branch, do this on the private GitLab development server
1. Consider creating and testing workarounds
1. After the branch is merged into master, cherry pick the commit(s) into the current stable branch
1. Make sure that the build has passed and all tests are passing
1. In a separate commit in the stable branch update the CHANGELOG
1. For EE, update the CHANGELOG-EE if it is EE specific fix. Otherwise, merge the stable CE branch and add to CHANGELOG-EE "Merge community edition changes for version X.X.X"
1. In a separate commit in the stable branch update the VERSION
1. Create an annotated tag vX.X.X for CE and another patch release for EE `git tag -a vx.x.x -m 'Version x.x.x'`
1. Make sure that the build has passed and all tests are passing
1. Push the code and the tags to all the CE and EE repositories
### Bump version
Get release tools
```
git clone git@dev.gitlab.org:gitlab/release-tools.git
cd release-tools
```
Bump version in stable branch, create release tag and push to remotes:
```
bundle exec rake release["x.x.x"]
```
Or if you need to release only EE:
```
CE=false be rake release['x.x.x']
```
### Release
1. Apply the patch to GitLab Cloud and the private GitLab development server
1. [Build new packages with the latest version](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/doc/release.md)
1. Cherry-pick the changelog update back into master
......
# 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
......@@ -154,14 +154,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/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/gitlab` 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/gitlab-ssl` the same as https://gitlab.com/gitlab-org/gitlab-ce/blob/7-3-stable/lib/support/nginx/gitlab-ssl but with your settings.
* HTTP setups: Make `/etc/nginx/sites-available/gitlab` 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/gitlab-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
......@@ -267,6 +267,7 @@ mysql> \q
# Set production -> username: git
# 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 (6.0)
......
......@@ -9,6 +9,7 @@
```bash
cd /home/git/gitlab
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production
```
### 2. Get latest code
......
......@@ -26,16 +26,14 @@ sudo -u git -H git checkout LATEST_TAG
Replace LATEST_TAG with the latest GitLab tag you want to upgrade to, for example `v6.6.3`.
### 3. Update gitlab-shell if it is not the latest version
### 3. Update gitlab-shell to the corresponding version
```bash
cd /home/git/gitlab-shell
sudo -u git -H git fetch
sudo -u git -H git checkout LATEST_TAG
sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_SHELL_VERSION`
```
Replace LATEST_TAG with the latest GitLab Shell tag you want to upgrade to, for example `v1.7.9`.
### 4. Install libs, migrations, etc.
```bash
......
......@@ -43,28 +43,31 @@ Check if GitLab and its dependencies are configured correctly:
If all items are green, then congratulations upgrade is complete!
## 5. Upgrade GitLab Shell (if needed)
## 5. Upgrade GitLab Shell
If the `gitlab:check` task reports an outdated version of `gitlab-shell` you should upgrade it.
Upgrade it by running the commands below after replacing 2.0.1 with the correct version number:
GitLab Shell might be outdated, running the commands below ensures you're using a compatible version:
```
cd /home/git/gitlab-shell
sudo -u git -H git fetch
sudo -u git -H git checkout v2.0.1
sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_SHELL_VERSION`
```
## One line upgrade command
You've read through the entire guide and probably already did all the steps one by one.
Here is a one line command with step 1 to 4 for the next time you upgrade:
Here is a one line command with step 1 to 5 for the next time you upgrade:
```bash
cd /home/git/gitlab; sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production; \
cd /home/git/gitlab; \
sudo -u git -H bundle exec rake gitlab:backup:create RAILS_ENV=production; \
sudo service gitlab stop; \
if [ -f bin/upgrade.rb ]; then sudo -u git -H ruby bin/upgrade.rb -y; else sudo -u git -H ruby script/upgrade.rb -y; fi; \
cd /home/git/gitlab-shell; \
sudo -u git -H git fetch; \
sudo -u git -H git checkout v`cat /home/git/gitlab/GITLAB_SHELL_VERSION`; \
cd /home/git/gitlab; \
sudo service gitlab start; \
sudo service nginx restart; sudo -u git -H bundle exec rake gitlab:check RAILS_ENV=production
```
......@@ -63,6 +63,11 @@ Triggered when a new issue is created or an existing issue was updated/closed/re
```json
{
"object_kind": "issue",
"user": {
"name": "Administrator",
"username": "root",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
},
"object_attributes": {
"id": 301,
"title": "New API: create/update/delete file",
......@@ -92,6 +97,11 @@ Triggered when a new merge request is created or an existing merge request was u
```json
{
"object_kind": "merge_request",
"user": {
"name": "Administrator",
"username": "root",
"avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
},
"object_attributes": {
"id": 99,
"target_branch": "master",
......
......@@ -29,7 +29,7 @@ class Spinach::Features::EventFilters < Spinach::FeatureSteps
step 'this project has push event' do
data = {
before: "0000000000000000000000000000000000000000",
before: Gitlab::Git::BLANK_SHA,
after: "0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e",
ref: "refs/heads/new_design",
user_id: @user.id,
......
......@@ -109,12 +109,12 @@ class Spinach::Features::ProjectServices < Spinach::FeatureSteps
step 'I fill Slack settings' do
check 'Active'
fill_in 'Webhook', with: 'https://gitlabhq.slack.com/services/hooks?token=cdIj4r4LfXUOySDUjp0tk3OI'
fill_in 'Webhook', with: 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685'
click_button 'Save'
end
step 'I should see Slack service settings saved' do
find_field('Webhook').value.should == 'https://gitlabhq.slack.com/services/hooks?token=cdIj4r4LfXUOySDUjp0tk3OI'
find_field('Webhook').value.should == 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685'
end
step 'I click Pushover service link' do
......
......@@ -78,7 +78,7 @@ class Spinach::Features::ProjectSourceBrowseFiles < Spinach::FeatureSteps
end
step 'I click on "Remove"' do
click_link 'Remove'
click_button 'Remove'
end
step 'I click on "Remove file"' do
......
......@@ -32,7 +32,7 @@ module SharedProject
@project = Project.find_by(name: "Shop")
data = {
before: "0000000000000000000000000000000000000000",
before: Gitlab::Git::BLANK_SHA,
after: "6d394385cf567f80a8fd85055db1ab4c5295806f",
ref: "refs/heads/fix",
user_id: @user.id,
......
......@@ -82,6 +82,7 @@ module API
authorize_push_project
result = CreateBranchService.new(user_project, current_user).
execute(params[:branch_name], params[:ref])
if result[:status] == :success
present result[:branch],
with: Entities::RepoObject,
......@@ -104,7 +105,9 @@ module API
execute(params[:branch])
if result[:status] == :success
true
{
branch_name: params[:branch]
}
else
render_api_error!(result[:message], result[:return_code])
end
......
......@@ -16,7 +16,8 @@ module API
class UserFull < User
expose :email
expose :theme_id, :color_scheme_id, :extern_uid, :provider
expose :theme_id, :color_scheme_id, :extern_uid, :provider, \
:projects_limit
expose :can_create_group?, as: :can_create_group
expose :can_create_project?, as: :can_create_project
end
......@@ -73,6 +74,25 @@ module API
end
end
class RepoTag < Grape::Entity
expose :name
expose :message do |repo_obj, _options|
if repo_obj.respond_to?(:message)
repo_obj.message
else
nil
end
end
expose :commit do |repo_obj, options|
if repo_obj.respond_to?(:commit)
repo_obj.commit
elsif options[:project]
options[:project].repository.commit(repo_obj.target)
end
end
end
class RepoObject < Grape::Entity
expose :name
......@@ -164,6 +184,12 @@ module API
expose :target_id, :target_type, :author_id
expose :data, :target_title
expose :created_at
expose :author_username do |event, options|
if event.author
event.author.username
end
end
end
class Namespace < Grape::Entity
......
......@@ -23,7 +23,8 @@ module API
# Example Request:
# GET /projects/:id/repository/tags
get ":id/repository/tags" do
present user_project.repo.tags.sort_by(&:name).reverse, with: Entities::RepoObject, project: user_project
present user_project.repo.tags.sort_by(&:name).reverse,
with: Entities::RepoTag, project: user_project
end
# Create tag
......@@ -43,7 +44,7 @@ module API
if result[:status] == :success
present result[:tag],
with: Entities::RepoObject,
with: Entities::RepoTag,
project: user_project
else
render_api_error!(result[:message], 400)
......
......@@ -91,7 +91,7 @@ module Backup
protected
def path_to_repo(project)
File.join(repos_path, project.path_with_namespace + '.git')
project.repository.path_to_repo
end
def path_to_bundle(project)
......
module Gitlab
class Auth
def find(login, password)
user = User.find_by(email: login) || User.find_by(username: login)
user = User.by_login(login)
# If no user is found, or it's an LDAP server, try LDAP.
# LDAP users are only authenticated via LDAP
......
......@@ -8,6 +8,13 @@ module Gitlab
end
end
class << self
def version_required
@version_required ||= File.read(Rails.root.
join('GITLAB_SHELL_VERSION')).strip
end
end
# Init new repository
#
# name - project path with namespace
......@@ -16,7 +23,8 @@ module Gitlab
# add_repository("gitlab/gitlab-ci")
#
def add_repository(name)
system "#{gitlab_shell_path}/bin/gitlab-projects", "add-project", "#{name}.git"
Gitlab::Utils.system_silent([gitlab_shell_projects_path,
'add-project', "#{name}.git"])
end
# Import repository
......@@ -27,7 +35,8 @@ module Gitlab
# import_repository("gitlab/gitlab-ci", "https://github.com/randx/six.git")
#
def import_repository(name, url)
system "#{gitlab_shell_path}/bin/gitlab-projects", "import-project", "#{name}.git", url, '240'
Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'import-project',
"#{name}.git", url, '240'])
end
# Move repository
......@@ -39,7 +48,8 @@ module Gitlab
# mv_repository("gitlab/gitlab-ci", "randx/gitlab-ci-new.git")
#
def mv_repository(path, new_path)
system "#{gitlab_shell_path}/bin/gitlab-projects", "mv-project", "#{path}.git", "#{new_path}.git"
Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'mv-project',
"#{path}.git", "#{new_path}.git"])
end
# Update HEAD for repository
......@@ -51,7 +61,8 @@ module Gitlab
# update_repository_head("gitlab/gitlab-ci", "3-1-stable")
#
def update_repository_head(path, branch)
system "#{gitlab_shell_path}/bin/gitlab-projects", "update-head", "#{path}.git", branch
Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'update-head',
"#{path}.git", branch])
end
# Fork repository to new namespace
......@@ -63,7 +74,8 @@ module Gitlab
# fork_repository("gitlab/gitlab-ci", "randx")
#
def fork_repository(path, fork_namespace)
system "#{gitlab_shell_path}/bin/gitlab-projects", "fork-project", "#{path}.git", fork_namespace
Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'fork-project',
"#{path}.git", fork_namespace])
end
# Remove repository from file system
......@@ -74,7 +86,8 @@ module Gitlab
# remove_repository("gitlab/gitlab-ci")
#
def remove_repository(name)
system "#{gitlab_shell_path}/bin/gitlab-projects", "rm-project", "#{name}.git"
Gitlab::Utils.system_silent([gitlab_shell_projects_path,
'rm-project', "#{name}.git"])
end
# Add repository branch from passed ref
......@@ -87,7 +100,8 @@ module Gitlab
# add_branch("gitlab/gitlab-ci", "4-0-stable", "master")
#
def add_branch(path, branch_name, ref)
system "#{gitlab_shell_path}/bin/gitlab-projects", "create-branch", "#{path}.git", branch_name, ref
Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'create-branch',
"#{path}.git", branch_name, ref])
end
# Remove repository branch
......@@ -99,7 +113,8 @@ module Gitlab
# rm_branch("gitlab/gitlab-ci", "4-0-stable")
#
def rm_branch(path, branch_name)
system "#{gitlab_shell_path}/bin/gitlab-projects", "rm-branch", "#{path}.git", branch_name
Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'rm-branch',
"#{path}.git", branch_name])
end
# Add repository tag from passed ref
......@@ -117,7 +132,7 @@ module Gitlab
cmd = %W(#{gitlab_shell_path}/bin/gitlab-projects create-tag #{path}.git
#{tag_name} #{ref})
cmd << message unless message.nil? || message.empty?
system *cmd
Gitlab::Utils.system_silent(cmd)
end
# Remove repository tag
......@@ -129,7 +144,8 @@ module Gitlab
# rm_tag("gitlab/gitlab-ci", "v4.0")
#
def rm_tag(path, tag_name)
system "#{gitlab_shell_path}/bin/gitlab-projects", "rm-tag", "#{path}.git", tag_name
Gitlab::Utils.system_silent([gitlab_shell_projects_path, 'rm-tag',
"#{path}.git", tag_name])
end
# Add new key to gitlab-shell
......@@ -138,7 +154,8 @@ module Gitlab
# add_key("key-42", "sha-rsa ...")
#
def add_key(key_id, key_content)
system "#{gitlab_shell_path}/bin/gitlab-keys", "add-key", key_id, key_content
Gitlab::Utils.system_silent([gitlab_shell_keys_path,
'add-key', key_id, key_content])
end
# Batch-add keys to authorized_keys
......@@ -157,7 +174,8 @@ module Gitlab
# remove_key("key-342", "sha-rsa ...")
#
def remove_key(key_id, key_content)
system "#{gitlab_shell_path}/bin/gitlab-keys", "rm-key", key_id, key_content
Gitlab::Utils.system_silent([gitlab_shell_keys_path,
'rm-key', key_id, key_content])
end
# Remove all ssh keys from gitlab shell
......@@ -166,7 +184,7 @@ module Gitlab
# remove_all_keys
#
def remove_all_keys
system "#{gitlab_shell_path}/bin/gitlab-keys", "clear"
Gitlab::Utils.system_silent([gitlab_shell_keys_path, 'clear'])
end
# Add empty directory for storing repositories
......@@ -249,5 +267,13 @@ module Gitlab
def exists?(dir_name)
File.exists?(full_path(dir_name))
end
def gitlab_shell_projects_path
File.join(gitlab_shell_path, 'bin', 'gitlab-projects')
end
def gitlab_shell_keys_path
File.join(gitlab_shell_path, 'bin', 'gitlab-keys')
end
end
end
module Gitlab
module Git
BLANK_SHA = '0' * 40
end
end
......@@ -67,7 +67,7 @@ module Gitlab
if forced_push?(project, oldrev, newrev)
:force_push_code_to_protected_branches
# and we dont allow remove of protected branch
elsif newrev =~ /0000000/
elsif newrev == Gitlab::Git::BLANK_SHA
:remove_protected_branches
else
:push_code_to_protected_branches
......@@ -85,7 +85,7 @@ module Gitlab
def forced_push?(project, oldrev, newrev)
return false if project.empty_repo?
if oldrev !~ /00000000/ && newrev !~ /00000000/
if oldrev != Gitlab::Git::BLANK_SHA && newrev != Gitlab::Git::BLANK_SHA
missed_refs = IO.popen(%W(git --git-dir=#{project.repository.path_to_repo} rev-list #{oldrev} ^#{newrev})).read
missed_refs.split("\n").size > 0
else
......
......@@ -5,7 +5,8 @@ module Gitlab
#
# Returns true for a valid reference name, false otherwise
def validate(ref_name)
system *%W(git check-ref-format refs/#{ref_name})
Gitlab::Utils.system_silent(
%W(git check-ref-format refs/#{ref_name}))
end
end
end
......@@ -15,7 +15,6 @@ module Gitlab
{ title: "support", color: yellow },
{ title: "discussion", color: blue },
{ title: "suggestion", color: blue },
{ title: "feature", color: green },
{ title: "enhancement", color: green }
]
......
......@@ -67,8 +67,7 @@ module Gitlab
def default_regex_message
"can contain only letters, digits, '_', '-' and '.'. " \
"It must start with letter, digit or '_', optionally preceeded by '.'. " \
"It must not end in '.git'."
"Cannot start with '-' or end in '.git'" \
end
def default_regex
......
module Gitlab
module Utils
extend self
# Run system command without outputting to stdout.
#
# @param cmd [Array<String>]
# @return [Boolean]
def system_silent(cmd)
Popen::popen(cmd).last.zero?
end
end
end
## GitLab
## Maintainer: @randx
## Contributors: randx, yin8086, sashkab, orkoden, axilleas, bbodenmiller
##
## Lines starting with two hashes (##) are comments with information.
## Lines starting with one hash (#) are configuration parameters that can be uncommented.
......@@ -15,7 +15,7 @@
## - installing an old version of Nginx with the chunkin module [2] compiled in, or
## - using a newer version of Nginx.
##
## At the time of writing we do not know if either of these theoretical solutions works.
## At the time of writing we do not know if either of these theoretical solutions works.
## As a workaround users can use Git over SSH to push large files.
##
## [0] https://git.kernel.org/cgit/git/git.git/tree/Documentation/technical/http-protocol.txt#n99
......@@ -26,6 +26,7 @@
## configuration ##
###################################
##
## See installation.md#using-https for additional HTTPS configuration details.
upstream gitlab {
server unix:/home/git/gitlab/tmp/sockets/gitlab.socket fail_timeout=0;
......@@ -33,7 +34,8 @@ upstream gitlab {
## Normal HTTP host
server {
listen *:80 default_server;
listen 0.0.0.0:80 default_server;
listen [::]:80 default_server;
server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com
server_tokens off; ## Don't show the nginx version number, a security best practice
root /home/git/gitlab/public;
......@@ -42,6 +44,8 @@ server {
## Or if you want to accept large git objects over http
client_max_body_size 20m;
## See app/controllers/application_controller.rb for headers set
## Individual nginx logs for this GitLab vhost
access_log /var/log/nginx/gitlab_access.log;
error_log /var/log/nginx/gitlab_error.log;
......
## GitLab
## Contributors: randx, yin8086, sashkab, orkoden, axilleas
## Contributors: randx, yin8086, sashkab, orkoden, axilleas, bbodenmiller
##
## Modified from nginx http version
## Modified from http://blog.phusion.nl/2012/04/21/tutorial-setting-up-gitlab-on-debian-6/
......@@ -26,9 +26,8 @@
## [1] https://github.com/agentzh/chunkin-nginx-module#status
## [2] https://github.com/agentzh/chunkin-nginx-module
##
##
###################################
## SSL configuration ##
## configuration ##
###################################
##
## See installation.md#using-https for additional HTTPS configuration details.
......@@ -37,22 +36,24 @@ upstream gitlab {
server unix:/home/git/gitlab/tmp/sockets/gitlab.socket fail_timeout=0;
}
## Normal HTTP host
## Redirects all HTTP traffic to the HTTPS host
server {
listen *:80 default_server;
listen 0.0.0.0:80;
listen [::]:80 default_server;
server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com
server_tokens off; ## Don't show the nginx version number, a security best practice
## Redirects all traffic to the HTTPS host
root /nowhere; ## root doesn't have to be a valid path since we are redirecting
rewrite ^ https://$server_name$request_uri? permanent;
return 301 https://$server_name$request_uri;
access_log /var/log/nginx/gitlab_access.log;
error_log /var/log/nginx/gitlab_error.log;
}
## HTTPS host
server {
listen 443 ssl;
listen 0.0.0.0:443 ssl;
listen [::]:443 ssl default_server;
server_name YOUR_SERVER_FQDN; ## Replace this with something like gitlab.example.com
server_tokens off;
server_tokens off; ## Don't show the nginx version number, a security best practice
root /home/git/gitlab/public;
## Increase this if you want to upload large attachments
......@@ -70,12 +71,9 @@ server {
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
## [WARNING] The following header states that the browser should only communicate
## with your server over a secure connection for the next 24 months.
add_header Strict-Transport-Security max-age=63072000;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
## See app/controllers/application_controller.rb for headers set
## [Optional] If your certficate has OCSP, enable OCSP stapling to reduce the overhead and latency of running SSL.
## Replace with your ssl_trusted_certificate. For more info see:
......
......@@ -574,20 +574,16 @@ namespace :gitlab do
Gitlab::Shell.new.version
end
def required_gitlab_shell_version
File.read(File.join(Rails.root, "GITLAB_SHELL_VERSION")).strip
end
def gitlab_shell_major_version
required_gitlab_shell_version.split(".")[0].to_i
Gitlab::Shell.version_required.split('.')[0].to_i
end
def gitlab_shell_minor_version
required_gitlab_shell_version.split(".")[1].to_i
Gitlab::Shell.version_required.split('.')[1].to_i
end
def gitlab_shell_patch_version
required_gitlab_shell_version.split(".")[2].to_i
Gitlab::Shell.version_required.split('.')[2].to_i
end
def has_gitlab_shell3?
......
......@@ -4,7 +4,7 @@ namespace :gitlab do
task :install, [:tag, :repo] => :environment do |t, args|
warn_user_is_not_gitlab
default_version = File.read(File.join(Rails.root, "GITLAB_SHELL_VERSION")).strip
default_version = Gitlab::Shell.version_required
args.with_defaults(tag: 'v' + default_version, repo: "https://gitlab.com/gitlab-org/gitlab-shell.git")
user = Gitlab.config.gitlab.user
......@@ -76,7 +76,7 @@ namespace :gitlab do
desc "GITLAB | Build missing projects"
task build_missing_projects: :environment do
Project.find_each(batch_size: 1000) do |project|
path_to_repo = File.join(Gitlab.config.gitlab_shell.repos_path, "#{project.path_with_namespace}.git")
path_to_repo = project.repository.path_to_repo
if File.exists?(path_to_repo)
print '-'
else
......
......@@ -10,13 +10,21 @@ describe Gitlab::Auth do
password: password,
password_confirmation: password)
end
let(:username) { 'john' }
let(:username) { 'John' } # username isn't lowercase, test this
let(:password) { 'my-secret' }
it "should find user by valid login/password" do
expect( gl_auth.find(username, password) ).to eql user
end
it 'should find user by valid email/password with case-insensitive email' do
expect(gl_auth.find(user.email.upcase, password)).to eql user
end
it 'should find user by valid username/password with case-insensitive username' do
expect(gl_auth.find(username.upcase, password)).to eql user
end
it "should not find user with invalid password" do
password = 'wrong'
expect( gl_auth.find(username, password) ).to_not eql user
......
......@@ -55,12 +55,13 @@ describe Gitlab::GitAccess do
def changes
{
push_new_branch: '000000000 570e7b2ab refs/heads/wow',
push_new_branch: "#{Gitlab::Git::BLANK_SHA} 570e7b2ab refs/heads/wow",
push_master: '6f6d7e7ed 570e7b2ab refs/heads/master',
push_protected_branch: '6f6d7e7ed 570e7b2ab refs/heads/feature',
push_remove_protected_branch: '570e7b2ab 000000000 refs/heads/feature',
push_remove_protected_branch: "570e7b2ab #{Gitlab::Git::BLANK_SHA} "\
'refs/heads/feature',
push_tag: '6f6d7e7ed 570e7b2ab refs/tags/v1.0.0',
push_new_tag: '000000000 570e7b2ab refs/tags/v7.8.9',
push_new_tag: "#{Gitlab::Git::BLANK_SHA} 570e7b2ab refs/tags/v7.8.9",
push_all: ['6f6d7e7ed 570e7b2ab refs/heads/master', '6f6d7e7ed 570e7b2ab refs/heads/feature']
}
end
......
......@@ -36,7 +36,7 @@ describe Event do
@user = project.owner
data = {
before: "0000000000000000000000000000000000000000",
before: Gitlab::Git::BLANK_SHA,
after: "0220c11b9a3e6c69dc8fd35321254ca9a7b98f7e",
ref: "refs/heads/master",
user_id: @user.id,
......@@ -60,7 +60,6 @@ describe Event do
it { @event.push?.should be_true }
it { @event.proper?.should be_true }
it { @event.new_branch?.should be_true }
it { @event.tag?.should be_false }
it { @event.branch_name.should == "master" }
it { @event.author.should == @user }
......
......@@ -34,11 +34,11 @@ describe GitlabCiService do
end
describe :commit_status_path do
it { @service.commit_status_path("2ab7834c").should == "http://ci.gitlab.org/projects/2/builds/2ab7834c/status.json?token=verySecret"}
it { @service.commit_status_path("2ab7834c").should == "http://ci.gitlab.org/projects/2/commits/2ab7834c/status.json?token=verySecret"}
end
describe :build_page do
it { @service.build_page("2ab7834c").should == "http://ci.gitlab.org/projects/2/builds/2ab7834c"}
it { @service.build_page("2ab7834c").should == "http://ci.gitlab.org/projects/2/commits/2ab7834c"}
end
end
end
......@@ -249,6 +249,12 @@ describe Note do
its(:note) { should == "_mentioned in merge request !#{mergereq.iid}_" }
end
context 'commit contained in a merge request' do
subject { Note.create_cross_reference_note(mergereq.commits.first, mergereq, author, project) }
it { should be_nil }
end
context 'commit from issue' do
subject { Note.create_cross_reference_note(commit, issue, author, project) }
......
......@@ -145,63 +145,6 @@ describe Project do
end
end
describe 'comment merge requests with commits' do
before do
@user = create(:user)
group = create(:group)
group.add_owner(@user)
@project = create(:project, namespace: group)
@fork_project = Projects::ForkService.new(@project, @user).execute
@merge_request = create(:merge_request, source_project: @project,
source_branch: 'master',
target_branch: 'feature',
target_project: @project)
@fork_merge_request = create(:merge_request, source_project: @fork_project,
source_branch: 'master',
target_branch: 'feature',
target_project: @project)
@commits = @merge_request.commits
end
context 'push to origin repo source branch' do
before do
@project.comment_mr_with_commits('master', @commits, @user)
end
it { @merge_request.notes.should_not be_empty }
it { @fork_merge_request.notes.should be_empty }
end
context 'push to origin repo target branch' do
before do
@project.comment_mr_with_commits('feature', @commits, @user)
end
it { @merge_request.notes.should be_empty }
it { @fork_merge_request.notes.should be_empty }
end
context 'push to fork repo source branch' do
before do
@fork_project.comment_mr_with_commits('master', @commits, @user)
end
it { @merge_request.notes.should be_empty }
it { @fork_merge_request.notes.should_not be_empty }
end
context 'push to fork repo target branch' do
before do
@fork_project.comment_mr_with_commits('feature', @commits, @user)
end
it { @merge_request.notes.should be_empty }
it { @fork_merge_request.notes.should be_empty }
end
end
describe :find_with_namespace do
context 'with namespace' do
before do
......
require_relative '../../app/models/project_services/slack_message'
require 'spec_helper'
describe SlackMessage do
subject { SlackMessage.new(args) }
......@@ -26,11 +26,11 @@ describe SlackMessage do
it 'returns a message regarding pushes' do
subject.pretext.should ==
'user_name pushed to branch <url/commits/master|master> of ' <<
'user_name pushed to branch <url/commits/master|master> of '\
'<url|project_name> (<url/compare/before...after|Compare changes>)'
subject.attachments.should == [
{
text: "<url1|abcdefghi>: message1 - author1\n" <<
text: "<url1|abcdefghi>: message1 - author1\n"\
"<url2|123456789>: message2 - author2",
color: color,
}
......@@ -45,7 +45,7 @@ describe SlackMessage do
it 'returns a message regarding a new branch' do
subject.pretext.should ==
'user_name pushed new branch <url/commits/master|master> to ' <<
'user_name pushed new branch <url/commits/master|master> to '\
'<url|project_name>'
subject.attachments.should be_empty
end
......
......@@ -31,71 +31,27 @@ describe SlackService do
end
describe "Execute" do
let(:slack) { SlackService.new }
let(:slack_service) { SlackService.new }
let(:user) { create(:user) }
let(:slack) { SlackService.new }
let(:user) { create(:user) }
let(:project) { create(:project) }
let(:sample_data) { GitPushService.new.sample_data(project, user) }
let(:webhook) { 'https://gitlabhq.slack.com/services/hooks?token=cdIj4r4LfXUOySDUjp0tk3OI' }
let(:new_webhook) { 'https://hooks.gitlabhq.slack.com/services/cdIj4r4LfXUOySDUjp0tk3OI' }
let(:api_url) {
'https://gitlabhq.slack.com/services/hooks/incoming-webhook?token=cdIj4r4LfXUOySDUjp0tk3OI'
}
let(:webhook_url) { 'https://hooks.slack.com/services/SVRWFV0VVAR97N/B02R25XN3/ZBqu7xMupaEEICInN685' }
before do
slack.stub(
project: project,
project_id: project.id,
service_hook: true,
webhook: webhook
webhook: webhook_url
)
WebMock.stub_request(:post, api_url)
WebMock.stub_request(:post, webhook_url)
end
it "should call Slack API" do
slack.execute(sample_data)
WebMock.should have_requested(:post, api_url).once
end
context 'with new webhook syntax' do
before do
slack_service.stub(
project: project,
project_id: project.id,
service_hook: true,
webhook: new_webhook
)
WebMock.stub_request(:post, api_url)
end
it "should call Slack API" do
slack_service.execute(sample_data)
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
WebMock.should have_requested(:post, webhook_url).once
end
end
end
......@@ -287,6 +287,20 @@ describe User do
end
end
describe '.by_login' do
let(:username) { 'John' }
let!(:user) { create(:user, username: username) }
it 'should get the correct user' do
expect(User.by_login(user.email.upcase)).to eq user
expect(User.by_login(user.email)).to eq user
expect(User.by_login(username.downcase)).to eq user
expect(User.by_login(username)).to eq user
expect(User.by_login(nil)).to be_nil
expect(User.by_login('')).to be_nil
end
end
describe 'all_ssh_keys' do
it { should have_many(:keys).dependent(:destroy) }
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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